1.图像在内存之中的存储方式:
图像矩阵的大小取决于所用的颜色模型,确切说,取决于所用通道数。如果是灰度图像,矩阵就会如图5.1所示。
对于多通道图像来说,矩阵中的列会包含多个子列,其子列个数与通道数相同,如图5.2所示RGB颜色模型的矩阵。
可以看到,OpenCV中子列的通道顺序是反过来的——BGR而不是RGB。 有时候,由于内存足够大,可实现连续存储,图像中的各行是一行一行连接起来的,形成一个长行。可以使用isContinuous()来判断矩阵是否是连续存储的。
2.mat矩阵 (图像存储类型)
1.概念:
Mat是一个类,由两部分组成:
什么是Mat呢,Mat其实就是matrix(矩阵)的缩写
我们看到的图像,就是以数字矩阵的形式存储在计算机中,在opencv中,我们用Mat类的对象
存储图像。
在opencv中,Mat类分为两个部分
- 矩阵头
- 矩阵数据
矩阵头
矩阵数据
如下边代码:
Mat A, C; // 仅创建信息头部分
A = imread("1.jpg", CV_LOAD_IMAGE_COLOR) // 这里为矩阵开辟内存
Mat B(A) //使用拷贝构造函数
C=A; //赋值运算符
上述代码中的所有Mat对象最终都指向同一个也是唯一一数据矩阵。虽然它们的信息头不同,但通过任何一个对象所做的改变也会影响其他对象。
创建部分信息数据的信息头:只需要创建包含边界信息的信息头
Mat D(A, Rect(10, 10, 100, 100)); //使用矩形界定
Mat E = A(Range:all(), Range(1, 3)
复制矩阵本身(不只是复制信息头和矩阵指针):使用函数clone()、copyTo()
Mat F = A.clone();
Mat G;
A.copyTo(G)
上述代码,改变F和G就不会影响Mat信息头所指向的矩阵。
2.Mat对象复制
看上图,我们发现Mat对象复制是有三种方法的
克隆
拷贝
赋值
这里说一下它们的区别
赋值:相当于浅复制,只复制了矩阵头,指向的是同一个数据块。类似浅拷贝,指针直接指向
克隆/拷贝:相当于深复制,还会复制相应的数据块
//1.赋值——浅复制
Mat src = imread("……");
Mat m3 = src;
//2.克隆——深复制
Mat src = imread("……");
Mat m1 = src.clone();
//3.拷贝——深复制
Mat src = imread("……");
Mat m2;
src.copyTo(m2);
3.Mat对象属性
Mat对象存储了一些属性,如:列数,行数,通道数(维度),位深度,图像类型
Mat image= imread("……");
获取方式:
image.cols;列
image.rows;行
image.channels();通道
image.depth();深度
image.type();类型
image.size() 长x高
数据类型和通道数
图像的数据类型type由两部分组成
std::cout << m << std::endl;//为了说明以上语句的不同,我们把矩阵进行打印
3.Mat对象的创建 与初始化
1.使用无参数构造函数,创建Mat对象。
Mat image = Mat();
image.create(4, 4, CV_8UC3);//创建一个4x4大小的像素块,每个像素都是三通道每个通道的位数都是8位
1
2
上述CV_8UC3中的8表示8位,UC表示uchar类型,3表示三个通道。
2.使用带行、列、类型这个三个参数的构造函数创建Mat对象
Mat m = Mat(4, 4, CV_8UC3); //创建一个4x4大小的像素块,每个像素都是三通道每个通道的位数都是8位
与方法二创建的像素块一样。
3.使用行、列、类型、Scalar向量四个参数的构造函数创建Mat对象。
Mat m = Mat(4, 4, CV_8UC3, Scalar(0, 255, 255));
//创建一个4x4大小的像素块,每个像素都是三通道每个通道的位数都是8位,指定三通道颜色值向量Scalar(0, 255, 255)
同样表示创建一个4x4的像素块,唯一的区别是颜色不是默认值,而是我们指定的三通道颜色值向量Scalar(0, 255, 255)。其中Scalar向量数目永远是等于通道数目。
4.使用大小、类型两个参数的构造函数创建Mat对象。
Mat m = Mat(Size(4, 4), CV_8UC3); //创建一个4x4大小的像素块,每个像素都是三通道每个通道的位数都是8位
5.使用大小、类型、Scalar向量三个参数的构造函数创建Mat对象。
Mat m = Mat(Size(4, 4), CV_8UC3, Scalar(255, 0, 0)); //创建一个4x4大小的像素块,每个像素都是三通道每个通道的位数都是8位
Mat对象创建,常用的是创建空白图像。如下演示了三种
4.Mat对象的赋值
最常用的有4种方法
-
Mat::zeros
创建空矩阵
-
Mat::ones
创建1矩阵
Mat m = Mat::ones(Size(8, 8), CV_8UC1);
Mat m = Mat::ones(Size(8, 8), CV_8UC3);
-
重载的 =
直接赋值
m=127;
和Mat::ones相同,单通道没问题,多通道只赋值第一个
-
Scalar
下面介绍一个非常常用的赋值方法,比如我们赋值三通道,全变127
m=Scalar(127,127,127);
5.Mat对象的显示
在opencv中Mat矩阵就是图像,那我们来显示一下全127对应的图像
void QuickDemo::mat_creation_demo(Mat& image) {
//创建空白图像
Mat m3 = Mat::ones(Size(400, 400), CV_8UC3);
m3 = Scalar(127, 127, 127);
imshow("创建图像", m3);
}
6.总结:
像素值的存储方法: