OpenCv cv::Mat类用法

本文深入探讨了OpenCV中Mat类的高效操作方法,通过实验对比了不同方式在处理大规模数据时的性能差异,并给出了推荐的操作策略。重点介绍了如何优化访问和修改矩阵元素的过程,同时附上了具体代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

penCv cv::Mat类用法1

1、使用准备:

using  namespace  cv;

2、Mat的声明

Mat m=Mat(rows, cols, type);

Mat m=Mat(Size(width,height), type);

Mat A=Mat(3,4,CV_32FC1);
Mat B=Mat(4,3,CV_32FC1);

3、Mat赋值

vector<Point3f>v;//suppose it is already full

Mat m1=Mat(v,true);//boolean value true is necessary in order to copy data from v to m1

CvMat *p1=====??

Mat m2=Mat(p1);

4、Mat之间运算

MatC=2*A*B;

Mat C=C.inv();//Now C is its own inverse matrix

Mat D=A.t();//D is the transposed matrix of A

Mat a=Mat(4,1, CV_32FC3);//a is 4x1, 3 channels

Mat b=a.reshape(1);//b is 4x3, 1 channel

5、单通道Mat元素读写

Mat a=Mat(4,3, CV_32FC1);

floatelem_a=a.at<float>(i,j);//access element aij, with i from 0 to rows-1 and j from 0 to cols-1

Point p=Point(x,y);

floatelem_a=a.at<float>(p);//Warning: y ranges from 0 to rows-1 and x from 0 to cols-1

6、多通道Mat元素读写

template<typename _Tp> _Tp& at(int y,int x);                // cxcore.hpp (868)
template<typename _Tp>const _Tp& at(int y,int x)const;    // cxcore.hpp (870)
template<typename _Tp> _Tp& at(Point pt); // cxcore.hpp (869)
template<typename _Tp>const _Tp& at(Point pt)const;        // cxcore.hpp (871)
// defineded in cxmat.hpp (454-468)
typedefVec<float,2>Vec2f;// cxcore.hpp (254)

// we can access the element like this :
Mat m(Size(3,3), CV_32FC2 );
Vec2f& elem = m.at<Vec2f>( row , col );// or m.at<Vec2f>( Point(col,row) );
elem[0]=1212.0f;
elem[1]=326.0f;
float c1 = m.at<Vec2f>( row , col )[0];// or m.at<Vec2f>( Point(col,row) );
float c2 = m.at<Vec2f>( row , col )[1];
m.at<Vec2f>( row, col )[0]=1986.0f;
m.at<Vec2f>( row, col )[1]=326.0f;

 

7.选取Mat上指定区域方法

  Mat src; Rect rect;

  Mat dst = src(rect); 或者Mat dst(src,rect);

 

注意:cv::Mat A;

A.row(i) = A.row(j); // 错误

A.row(i) = A.row(j) + 0; // 正确


OpenCV cv::Mat类操作

首先还是要感谢箫鸣朋友在我 《OpenCV学习笔记(四十)——再谈OpenCV数据结构Mat详解》的留言,告诉我 M.at<float>(3, 3)在Debug模式下运行缓慢,推荐我使用M.ptr<float>(i)此类方法。这不禁勾起了我测试一下的冲动。下面就为大家奉上我的测试结果。

我这里测试了三种操作Mat数据的办法,套用流行词,普通青年,文艺青年,为啥第三种我不叫2b青年,大家慢慢往后看咯。

普通青年的操作的办法通常是M.at<float>(i, j)

文艺青年一般会走路线M.ptr<float>( i )[ j ]

暴力青年通常直接强制使用我第40讲提到的M.data这个指针

实验代码如下:

  1. (double)getTickCount();
  2. Mat img1(1000, 1000, CV_32F);
  3. for (int i=0; i<1000; i++)
  4. {
  5. for (int j=0; j<1000; j++)
  6. {
  7. img1.at<float>(i,j) 3.2f;
  8. }
  9. }
  10. (double)getTickCount() t;
  11. printf("in %gms\n", t*1000/getTickFrequency());
  12. /
  13. (double)getTickCount();
  14. Mat img5(1000, 1000, CV_32F);
  15. float *pData1;
  16. for (int i=0; i<1000; i++)
  17. {
  18. pData1=img5.ptr<float>(i);
  19. for (int j=0; j<1000; j++)
  20. {
  21. pData1[j] 3.2f;
  22. }
  23. }
  24. (double)getTickCount() t;
  25. printf("in %gms\n", t*1000/getTickFrequency());
  26. (double)getTickCount();
  27. Mat img6(1000, 1000, CV_32F);
  28. float *pData2;
  29. Size size=img6.size();
  30. if(img2.isContinuous())
  31. {
  32. size.width size.width*size.height;
  33. size.height 1;
  34. }
  35. size.width*=img2.channels();
  36. for(int i=0; i<size.height; i++)
  37. {
  38. pData2 img6.ptr<float>(i);
  39. for(int j=0; j<size.width; j++)
  40. {
  41. pData2[j] saturate_cast<float>(3.2f);
  42. }
  43. }
  44. (double)getTickCount() t;
  45. printf("in %gms\n", t*1000/getTickFrequency());

测试结果: 













DebugRelease
加强版文艺青年5.74ms2.43ms
终极版文艺青年40.12ms2.34ms
我的测试结果感觉这两种方案只是锦上添花的效果,也使大家的操作有了更多的选择,但感觉在速度上并没有数量级的提升,再次感谢箫铭对我blog的支持。后来箫铭说saturate_cast才把速度降下来,我很同意,就不贴上去测试结果了。但我查看资料了解了一下 saturate_cast的作用。可以看成是类型的强制转换,比如对于saturate_cast<uchar>来说,就是把数据转换成8bit的0~255区间,负值变成0,大于255的变成255。如果是浮点型的数据,变成round最近的整数,还是很有用处的函数,推荐大家在需要的时候尝试。

<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、付费专栏及课程。

余额充值