【OpenCV(C++)】基础图像容器Mat
数字图像存储
通常由显示屏上看到的都是真实的图像,但是这些图像在转化到我们的数字设备中时,记录的却是图像中每个点的数值。
矩阵就是图像在数码设备中的表现形式,OpenCV作为一个计算机视觉库,其主要的工作就是处理和操作并进一步了解这些形式和信息。
Mat结构的使用
Mat是一个类,由两个数据部分组成:矩阵头和一个指向存储所有像素值的矩阵的指针。
OpenCV使用了引用计数机制,让每个Mat对象有自己的信息头,但共享同一个矩阵。这通过让矩阵指针指向同一地址而实现。
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main()
{
Mat A, C;
A = imread("fg.jpg", CV_LOAD_IMAGE_COLOR);
Mat B(A);
C = A;
Mat D(A, Rect(50, 50, 50, 50));
Mat F = A.clone();
imshow("A", F);
waitKey(0);
return 0;
}
运行结果如下:
使用函数clone()或者copyTo()来复制一幅图像的矩阵。
像素值的存储方法
存储像素值需要指定颜色空间和数据类型。
颜色空间
颜色空间是指针对一个给定颜色,如何组合颜色元素以对其编码。
-
灰度级空间:只处理黑色和白色
-
彩色空间:把颜色分成三个或四个基元素,通过组合基元素可以产生所有的颜色。
- RGB——最常见的,因为其与人眼采用相似的工作机制,也被显示设备所采用。有时为了表示透明颜色也会加入第四个元素alpha(A)。
- HSV和HLS——把颜色分解为色调、饱和度和亮度。这是描述颜色更自然的方式。
- YCrCb——在JEPG图像格式中广泛使用。
- CIE L * a * b*——是一种在感知上均匀的颜色空间,适合用来度量两个颜色之间的距离。
数据类型
每个组成元素都有其自己的定义域,而定义域取决于其数据类型,如何存储一个元素决定了我们在其定义域上能控制的精度。
- char:1字节,8位
- float: 4字节,32位
- double: 8字节,64位
增加元素的尺寸,能给出更加精细的颜色分辨能力,但同时也会增加图像所占的内存空间。
显示创建Mat对象的七种办法
1.使用Mat()构造函数
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat A(2, 2, CV_8UC3,Scalar(0,0,225));
cout << "A=" << endl << "" << A << endl << endl;
return 0;
}
2.在C/C++中构造函数进行初始化
int sz[3] = { 2, 2, 2 };
Mat A(3,sz, CV_8UC,Scalar::all(0));
3.为已存在的IplImage指针创建信息头
IplImage* img = cvLoadImage("pig,jpg", 1);
Mat mtx(img);
4.利用Create()函数
不能为矩阵设初值,只能改变尺寸,为矩阵开辟内存。
A.Create(4, 4, CV_8UC(2));
cout << "A=" << endl << "" << A << endl << endl;
5.采用MATLAB式的初始化方法
Mat A = Mat::eye(4, 4, CV_64F);
cout << "A=" << endl << "" << A << endl << endl;
Mat B = Mat::ones(2, 2, CV_32F);
cout << "B=" << endl << "" << B << endl << endl;
Mat C = Mat::zeros(3, 3, CV_8UC1);
cout << "C=" << endl << "" << C << endl << endl;
6.小矩阵采用逗号分隔开初始化
Mat A = (Mat_<double>(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
cout << "A=" << endl << "" << A << endl << endl;
7.为已存在的数据创建新的数据头
Mat A = (Mat_<double>(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
Mat RowClone = A.row(1).clone();
cout << "RowClone=" << endl << "" << RowClone << endl << endl;