前言
Mat(图像数据结构体)代替了CvMat和IPIImage,并将功能模块化。
Mat它由两个数据部分组成:矩阵头(包含矩阵尺寸,存储方法,存储地址等信息)和一个指向存储所有像素值的矩阵(根据所选存储方法的不同矩阵可以是不同的维数)的指针。
一 Mat 初始化
1.构造函数初始化
CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number]
首先要定义其尺寸,即行数和列数,然后,需要指定存储元素的数据类型以及每个矩阵点的通道数。Scalar 是个short型vector。指定这个能够使用指定的定制化值来初始化矩阵。例如以下函数:
Mat (int rows, int cols, int type)
Mat (int rows, int cols, int type, const Scalar &s)
2.Create()function:函数
M.create(4,4,CV_8UC(2));
3.MATLAB形式的初始化方式:zeros(), ones(), :eyes() 。
使用以下方式指定尺寸和数据类型:
Mat E = Mat::eye(4, 4, CV_64F);
cout << "E = " << endl << " " << E << endl << endl;
Mat O = Mat::ones(2, 2, CV_32F);
cout << "O = " << endl << " " << O << endl << endl;
Mat Z = Mat::zeros(3,3, CV_8UC1);
cout << "Z = " << endl << " " << Z << endl << endl;
*.Mat c = (Mat_<double>(3,3)<<0,1,2,3,4,5,6,7,8);
*.随机填充randu()
Mat R = Mat(3, 2, CV_8UC3);
randu(R, Scalar::all(0), Scalar::all(255));
二 Mat 中像素的读取(矩阵元素读取)
很多时候,我们需要读取某个像素值,或者设置某个像素值;在更多的时候,我们需要对整个图像里的所有像素进行遍历。OpenCV提供了多种方法来实现图像的遍历。
函数at()来实现读去矩阵中的某个像素,或者对某个像素进行赋值操作。下面两行代码演示了at()函数的使用方法。
If matrix is of type CV_8U then use Mat.at<uchar>(y,x).
If matrix is of type CV_8S then use Mat.at<schar>(y,x).
If matrix is of type CV_16U then use Mat.at<ushort>(y,x).
If matrix is of type CV_16S then use Mat.at<short>(y,x).
If matrix is of type CV_32S then use Mat.at<int>(y,x).
If matrix is of type CV_32F then use Mat.at<float>(y,x).
If matrix is of type CV_64F then use Mat.at<double>(y,x).
例: uchar value = grayim.at(i,j);//读出第i行第j列像素值
grayim.at(i,j)=128; //将第i行第j列像素值设置为128
当然Mat也提供迭代器使用去修改像素的值
MatIterator_<uchar> grayit,grayend;
for( grayit = grayim.begin<uchar>(), grayend = grayim.end<uchar>(); grayit != grayend; ++grayit)
MatIterator_<Vec3b> grayit,grayend;
for( grayit = grayim.begin<Vec3b>(), grayend = grayim.end<Vec3b>(); grayit != grayend; ++grayit)
最高效的遍历像素的方法就是使用指针了。
Vec3b *p = grayim.ptr<Vec3b>(i)
uchar *p = grayim.ptr<uchar>(i);
三 Mat 表达式
其实之前再看这个像素提取的时候有点懵,如果先介绍这个Mat表达式就好了,其实它提供的也就是一些矩阵的操作,加减乘除之类,至于像素提取,那就是将图像矩阵化,按照矩阵计算方法提取某行,某列,某个子矩阵。
在介绍Mat表达式的时候需要介绍一个另外的函数出cv::print()
po:其实OC这个语言兼容C/C++,使用printf,cout函数是没有问题的,在这里就用OpenCV的Print方法,他这里提供打印它的数据结构。
下面给出Mat表达式所支持的运算。下面的列表中使用A和B表示Mat类型的对象,使用s表示Scalar对象,alpha表示double值。
加法,减法,取负:A+B,A-B,A+s,A-s,s+A,s-A,-A
缩放取值范围:A*alpha
矩阵对应元素的乘法和除法:A.mul(B),A/B,alpha/A
矩阵乘法:A*B(注意此处是矩阵乘法,而不是矩阵对应元素相乘)
矩阵转置:A.t()
矩阵求逆和求伪逆:A.inv()
矩阵比较运算:A cmpop B,A cmpop alpha,alpha cmpop A。此处cmpop可以是>,>=,==,!=,<=,<。如果条件成立,则结果矩阵(8U类型矩
阵)的对应元素被置为255;否则置0。
矩阵位逻辑运算:A logicop B,A logicop s,s logicop A,~A,此处logicop可以是&,|和^。
34
矩阵对应元素的最大值和最小值:min(A, B),min(A, alpha),max(A, B),max(A, alpha)。
矩阵中元素的绝对值:abs(A)
叉积和点积:A.cross(B),A.dot(B)
总结
OpenCV函数中输出图像的内存分配是自动完成的(如果不特别指定的话)。
使用OpenCV的C++接口时不需要考虑内存释放问题。
赋值运算符和拷贝构造函数( ctor )只拷贝信息头。
使用函数 clone() 或者 copyTo() 来拷贝一副图像的矩阵。