opencv之cv::Mat遍历

opencv之cv::image遍历

访问cv::image元素的方法:

  • 使用at成员函数
  • 使用ptr指针访问
  • 使用迭代器iterator

方式1: at(i, j)访问

这种方式在Debug模式下的访问速度是最慢的,但是在Release模式下的访问速度也是相当快的,和其他方式相近。

  • 单通道遍历(灰度图像)
cv::Mat image(100 , 100 , CV_8UC1);  
int rows = image.rows;
int cols = image.cols;

for (int i=0; i<rows ; i++)  
{  
    for (int j=0; j<cols ; j++)  
    {  
        image.at<uchar>(i,j) = 20;  
    }  
}
  • 多通道遍历(彩色图像)
cv::Mat image(100 , 100 , CV_8UC3);  
int rows = image.rows;
int cols = image.cols;

for (int i=0; i<rows ; i++)  
{  
    for (int j=0; j<cols ; j++)  
    {  
       image.at<cv::Vec3b>(i,j)[0]= 20;  // B 通道
       image.at<cv::Vec3b>(i,j)[1]= 20;  // G 通道
       image.at<cv::Vec3b>(i,j)[2]= 20;  // R 通道
    }  
}  

注:灰度图像元素类型为<uchar>, 彩色图像元素类型为<cv::Vec3b>

注:image.at<>(y, x)

注:这种方式会检查访问是否会溢出。

方式2: ptr(i) [j] 方式

这种方式是最有效的方式, 可以使用iscontinue()函数来提高遍历的速度。

cv::image image = cv::imread("xx.png", cv::IMREAD_COLOR);

int channels = image.channels;
int rows = image.rows;
int cols = image.cols * channels;

if (image.isContinuous())
  {
    cols *= rows;
    rows = 1;
  }

int i, j;
uchar* p;
for (i = 0; i < rows; ++i)
{
  p = image.ptr<uchar>(i);
    for (j = 0; j < cols; ++j)
    {
       std::cout << int(p[j]) << " ";
    }
}

注: image.ptr<>(i)返回第i行首元素的指针。

方式3:iterator方式

  • 单通道遍历(灰度图像)
cv::Mat image(100 , 100 , CV_8UC1);  

for (auto it = image.begin<uchar>(); it != image.end<uchar>(); ++it)
{
    std::cout << int((*it)) << " ";
}
  • 多通道遍历(彩色图像)
cv::Mat image(100 , 100 , CV_8UC3);  

for (auto it = image.begin<cv::Vec3b>(); it != image.end<cv::Vec3b>(); ++it)
{
    std::cout << int((*it)[0]) << " " << int((*it)[1]) << " " << int((*it)[2]) << std::endl;
}

转载于:https://www.cnblogs.com/ChrisCoder/p/10083755.html

<think>我们正在解决如何在C++ OpenCV中找到cv::Mat矩阵的最大值或最小值的问题。 根据OpenCV文档,我们可以使用以下函数: 1. cv::minMaxLoc - 用于单通道矩阵(或特定通道) 2. 对于多通道矩阵,可能需要分离通道或使用其他方法 步骤: 1. 检查矩阵是否为空 2. 确定矩阵的通道数和深度(数据类型) 3. 根据通道数选择处理方法: 单通道:直接使用minMaxLoc 多通道:可以分别对每个通道求极值,或者将多通道矩阵重新塑造成单通道(但这样会改变结构,通常我们更关心每个通道的极值) 注意:minMaxLoc只能处理单通道,所以多通道矩阵需要分通道处理。 另外,如果矩阵有多个相同的最值位置,minMaxLoc默认返回第一个出现的位置。如果需要所有位置,则需要遍历矩阵。 我们将提供两种方法: 方法1:使用minMaxLoc(单通道) 方法2:处理多通道矩阵(分别对每个通道求极值) 同时,我们也可以使用cv::reduce或cv::min/max函数来求每行或每列的极值,但这里我们关注全局极值。 代码示例:</think># 在 C++ OpenCV 中查找 cv::Mat 矩阵的最大值和最小值 在 OpenCV 中查找矩阵的最大值和最小值是常见的图像处理任务,可以使用 `cv::minMaxLoc()` 函数高效实现。该函数可以处理单通道和多通道矩阵,并返回极值及其位置。 ## 核心函数cv::minMaxLoc() ```cpp void minMaxLoc(InputArray src, double* minVal, double* maxVal = 0, Point* minLoc = 0, Point* maxLoc = 0, InputArray mask = noArray()); ``` 参数说明: - `src`:输入矩阵(单通道或多通道) - `minVal`:返回的最小值指针 - `maxVal`:返回的最大值指针 - `minLoc`:返回的最小值位置指针(仅单通道有效) - `maxLoc`:返回的最大值位置指针(仅单通道有效) - `mask`:可选掩码矩阵 ## 完整代码实现 ### 单通道矩阵示例 ```cpp #include <opencv2/opencv.hpp> #include <iostream> int main() { // 创建单通道矩阵 cv::Mat mat = (cv::Mat_<uchar>(3, 3) << 10, 20, 30, 40, 50, 60, 70, 80, 90); double minVal, maxVal; cv::Point minLoc, maxLoc; // 查找最小值和最大值及其位置 cv::minMaxLoc(mat, &minVal, &maxVal, &minLoc, &maxLoc); std::cout << "单通道矩阵:\n" << mat << "\n\n"; std::cout << "最小值: " << minVal << " 位置: (" << minLoc.x << ", " << minLoc.y << ")\n"; std::cout << "最大值: " << maxVal << " 位置: (" << maxLoc.x << ", " << maxLoc.y << ")\n"; return 0; } ``` ### 多通道矩阵(如 RGB 图像)示例 ```cpp #include <opencv2/opencv.hpp> #include <iostream> int main() { // 创建多通道矩阵(3通道) cv::Mat mat(3, 3, CV_8UC3); mat.forEach<cv::Vec3b>([](cv::Vec3b& pixel, const int* position) { pixel[0] = position[0] * 30; // 蓝色通道 pixel[1] = position[1] * 30; // 绿色通道 pixel[2] = position[0] + position[1] * 10; // 红色通道 }); std::cout << "多通道矩阵:\n" << mat << "\n\n"; // 分离通道处理 std::vector<cv::Mat> channels; cv::split(mat, channels); for (int i = 0; i < channels.size(); i++) { double minVal, maxVal; cv::Point minLoc, maxLoc; cv::minMaxLoc(channels[i], &minVal, &maxVal, &minLoc, &maxLoc); std::cout << "通道 " << i << ":\n"; std::cout << " 最小值: " << minVal << " 位置: (" << minLoc.x << ", " << minLoc.y << ")\n"; std::cout << " 最大值: " << maxVal << " 位置: (" << maxLoc.x << ", " << maxLoc.y << ")\n"; } return 0; } ``` ## 关键注意事项 1. **通道限制**: - `minLoc` 和 `maxLoc` 参数仅适用于**单通道**矩阵 - 对于多通道矩阵,需要先使用 `cv::split()` 分离通道再处理 2. **数据类型兼容性**: - 函数支持所有数值类型(`CV_8U`, `CV_32F` 等) - 对于浮点矩阵,位置信息仍以整数坐标返回 3. **掩码操作**: ```cpp cv::Mat mask = (mat > 50); // 创建大于50的掩码 cv::minMaxLoc(mat, &minVal, &maxVal, &minLoc, &maxLoc, mask); ``` 4. **仅获取值(忽略位置)**: ```cpp double min, max; cv::minMaxLoc(mat, &min, &max); ``` 5. **性能优化**: - 对于大型矩阵,处理前可降采样 - 使用 `cv::reduce()` 进行行/列级统计 ## 数学原理 `cv::minMaxLoc()` 函数高效实现的数学基础是分治策略: $$\text{minVal} = \min_{i,j} \text{src}(i,j)$$ $$\text{maxVal} = \max_{i,j} \text{src}(i,j)$$ 其中 $(i,j)$ 表示矩阵中的位置坐标。对于 $m \times n$ 矩阵,算法时间复杂度为 $O(mn)$[^4]。 ## 应用场景 1. 图像对比度分析 2. 特征点检测(如寻找最亮点) 3. 直方图均衡化的预处理 4. 图像二值化的阈值确定 5. 异常值检测
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值