当前位置:   article > 正文

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

opencv mat初始化
转载、参考、引用请注明出处。
文章地址:https://blog.csdn.net/duiwangxiaomi/article/details/93075571?spm=1001.2014.3001.5501
  • 1
  • 2

一、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) );
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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

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

3.利用create函数

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

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);
  • 1
  • 2
  • 3

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

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

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
  • 2
  • 3
  • 4
  • 5
  • 6

参考链接1

二、Mat访问

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

单通道图像

在这里插入图片描述

多通道图像

在这里插入图片描述

单通道灰度图数据存放格式:

在这里插入图片描述

多通道的图像中,每列并列存放通道数量的子列,如RGB三通道彩色图:

在这里插入图片描述

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

Mat_<uchar>---------CV_8U
Mat_<char>-----------CV_8S
Nat_<short>---------CV_16S
Mat_<ushort>--------CV_16U
Mat_<int>-----------CV_32S
Mat_<float>----------CV_32F
Mat_<double>--------CV_64F
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

CV_8U 8位无符号整数 (0…..255)
CV_8S 8 位符号整数 (-128…..127)
CV_16U 16 位无符号整数 (0……65535)
CV_16S 16 位符号整数 (-32768…..32767)
CV_32S 32 位符号整数 (-2147483648……2147483647)
CV_32F 32 位浮点数 (-FLT_MAX ………FLT_MAX,INF,NAN)
CV_64F 64 位浮点数 (-DBL_MAX ……….DBL_MAX,INF,NAN)

下面主要记录三种常见的访问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<float>(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<float>(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());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

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

测试结果
 DebugRelease
方法1139.06ms2.51ms
方法266.28ms2.50ms
方法3-14.95ms2.28ms
方法3-25.11ms1.37ms
可以看出在debug版本下测试,不同访问方法差别比较大,Release下还好,而且也可以采用和指针结合的方式来增加效率,比如
/*********加强版********/
	t = (double)getTickCount();
	Mat img5(1000, 1000, CV_32F);
	float *pData1;
	for (int i=0; i<1000; i++) 
	{ 
		pData1=img5.ptr<float>(i);
		for (int j=0; j<1000; j++) 
		{ 
			pData1[j] = 3.2f; 
		} 
	} 
	t = (double)getTickCount() - t;
	printf("in %gms\n", t*1000/getTickFrequency());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
 DebugRelease
加强版5.74ms2.43ms

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

多通道Mat访问
用at进行多通道访问,对应的数据类型如下:
typedef Vec<uchar, 2> Vec2b; //无符号双通道 CV_8U:0~255
typedef Vec<uchar, 3> Vec3b; //无符号3通道
typedef Vec<uchar, 4> Vec4b;
typedef Vec<short, 2> Vec2s; //short型双通道 CV_16S:-32768~32767
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;
typedef Vec<int, 2> Vec2i; //整型双通道 CV_32S:-2147483648~2147483647
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<float, 2> Vec2f; //浮点型双通道 CV_32F:1.1810-38~3.401038
typedef Vec<float, 3> Vec3f;
typedef Vec<float, 4> Vec4f;
typedef Vec<float, 6> Vec6f;
typedef Vec<double, 2> Vec2d; //double型双通道 CV_64F:2.2310-308~1.7910308
typedef Vec<double, 3> Vec3d;
typedef Vec<double, 4> Vec4d;
typedef Vec<double, 6> Vec6d;

示例程序,创建及访问双通道Mat

#include <opencv2/core/core.hpp>
#include <iostream>
 
using namespace std;
using namespace cv;
 
int main()
{
	int i, j;
	Mat dimg(3, 5, CV_16SC2,Scalar(-5,5));//构造一个3*5的short型双通道矩阵
       cout << "原矩阵" << endl << dimg << endl;
 	short int a=1,b=15;
	for (i = 0; i < dimg.rows; i++)
	{
		for (j = 0; j < dimg.cols; j++)
		{
			dimg.at<Vec2s>(i, j)[0] = a;//at<type>其中type由矩阵的类型确定
			dimg.at<Vec2s>(i, j)[1] = b;
		}
	}
 
	cout << "改变后矩阵" << endl << dimg << endl;
	system("pause");
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

参考链接6
参考链接7

欢迎大家点赞、收藏、评论,让更多的人看到哦~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/886846?site
推荐阅读
相关标签
  

闽ICP备14008679号