图像中的每个点称为像素,每个像素可以存储一个或多个值,这个取决于它是否为彩色,灰色,黑色或者白色图像(也称为二进制图像)。
灰度级尺度图像可以存储一个值,彩色图像可以存储三个值。这些值通常是介于0-255之间的整数。
在计算机中,我们将图像以矩阵的格式存储,在矩阵格式中,每个像素都有位置,可以通过列数和行数引用到像素,opencv中通过Mat类来实现图像数据的管理
下图显示的是使用一个宽度x高度x颜色数目矩阵的彩色图像和使用一个单一矩阵的灰度图像(在opencv中这些矩阵都可以使用Mat类来创建)
Mat类不只是用于存储图像,而且还可以存储任意大小的不同类型的矩阵。可以使用它作为代数矩阵,并执行操作。
计算机内存中矩阵是如何存储的?
在内存中,矩阵被保存为数组或值按列和行有序排序的序列。
下表显示BGR图像格式中的像素序列
按此顺序,通过下面公式就可以访问任何像素:
value = Row_i * num_cols * num_channels + col_i + channel_i
值 = 行号 * 每行列数 * 每列像素个数 + 第几列 + 第几个像素
Mat类是一个图像类,也是一种通用矩阵类。下面先了解一下Mat构造矩阵和操作矩阵的一些方法
//构造函数
//无参构造
Mat::Mat();
//创建行数为rows,列为col,类型为type的图像(图像元素类型,如CV_8UC3等)
Mat::Mat(int rows, int cols, int type);
//创建大小为size,类型为type的图像
Mat::Mat(Size size, int type);
//创建行数为rows,列数为 col,类型为 type 的图像,并将所有元素初化为值s
Mat::Mat(int rows, int cols, int type, const Scalar& s);
//创建大小为size,类型为type的图像,并且将所有元素初始化为值s
Mat(Size size, int type, const Scalar& s);
//ndims是维数。
Mat(int ndims, const int* sizes, int type);
//ndims是维数。
Mat(int ndims, const int* sizes, int type, const Scalar& s);
//拷贝构造函数,仅复制头和指针,不复制数据部分,即共用数据部分
Mat(const Mat& m);
创建矩阵需要知道矩阵的尺寸大小和数据类型;
矩阵尺寸大小:就是m行n列;Size(5,5);
矩阵数据类型:深度8/32位,类型uchar/float,通道数1/3/4;
可选的矩阵的数据类型:
CV_8UC1 // 8位无符号单通道
CV_8UC3 // 8位无符号3通道
CV_8UC4 // 8位无符号4通道
CV_32FC1 // 32位浮点型单通道
CV_32FC3 // 32位浮点型3通道
CV_32FC4 // 32位浮点型4通道
如:Mat b = Mat(Size(5, 5), CV_8UC1);
创建3通道的2行2列的矩阵
/*
2,2:分别表示行(row)跟列(column)、
CV_8UC3:中的8表示每个通道占8位、U表示无符号、C表示Char类型、3表示通道数目是3
Scalar(0,0,255):是向量表示初始化每个像素值是多少,向量长度对应通道数目一致
*/
//创建3通道的2行2列的矩阵,(0,0,255)为1列中的三个元素
Mat M1(2,2,CV_8UC3, Scalar(0,0,255));
cout << "M1 = " << endl << " " << M1 << endl << endl;
创建3通道,4行3列的矩阵
//创建3通道,4行3列的矩阵
Mat M2;
M2.create(4, 3, CV_8UC2);
M2 = Scalar(127,127);
cout << "M2 = " << endl << " " << M2 << endl << endl;
uchar* firstRow = M2.ptr<uchar>(0);
cout << "firstRow = " << firstRow << endl;
创建1通道的3行3列的矩阵
//创建1通道的3行3列的矩阵。赋值为下面的数
Mat M3 = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
cout << "M3 = " << endl << " " << M3 << endl << endl;
Mat mz = Mat::zeros(5, 5, CV_8UC1); //全0矩阵
Mat mo = Mat::ones(5, 5, CV_8UC1); //全1矩阵
Mat me = Mat::eye(5, 5, CV_32FC1); //对角线为1的对角矩阵
cout << "mz = " << endl << mz << endl;
cout << "mo = " << endl << mo << endl;
cout << "me = " << endl << me << endl;
创建Qt工程参考2.2章-Qt测试Opencv代码
在Qt工程的pro文件添加如下内容
#若将D:/opencv/install/install/include添加到环境变量,下面INCLUDEPATH这三行可以不写
INCLUDEPATH += D:/opencv/install/install/include/opencv \
D:/opencv/install/install/include/opencv2 \
D:/opencv/install/install/include
LIBS += -L D:/opencv/install/install/x64/mingw/lib/libopencv_*.a
#添加环境变量之后可以不使用绝对路径
#LIBS += -L libopencv_*.a
修改Qt工程的main.cpp文件如下
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
//创建3通道的2行2列的矩阵,(0,0,255)为1列中的三个元素
Mat M1(2,2,CV_8UC3, Scalar(0,0,255));
cout << "M1 = " << endl << " " << M1 << endl << endl;
//创建3通道的4行3列的矩阵,(127,127)为1列中的2个元素
Mat M2;
M2.create(4, 3, CV_8UC2);
M2 = Scalar(127,127);
cout << "M2 = " << endl << " " << M2 << endl << endl;
uchar* firstRow = M2.ptr<uchar>(0); //指针指向矩阵的第一行
printf("%d\n", *firstRow); //取指针的内容(本质就是取到第一个元素)
//创建1通道的3行3列的矩阵。赋值为下面的数
Mat M3 = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
cout << "M3 = " << endl << " " << M3 << endl << endl;
Mat mz = Mat::zeros(5, 5, CV_8UC1); //全0矩阵
Mat mo = Mat::ones(5, 5, CV_8UC1); //全1矩阵
Mat me = Mat::eye(5, 5, CV_32FC1); //对角线为1的对角矩阵
cout << "mz = " << endl << mz << endl;
cout << "mo = " << endl << mo << endl;
cout << "me = " << endl << me << endl;
}