OpenCV Mat矩阵(图像Mat)初始化及访问方法

一、Mat初始化
1.使用Mat构造函数

//方法一:
Mat M( 2, 2, CV_8UC3, Scalar(0,255,0) );//其实是2*6的矩阵,因为每个元素有3个通道。
Mat M1( 2, 2, CV_8UC1,Scalar(0) );//单通道
//方法二:
int sz[3] = {2, 2, 2};
Mat L( 3, sz, CV_8UC(1), Scalar::all(0) );

2.为已存在的IplImage指针创建信息头

IplImage* img = cvLoadImage("1.jpg",1);
Mat test(img);

3.利用create函数

M.create( 4, 4, CV_8UC2);//CV_8UC2里面的2表示2通道

4.采用Matlab形式的初始化方式

Mat E = Mat::eye(4, 4, CV_64F);
Mat O = Mat::ones(2, 3, CV_32F);
Mat Z = Mat::zeros(3, 3, CV_8UC1);

5.Mat矩阵比较小时,学会直接赋值的方法,即用Mat_

Mat C =(Mat_(3,3)<<0,-1,0,-1,5,-1,0,-1,0);//直接赋初始值的方法

6.使用数组或指针初始化

Mat (int rows, int cols, int type, void *data, size_t step=AUTO_STEP)
Mat (Size size, int type, void *data, size_t step=AUTO_STEP)
example:
int a[2][3] = { 1, 2, 3, 4, 5, 6};
Mat m1(2,3,CV_32S,a);   //float 对应的是CV_32F,double对应的是CV_64F
cout << m1 << endl;

参考链接1

二、Mat访问

Mat和Matlab里的数组格式有点像,但一般是二维向量,如果是灰度图,一般存放"uchar"类型;如果是RGB彩色图,存放"Vec3b"类型。首先先看看图像的是怎么存储的。

单通道图像

OpenCV Mat矩阵(图像Mat)初始化及访问方法_第1张图片

多通道图像
OpenCV Mat矩阵(图像Mat)初始化及访问方法_第2张图片

单通道灰度图数据存放格式:
OpenCV Mat矩阵(图像Mat)初始化及访问方法_第3张图片
多通道的图像中,每列并列存放通道数量的子列,如RGB三通道彩色图:
OpenCV Mat矩阵(图像Mat)初始化及访问方法_第4张图片

opencv中,由于使用Mat.at访问数据时,必须正确填写相应的数据类型,因此必须弄清楚opencv中的数据类型与我们常用
数据类型一一对应关系。

Mat_---------CV_8U
Mat-----------CV_8S
Nat_---------CV_16S
Mat_--------CV_16U
Mat_-----------CV_32S
Mat_----------CV_32F
Mat_--------CV_64F
下面主要记录三种常见的访问Mat的方式:1.at访问 2.ptr访问 3.data访问
Mat中不管是以at访问还是ptr访问,都是行优先 ,先Y轴后X轴(即先行后列)

//方法1:
t = (double)getTickCount();
	Mat img1(1000, 1000, CV_32F);
	
	for (int i=0; i<1000; i++)
	{
		for (int j=0; j<1000; j++)
		{
			img1.at(i,j) = 3.2f;
		}
	}
	t = (double)getTickCount() - t;
	printf("in %gms\n", t*1000/getTickFrequency());
	//***方法2************************************************************
	t = (double)getTickCount();
	Mat img2(1000, 1000, CV_32F);

	for (int i=0; i<1000; i++)
	{
		for (int j=0; j<1000; j++)
		{
			img2.ptr(i)[j] = 3.2f;
		}
	}
	t = (double)getTickCount() - t;
	printf("in %gms\n", t*1000/getTickFrequency());
	//***方法3************************************************************
	t = (double)getTickCount();
	Mat img3(1000, 1000, CV_32F);
	float* pData = (float*)img3.data;

	for (int i=0; i<1000; i++)
	{
		for (int j=0; j<1000; j++)
		{
			*(pData) = 3.2f;
			pData++;
		}
	}
	t = (double)getTickCount() - t;
	printf("in %gms\n", t*1000/getTickFrequency());
	//***方法3************************************************************
	t = (double)getTickCount();
	Mat img4(1000, 1000, CV_32F);

	for (int i=0; i<1000; i++)
	{
		for (int j=0; j<1000; j++)
		{
			((float*)img3.data)[i*1000+j] = 3.2f;
		}
	}
	t = (double)getTickCount() - t;
	printf("in %gms\n", t*1000/getTickFrequency());

对比几种方法,速度测试如下:

测试结果
  Debug Release
方法1 139.06ms 2.51ms
方法2 66.28ms 2.50ms
方法3-1 4.95ms 2.28ms
方法3-2 5.11ms 1.37ms
可以看出在debug版本下测试,不同访问方法差别比较大,Release下还好,而且也可以采用和指针结合的方式来增加效率,比如
/*********加强版********/
	t = (double)getTickCount();
	Mat img5(1000, 1000, CV_32F);
	float *pData1;
	for (int i=0; i<1000; i++) 
	{ 
		pData1=img5.ptr(i);
		for (int j=0; j<1000; j++) 
		{ 
			pData1[j] = 3.2f; 
		} 
	} 
	t = (double)getTickCount() - t;
	printf("in %gms\n", t*1000/getTickFrequency());
时间有限,总结不到位,贴几个参考博客,大家自行参阅:
  Debug Release
加强版 5.74ms 2.43ms

参考链接2
参考链接3
参考链接4
参考链接5

你可能感兴趣的:(opencv)