【VC++、OpenCV3.4】Mat对象

这节记录下图像加载或者读取后的内存对象Mat的相关知识。

包括:Mat对象和IplImage对象,Mat对象的使用,Mat定义数组。

1、Mat对象和IplImage对象:

IplImage对象:是从2001年OpenCV发布就一直存在的,是C语言风格的数据结构,需要开发者自己分配和管理内存,对大的程序来说,使用IplImage对象容易造成内存泄漏的问题。

Mat对象:OpenCV2.0以后引入的图像数据结构,自动分配内存,不存在内存泄漏的问题,是面向对象的数据结构。分成了两个部分,头部与数据部分

上一节中说道:

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

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

【VC++、OpenCV3.4】Mat对象_第1张图片

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

【VC++、OpenCV3.4】Mat对象_第2张图片

注意通道的顺序反转了:BGR。通常情况内存足够大的话图像的每一行是连续存放的,也就是在内存上图像的所有数据存放成一行,这中情况在访问时可以提供很大方便。可以用 isContinuous()函数来判断图像数组是否为连续的。

所以:应尽量避免使用IplImage对象,进行算法迁移的时候尽量将IplImage对象转换成Mat对象。

2、Mat对象构造函数和常用方法:

构造函数:

Mat();

Mat(int rows,int cols,int type);

Mat(Szie size,int type);

Mat(int rows,int cols,int type,const Scalar &s);

Mat(Size size,int type,const Scalar &s);

Mat(int ndims,const int* size,int type);

Mat(int ndims,const int* size,int type,const Scalar &s);

常用方法:

void copyTo(Mat mat);//完全复制一份

void convertTo(Mat dst,int type);//转换类型

Mat Clone();//完全复制一份

int channels();

int depth();

bool empty();

uchar * ptr(i=0);

3、Mat对象的使用

部分复制:一般情况下只会复制Mat对象的头和指针部分,不会复制数据部分。Mat A=imread(imageFile);

                                                                                                                             Mat B(A);//只复制

完全复制:如果想把Mat对象的头部和数据部分一起复制,可以通过如下两个API实现:Mat C=A.clone();

                                                                                                                                      或Mat D;A.copyTo(D);

4、Mat对象使用的四个要点:

输出图像的内存是自动分配的;

使用OpenCV的C++接口,不需要考虑内存泄漏的问题;

复制操作和拷贝构造函数只会复制头部分;

使用clone和copyTo两个函数实现数据的完全复制。

5、Mat对象的创建

Mat M(3, 3, CV_8UC3, Scalar(0, 0, 255));//前面两个3代表行和列。UC表示无符号,8代表位数,后面的3代表通道数

创建高维对象:

int sz[3] = { 2,2,2 };
Mat L(3, sz, CV_8UC1, Scalar::all(0));

Mat::create方法不想上面的可以直接赋值,需要单独写Scalar赋值:

Mat M;
M.create(4, 3, CV_8UC2);
M = Scalar(127, 127);

定义小数组:像是上一节的掩模mask

Mat kernel=(Mat_(3,3) <<0,-1,0,-1,5,-1,0,-1,0);

filter2D(src,dst,-1,kernel);

相关代码:

#include
#include

using namespace cv;
using namespace std;


int main(int argc, char **argv) {
	Mat src = imread("C:\\Users\\admin\\Desktop\\demo.jpg", IMREAD_COLOR);
	if (src.empty())
	{
		printf("Could not load image...");
		return -1;
	}

	namedWindow("Demo image", CV_WINDOW_AUTOSIZE);
	imshow("Demo image", src);

	Mat dst;
	//完全拷贝:法1
	//dst = Mat(src.size(), src.type());
	//src.copyTo(dst);//复制
	
	//完全拷贝:法2
	//dst = src.clone();
	
	cvtColor(src, dst, CV_BGR2GRAY);
	printf("The channels of src: %d\n", src.channels());
	printf("The channels of dst: %d\n", dst.channels());

	const uchar* ptr1 = dst.ptr(0);
	printf("first pixel value : %d", *ptr1);

	int cols = dst.cols;
	int rows = dst.rows;
	printf("cols:%d rows:%d\n", cols, rows); 
	

	namedWindow("Copy image", CV_WINDOW_AUTOSIZE);
	imshow("Copy image", dst);

	//构造函数集合
	//Mat M(3, 3, CV_8UC3, Scalar(0, 0, 255));
	//cout << "M=" << endl << M << endl;
	//imshow("Copy image", M);

	//Mat B(dst);
	//namedWindow("B image", CV_WINDOW_AUTOSIZE);
	//imshow("B image", B);

	Mat M;
	M.create(4, 3, CV_8UC2);
	M = Scalar(127, 127);
	cout << "M=" << endl << M << endl << endl;
	uchar *firstRow = M.ptr(0);
	printf("FirstRow's value:%d\n", *firstRow);

	Mat dd;
	Mat kernel = (Mat_(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
	filter2D(src, dd, -1, kernel);

	Mat dd2;
	dd2 = Mat::zeros(dst.size(), dst.type());
	namedWindow("Black window", CV_WINDOW_AUTOSIZE);
	imshow("Black window", dd2);

	//小数组
	Mat m2 = Mat::zeros(2, 2, CV_8UC1);
	//Mat m2 = Mat::eye(2, 2, CV_8UC1);
	cout << "m2=" << endl << m2 << endl;

	waitKey(0);
	return 0;
}

 

你可能感兴趣的:(OPENCV)