图像识别与处理之Opencv——Mat_类与Mat 类的内存管理
Mat_类
Mat_类是对 Mat 类的一个包装,其定义如下
点击查看代码
template<typename _Tp> class Mat_ : public Mat
{
public:
//只定义了几个方法
//没有定义新的属性
};
点击查看代码
Mat M(600, 800, CV_8UC1);
for( int i = 0; i < M.rows; ++i)
{
uchar * p = M.ptr<uchar>(i);
for( int j = 0; j < M.cols; ++j )
{
double d1 = (double) ((i+j)%255);
M.at<uchar>(i,j) = d1;
double d2 = M.at<double>(i,j);//此行有错
}
}
点击查看代码
#include<iostream>
#include"opencv2/opencv.hpp"
#include<stdio.h>
using namespace std;
using namespace cv;
int main()
{
Mat M(600, 800, CV_8UC1);
for (int i = 0; i < M.rows; ++i)
{
//获取指针时需要指定类型
uchar* p = M.ptr<uchar>(i);
for (int j = 0; j < M.cols; ++j)
{
double d1 = (double)((i + j) % 255);
//用at()读写像素时,需要指定类型
M.at<uchar>(i, j) = d1;
//下面代码错误,应该使用at<uchar>()
//但编译时不会提醒错误
//运行结果不正确,d2不等于d1
double d2 = M.at<double>(i, j);
cout << "d1=" << d1 << endl;
cout << "d2=" << d2 << endl;
}
}
system("pause");
return 0;
}
点击查看代码
#include<iostream>
#include"opencv2/opencv.hpp"
#include<stdio.h>
using namespace std;
using namespace cv;
int main()
{
Mat M(600, 800, CV_8UC1);
//在变量声明时指定矩阵元素类型
Mat_<uchar>M1 = (Mat_<uchar>&)M;
for (int i = 0; i < M1.rows; ++i)
{
//不需指定元素类型,语句简洁
uchar* p = M1.ptr(i);
for (int j = 0; j < M1.cols; ++j)
{
double d1 = (double)((i + j) % 255);
//直接使用Matlab风格的矩阵元素读写,简洁
M1(i, j) = d1;
double d2 = M1(i, j);
cout << "d1=" << d1 << endl;
cout << "d2=" << d2 << endl;
}
}
system("pause");
return 0;
}
Mat是一个类,由两个数据部分组成:矩阵头(包含矩阵尺寸,存储方法,存储地址等信息)和一个指向存储所有像素值的指针,如下图所示。矩阵头
的尺寸是常数值,但矩阵本身的尺寸会依透骨香的不同而不同,通常比矩阵头的尺寸大数个数量级。复制矩阵数据往往花费较多时间,因此除非有
必要,不要复制大的矩阵。
为了解决矩阵数据的传递,OpenCV使用了引用计数机制,其思路是让每个Mat对象有自己的矩阵头信息,但多个Mat对象可以共享同一个矩阵数据。
让矩阵指针指向同一地址而实现这一目的。很多函数以及很多操作(如函数参数传值)只复制矩阵头信息,而不复制矩阵数据。
前面文提到过,有很多种方法创建Mat类。如果Mat类自己申请数据空间,那么该类会多申请4个字节,多出的4个字节存储数据被引用的次数。
引用次数存储于数据空间的后面,refcount指向这个位置,如下图所示。当计数等于0时,则释放该空间。