OpenCV1.X的函数库一直都是基于C接口构建的,其中一直作为图片存储结构的IplImage可以说是当时的大哥大。
但是其有一个非常明显的缺点,那也是C语言中无法避免的问题—那就是内存需要手动释放。当工程越来越大时,我们就会逐渐纠结于内存管理的问题,这就有点舍本逐末了。
然而OpenCV1.X还是有非常明显的优势的,那也还是因为其是完全由C语言实现的库,完美支持大多数嵌入式开发系统,这是C++接口所不能做的。当然,随着时代的发展,嵌入式系统也都逐渐支持了C++,OpenCV1.X的这一优势正在逐渐减弱。
Mat是一个类,由两个数据部分组成:矩阵头和矩阵存储区(指针指向)。
因为类的封装,类的实例化可以自动分配内存空间,而销毁时则会自动释放矩阵内存区。自动化的内存管理,让大型工程开发更加容易。
同时其中封装的矩阵的一些操作,使得这个类功能十分的强大。可以这么说,如果你不会用Mat,那么你还没有领略到OpenCV真正的美!!!
混合标志:int flags;
矩阵维数:intdims;
矩阵行列数:int rows, cols;
指向矩阵存储区的指针:uchar* data;
矩阵每一维步长:MStep step;
图像最小单元:像素
通道数表示像素表示的分量数
深度表示分量数据存储类型
常用图像构造之一:Mat(int rows, int cols, int type);
rows为行数,cols为列数,type为图片类型(如CV_8UC1)
常用图像构造之二:Mat(Size size, int type);
size为图片尺寸, type为图片类型(如CV_8UC1)
常用图像构造之三:Mat(Size size, int type, void* data, size_t step=AUTO_STEP);
size为图片尺寸, type为图片类型,data为指向矩阵存储区的指针
常用图像拷贝之一:Mat& operator = (const Mat& m);(软拷贝)
常用图像拷贝之二: Mat(const Mat& m);(软拷贝)
常用图像拷贝之三:void copyTo( OutputArray m ) const;(硬拷贝)
常用图像拷贝之四: Mat clone() const;(硬拷贝)
查询矩阵是否为空:bool empty() const;
查询矩阵类型:int type() const;(如CV_8UC1)
查询矩阵深度(像素数据类型):int depth() const;
查询矩阵通道数(像素分量数):int channels() const;
查询矩阵数据总量:size_t total() const;
常用图像赋值之一:Mat& operator = (const Scalar& s);
常用图像赋值之二:Mat& setTo(InputArray value, InputArray mask=noArray());
value为所赋的值,可以是数字或颜色类;mask为掩膜。
常用图像赋值之三: static MatExpr zeros(int rows, int cols, int type);(单通道置零)
常用图像赋值之四: static MatExpr ones(int rows, int cols, int type);(单通道置一)
常用图像赋值之五: static MatExpr eye(int rows, int cols, int type);(对角线置一)
行操作之一:Mat row(int y) const;(返回第y行)
行操作之二:Mat rowRange(int startrow, int endrow) const;(返回数行)
列操作之一:Mat col(int x) const;(返回第x列)
列操作之二:Mat colRange(int startcol, int endcol) const;(返回数列)
矩阵转置:MatExpr t() const;
矩阵求逆:MatExpr inv(int method=DECOMP_LU) const;
矩阵乘法:MatExpr mul(InputArray m, double scale=1) const;
方法一:指针访问
uchar*data = image.ptr
uchar*data = image.data + i*image.cols;
……
方法二:迭代器iterator
方法三:动态地址计算
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
//打印Mat主要数据成员信息,分析图片内存关系
Mat src = Mat(300,300,CV_8UC3,Scalar(255,127,0));
Mat roi = src(Rect(100,100,200,200)); //设置感兴趣区域
cout << "flags of src: " << src.flags << "\tflags of roi: " << roi.flags << endl;
cout << "size of src:" << src.rows << "," << src.cols << "\t" << src.size() << endl;
cout << "size of roi:" << roi.rows << "," << roi.cols << "\t" << roi.size() << endl;
cout << "type of src:" << src.type() << "\ttype of roi:" << roi.type() << endl;
cout << "depth of src:" << src.depth() << "\tdepth of roi:" << roi.depth() << endl;
cout << "channels of src:" << src.channels() << "\tchannels of roi:" << roi.channels() << endl;
cout << "address of src: " << (int)src.data << "\t" << (int)src.datastart << "\t" << (int)src.dataend << "\t" << (int)src.datalimit << endl;
cout << "address of roi: " << (int)roi.data << "\t" << (int)roi.datastart << "\t" << (int)roi.dataend << "\t" << (int)roi.datalimit << endl;
cout << "address of (100,50) of src: " << (int)src.ptr(100,50) << "\taddress of (20,50) of roi: " << (int)roi.ptr(20,50) << endl << endl;
imshow("src",src);
imshow("roi",roi);
src.release();
waitKey(0);
destroyAllWindows();
//分析图片拷贝后内存关系
src = Mat(200,200,CV_8UC3,Scalar(255,0,0));
roi = src;
Mat newImage1(src);
Mat newImage2 = Mat(roi.size(),roi.type(),roi.data);
Mat newImage3 = src.clone();
Mat newImage4;
src.copyTo(newImage4);
cout << "address of src: " << (int)src.data << endl;
cout << "address of roi: " << (int)roi.data << endl;
cout << "address of newImage1: " << (int)newImage1.data << endl;
cout << "address of newImage2: " << (int)newImage2.data << endl;
cout << "address of newImage3: " << (int)newImage3.data << endl;
cout << "address of newImage4: " << (int)newImage4.data << endl << endl;
imshow("src",src);
src.release();
newImage3.release();
newImage4.release();
waitKey(0);
//矩阵赋值
src = Mat(3,3,CV_8UC1);
src = Scalar(255);
cout << "operator = :" << src << endl;
src.setTo(Scalar(127));
cout << "setTo:" << src << endl;
src = Mat::zeros(src.size(),src.type());
cout << "zeros:" << src << endl;
src = Mat::ones(src.size(),src.type());
cout << "ones:" << src << endl;
src = Mat::eye(src.size(),src.type());
cout << "eye:" << src << endl;
//矩阵计算
src = (Mat_(3,3) << 1,0,-1,2,0,-2,3,0,-3);
roi = (Mat_(3,3) << 1,0,-1,2,0,-2,3,0,-3);
cout << endl << "3*3:" << src << endl;
cout << "t:" << src.t() << endl;
cout << "inv:" << src.inv() << endl;
cout << "mul:" << src.mul(roi) << endl;
waitKey(0);
return 0;
}