| 
 | 
 
对于新手学习opencv,了解Mat类是最基本的要求。为了方便大家学习,对Mat的用法做了一些总结,希望对各位opencv初学者有所帮助。总结大部分是基于例子来写的,感觉这样更容易理解。 
1. 创建 Mat  对象 
1.1 构造函数方法 
Mat M(3,2, CV_8UC3, Scalar(0,0,255)); 
第一行代码创建一个行数(高度)为 3,列数(宽度)为 2 的图像,图像元素是 8 位无符号整数类型,且有三个通道。图像的所有像素值被初始化为(0, 0,255)。 
常用的构造函数有: 
 Mat::Mat() 
无参数构造方法; 
 Mat::Mat(int rows, int cols, int type) 
创建行数为 rows,列数为 col,类型为 type 的图像; 
 Mat::Mat(Size size, int type) 
创建大小为 size,类型为 type 的图像; 
 Mat::Mat(int rows, int cols, int type, const Scalar& s) 
创建行数为 rows,列数为 col,类型为 type 的图像,并将所有元素初始 
化为值 s; 
 Mat::Mat(Size size, int type, const Scalar& s) 
创建大小为 size,类型为 type 的图像,并将所有元素初始化为值 s; 
 Mat::Mat(const Mat& m) 
将 m 赋值给新创建的对象, 此处不会对图像数据进行复制, m 和新对象共用图像数据; 
 Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP) 
创建行数为 rows,列数为 col,类型为 type 的图像,此构造函数不创建图像数据所需内存, 而是直接使用 data 所指内存, 图像的行步长由 step指定。 
 Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP) 
创建大小为 size,类型为 type 的图像,此构造函数不创建图像数据所需内存,而是直接使用 data 所指内存,图像的行步长由 step 指定。 
 Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange) 
创建的新图像为 m 的一部分,具体的范围由 rowRange 和 colRange 指定, 此构造函数也不进行图像数据的复制操作, 新图像与 m 共用图像数据; 
 Mat::Mat(const Mat& m, const Rect& roi) 
创建的新图像为 m 的一部分,具体的范围 roi 指定,此构造函数也不进行图像数据的复制操作,新图像与 m 共用图像数据。 
这些构造函数中, 很多都涉及到类型type。 type可以是CV_8UC1, CV_16SC1, …,CV_64FC4 等。里面的 8U 表示 8 位无符号整数,16S 表示 16 位有符号整数,64F表示 64 位浮点数(即 double 类型) ;C 后面的数表示通道数,例如 C1 表示一个通道的图像,C4 表示 4 个通道的图像,以此类推。 
1.2 create() 函数创建对象 
Mat M(2,2, CV_8UC3);//构造函数创建图像 
M.create(3,2, CV_8UC2);//释放内存重新创建图像 
2 像素值的读写 
很多时候, 我们需要读取某个像素值, 或者设置某个像素值; 在更多的时候,我们需要对整个图像里的所有像素进行遍历。OpenCV 提供了多种方法来实现图像的遍历。 
2.1 at() 函数 
uchar value = grayim.at<uchar>(i,j);//读出第 i 行第 j 列像素值 
grayim.at<uchar>(i,j)=128; //将第 i 行第 j 列像素值设置为 128 
下面是个简单的图像遍历程序 
#include <iostream> 
#include "opencv2/opencv.hpp" 
using namespace std; 
using namespace cv; 
int main(int argc, char* argv[]) 
{ 
Mat grayim(600, 800, CV_8UC1); 
Mat colorim(600, 800, CV_8UC3); 
//遍历所有像素,并设置像素值 
for( int i = 0; i < grayim.rows; ++i) 
for( int j = 0; j < grayim.cols; ++j ) 
grayim.at<uchar>(i,j) = (i+j)%255; 
//遍历所有像素,并设置像素值 
for( int i = 0; i < colorim.rows; ++i) 
for( int j = 0; j < colorim.cols; ++j ) 
{ 
Vec3b pixel; 
pixel[0] = i%255; //Blue 
pixel[1] = j%255; //Green 
pixel[2] = 0; //Red 
colorim.at<Vec3b>(i,j) = pixel; 
} 
//显示结果 
imshow("grayim", grayim); 
imshow("colorim", colorim); 
29 
waitKey(0); 
return 0; 
} 
2.2 使用迭代器 
#include <iostream> 
#include "opencv2/opencv.hpp" 
using namespace std; 
using namespace cv; 
int main(int argc, char* argv[]) 
{ 
Mat grayim(600, 800, CV_8UC1); 
Mat colorim(600, 800, CV_8UC3); 
//遍历所有像素,并设置像素值 
MatIterator_<uchar> grayit, grayend; 
30 
for(  grayit  =  grayim.begin<uchar>(),  grayend  = 
grayim.end<uchar>(); grayit != grayend; ++grayit) 
*grayit = rand()%255; 
//遍历所有像素,并设置像素值 
MatIterator_<Vec3b> colorit, colorend; 
for(  colorit  =  colorim.begin<Vec3b>(),  colorend  = 
colorim.end<Vec3b>(); colorit != colorend; ++colorit) 
{ 
(*colorit)[0] = rand()%255; //Blue 
(*colorit)[1] = rand()%255; //Green 
(*colorit)[2] = rand()%255; //Red 
} 
//显示结果 
imshow("grayim", grayim); 
imshow("colorim", colorim); 
waitKey(0); 
return 0; 
} 
3 从图像中抠出感兴趣的部分 
//创建宽度为 320,高度为 240 的 3 通道图像 
Mat img(Size(320,240),CV_8UC3); 
//roi 是表示 img 中 Rect(10,10,100,100)区域的对象 
Mat roi(img, Rect(10,10,100,100)); 
4 Mat之间的运算 
同样给出一个简单程序 
#include <iostream> 
#include "opencv2/opencv.hpp" 
using namespace std; 
using namespace cv; 
int main(int argc, char* argv[]) 
{ 
Mat A = Mat::eye(4,4,CV_32SC1); 
Mat B = A * 3 + 1; 
Mat C = B.diag(0) + B.col(1); 
cout << "A = " << A << endl << endl; 
cout << "B = " << B << endl << endl; 
cout << "C = " << C << endl << endl; 
cout << "C .* diag(B) = " << C.dot(B.diag(0)) << endl; 
return 0; 
} 
5. Mat和IplImage、cvMat之间的相互转换 
Mat img(Size(320, 240), CV_8UC3); 
... 
IplImage iplimg = img; //转为 IplImage 结构 
mycvOldFunc( & iplimg, ...);//对 iplimg 取地址 
CvMat cvimg = img; //转为 CvMat 结构 
IplImage * iplimg = cvLoadImage("lena.jpg"); 
Mat im(iplimg, true); 
 
 |   
 
 
 
 |