OpenCV Mat类
Mat类有两个部分:矩阵头和指向矩阵数据部分的指针
矩阵头中包含矩阵的尺寸、存储方法、地址和引用次数等,矩阵头的大小是一个常数。
由于矩阵数据较大,传递时只是传递矩阵头和数据指针,即共同指向同一块数据内存。除非深拷贝或移动,即clone或std::move。
cv::Mat src1 = cv::imread("d:/1.jpg"); //cv::imread会开辟内存Memory1,src1中的数据指针指向Memory1 cv::Mat src2 = src1; //src2中的数据指针指向Memory1 src1 = cv::imread("d:/2.jpg"); //开辟内存Memory2,src1中的数据指针指向Memory2。src2中的数据指针依然指向Memory1 cv::imshow("src1", src1); //2.jpg cv::imshow("src2", src2); //1.jpg //cv::Mat src3 = src1; //浅拷贝,指向同一内存 //cv::Mat src3 = src1.clone(); //clone会开辟内存 cv::Mat src3 = std::move(src1); //比clone效率高,内存所有权被转移而不是新开辟。即src3中的数据指针指向该内存,src1中的数据指针悬空 //因此,std::move使用要注意:src1的内存数据一定不会被再次使用(指针悬空,无法再操作原有数据了)。 src1=cv::imread("d:/3.jpg"); //src1中的数据指针不再悬空,指向新内存 cv::waitKey(0);
如果不理解,可以参考下述案例
int a = 10; //开辟内存Memory1 int *pA1 = &a; int *pA2 = pA1; //pA1、pA2都指向Memory1 std::cout << a << " " << *pA1 << " " << *pA2 << std::endl; //10 10 10 a = 11; std::cout << a << " " << *pA1 << " " << *pA2 << std::endl; //11 11 11 int b = 20; //开辟内存Memory2 pA1 = &b; //pA1指向Memory2,pA2依然指向Memory1 std::cout << a << " " << *pA1 << " " << *pA2 << std::endl; //11 20 11
其他参考
c++ 为什么std::move()没有窃取一个int值? _大数据知识库 (saoniuhuo.com)
【OpenCV】浅谈 Mat 类_opencv mat-CSDN博客
经典场景:踩坑,C++ Opencv中Mat对象作消息队列参数时候出现队列中数据完全一样的情况_c++ mat相等-CSDN博客
queue<Mat> videoframes; Mat frame; VideoCapture capture; capture.open("./data/output.mp4"); if (!capture.isOpened()) { return; } videoframes = queue<Mat>(); while (capture.read(frame)) { qDebug("add one frame"); videoframes.push(frame);//队列中所有元素都是最后进入的那一张 //videoframes.push(frame.clone()); //方法1 //videoframes.push(move(frame)); //方法2 }
Mat类的属性:
- rows 矩阵的行数
- cols 矩阵的列数
- dims 矩阵的维度,例如5*6矩阵是二维矩阵,则dims=2,三维矩阵dims=3.
- data uchar类型的指针,指向Mat数据矩阵的首地址。
Mat类的方法:
- size() 矩阵的大小,宽×高(列×行)
- channels() 矩阵元素拥有的通道数,例如常见的彩色图像,每一个像素由RGB三部分组成,则channels = 3
【参考】
https://www.cnblogs.com/faith0217/articles/4708877.html
【案例】
Mat kernel = (Mat_<char>(2, 3) << 0, -1, 0,-1, 5, -1); cout << kernel << endl; cout << kernel.rows << endl; cout << kernel.cols << endl; cout << kernel.size()<<endl; cout << kernel.channels() << endl; cout << kernel.dims << endl; waitKey(); return 0;