【Opencv】Opencv中的Mat类介绍

Opencv中的Mat类介绍

1. Mat类简介

Mat类是Opencv中储存图像非常常见的一种数据结构。Mat类可以看做是存放矩阵的容器,他包含了两部分,分别是用来存放图片信息的信息头,和一个指向图片储存矩阵的指针。信息头往往占用空间比较小,而且各个图片之间的信息头是完全独立的。而图片储存矩阵往往占用较大的空间,并且可以多个图片的矩阵指针指向同一个内存空间。

2. Mat类的拷贝

从Mat类的数据储存结构来看,Mat类图像储存是通过矩阵指针实现的。这样的话,在做图片复制的时候,就必须要考虑的一个问题是:我们需要复制的是矩阵指针的地址,还是需要重新创建一个内存空间,把图片存储矩阵重新拷贝一份。所以Mat类的拷贝具有浅拷贝和完全拷贝两种。

2.1 使用拷贝构造函数进行拷贝

Mat类中具有自己的拷贝构造函数,其函数原型如下

Mat(const Mat& m);

使用拷贝构造函数进行图片的拷贝有两种写法,并且这两种写法是等价的。

Mat m = imread("1.jpg);
Mat m1 = m;
Mat m2(m);

使用拷贝构造函数进行图片拷贝是一种浅拷贝,其结果是,m1和m2并没有自己独立的图片储存空间,而是把自己的矩阵指针指向了m的指针的地址。所以,当我们对m,m1,m2三个图片中的一个有所操作的时候,其他两个图片也会受到影响,有如下的测试代码:

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;

int main()
{

	//创建了Mat类型的变量m,并且通过拷贝构造的方法拷贝到了变量m1和m2
	Mat m = imread("a.jpg");
	Mat m1 = m;
	Mat m2(m);

	//创建了矩阵r和向量s,用于在图m1上绘图
	Rect r(0, 0, 300, 300);
	Scalar s(255, 0, 255);
	rectangle(m1, r, s);

	//显示所有的三张图片
	imshow("m", m);
	imshow("m1", m1);
	imshow("m2", m2);

	waitKey(0);
	return 0;
}

运行结果如下:
在这里插入图片描述

2.2 使用clone()函数或者copyTo()函数进行拷贝

使用这两种方法拷贝,是一种完全拷贝,会为图片生成独立的图片储存矩阵,与原图片不公用数据,这样的话,操作其中一个,其他的并不会受到影响,缺点是占用空间大,而且速度比较慢。

写法如下:

Mat m = imread("a.jpg");
Mat m1;
m.copyTo(m1);
Mat m2=m.clone();

测试代码:

扫描二维码关注公众号,回复: 10461709 查看本文章
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;

int main()
{

	//创建了Mat类型的变量m,并且拷贝到了变量m1和m2
	Mat m = imread("a.jpg");
	Mat m1;
	m.copyTo(m1);
	Mat m2=m.clone();
	

	//创建了矩阵r和向量s,用于在图m1上绘图
	Rect r(0, 0, 300, 300);
	Scalar s(255, 0, 255);
	rectangle(m, r, s);

	//显示所有的三张图片
	imshow("m", m);
	imshow("m1", m1);
	imshow("m2", m2);

	waitKey(0);
	return 0;
}

在这里插入图片描述

3.Mat类创建矩阵

由于Mat类本身就是一种矩阵处理的类,所以可以通过Mat类进行矩阵的创建

3.1Mat类创建二维矩阵

利用Mat类的构造函数进行

Mat类有很多构造函数可以用来创建矩阵结构,并且给与赋值,这里距离介绍一种,其函数定义为

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

这个构造函数具有四个参数,其特点是能够定义矩阵的结构并且能够赋予初值

第一个参数表示矩阵的行数
第二个参数表示矩阵的列数
第三个参数表示矩阵储存数据的类型,具有格式 CV_[位数][有无符号][数据类型][通道数],如

CV_8UC3 //表示存储数据为8位无符号char类型,并且具有三个通道

第四个参数是一种向量类型的变量,能够给予矩阵赋予初值,这个向量最多有四个维度。

使用举例:

Mat m(3, 3, CV_8UC3, Scalar(100, 10, 0));

在这里插入图片描述

利用成员函数create创建矩阵

使用这种方法创建的矩阵只是一种开辟内存空间,而不能赋予初值

Mat m;
m.create(3, 3, CV_8UC3);

Matlab式的矩阵创建

Mat类中有三个static的函数eye(),zeros(),ones()用于创建矩阵,与matlab中的同名函数用法相似
,因为是静态函数,所以他们可以脱离具体实例对象单独存在,调用的时候前面加上所属类名即可调用,用法如下

	Mat E = Mat::eye(4, 4, CV_32F);
	Mat Z = Mat::zeros(4, 4, CV_32F);
	Mat O = Mat::ones(4, 4, CV_32F);

输出:

逗号分隔的方式创建矩阵

如果矩阵比较小,可以通过这种方法进行输入,有点类似于每个数字都自己输入的样子

Mat C =(Mat_<double>(3,3)<<1,1,1,1,1,1,1,1,1);

3.2Mat类创建多维矩阵

Mat类除了能够像上面的例子那样创建二维矩阵,也可以通过定义维度的方法创建多维矩阵,这种构造函数定义如下:

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

第一个参数是矩阵的维度,比如写3代表是三维矩阵
第二个参数是一个int类型的指针,表示每个维度的数据长度是多少
第三个参数表示储存数据的类型是什么
第四个参数用来赋予初始值的

使用方法如下:

int size[3]={3,3,3};
Mat(3,size,CV_8UC3,Scalar::all(0));

4.Mat类的格式化输出

Mat类的格式化输出仅限于二维的矩阵。或者说,使用cout来输出Mat类型的变量,仅限于二维的。这里只举几个例子。

4.1 默认格式

Mat m=Mat::zeros(5,5,CV_64F);
cout<<m<<endl;

在这里插入图片描述

4.2 python格式

Mat m = Mat::zeros(5, 5, CV_64F);
cout << format(m,Formatter::FMT_PYTHON)<< endl<<endl;

在这里插入图片描述

4.3 c语言格式

Mat m = Mat::zeros(5, 5, CV_64F);
cout << format(m, Formatter::FMT_C) << endl << endl;

在这里插入图片描述

4.4 numpy格式

Mat m = Mat::zeros(5, 5, CV_64F);
cout << format(m, Formatter::FMT_NUMPY) << endl<<endl;

在这里插入图片描述

发布了14 篇原创文章 · 获赞 1 · 访问量 504

猜你喜欢

转载自blog.csdn.net/qq_41741344/article/details/104341760