Mat常用成员属性
data
是指向矩阵数据的uchar类指针,用*解引用后再强转为int可以读到第一个像素数据。dims
矩阵的维度,例如5*6矩阵是二维矩阵,则dims=2,三维矩阵dims=3。rows
矩阵的行数。cols
矩阵的列数。size
矩阵的大小,返回一个向量,二维矩阵即为 行数 x 列数。
Mat常用成员方法
channels()
矩阵元素拥有的通道数,例如常见的彩色图像,每一个像素由RGB三部分组成,则image.channels() = 3
。type()
表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位数)+(数据类型)+(通道数)。具体的有以下值:
CV_8UC1 | CV_8UC2 | CV_8UC3 | CV_8UC4 |
---|---|---|---|
CV_8SC1 | CV_8SC2 | CV_8SC3 | CV_8SC4 |
CV_16UC1 | CV_16UC2 | CV_16UC3 | CV_16UC4 |
CV_16SC1 | CV_16SC2 | CV_16SC3 | CV_16SC4 |
CV_32SC1 | CV_32SC2 | CV_32SC3 | CV_32SC4 |
CV_32FC1 | CV_32FC2 | CV_32FC3 | CV_32FC4 |
CV_64FC1 | CV_64FC2 | CV_64FC3 | CV_64FC4 |
这里U(unsigned integer)表示的是无符号整数,S(signed integer)是有符号整数,F(float)是浮点数。
例如:CV_16UC2
,表示的是元素类型是一个16位的无符号整数,通道为2。C1,C2,C3,C4则表示通道是1,2,3,4。
type一般是在创建Mat对象时设定,如果要取得Mat的元素类型,则无需使用type,使用下面的depth。
depth()
矩阵中元素的一个通道的数据类型,这个值和type是相关的。例如 type为CV_16SC2
,一个2通道的16位的有符号整数。那么,depth则是CV_16S
。depth也是一系列的预定义值,
将type的预定义值去掉通道信息就是depth值:
CV_8U
CV_8S
CV_16U
CV_16S
CV_32S
CV_32F
CV_64F
首先需要确定的一点是,elemSize()
,elemSize1()
,step[i]
都指的是占用字节数,step1(i)
指的是像素数
-
elemSize()
矩阵一个元素占用的字节数,例如:type是CV_16SC3,那么elemSize = 3 * 16 / 8 = 6 bytes,即每个元素占6个字节,取决于type()
。 -
elemSize1()
矩阵元素一个通道占用的字节数,例如:type是CV_16CS3,那么elemSize1 = 16 / 8 = 2 bytes = elemSize / channels,取决于depth()
。 -
step[i]
step是一个数组,定义了矩阵的布局,以二维矩阵为例,step[0]表示第一维度的单位长度占用字节数(即每行),step[1]表示第二维度的单位长度占用字节数(即每个元素),二维矩阵不存在step[2]。如200 x 300,CV_16UC3的矩阵,step[0] = 300 x (16 / 8) x 3 = 1800, step[1] = (16 / 8) x 3 = 6,即为elemSize()。
-
step1(i)
step1也是一个数组,但是是使用()访问的,这个数组在step[i]
的基础上/elemSize1()
,即除掉了位深度16的影响。以二维矩阵为例,step1(0)
表示第一维度的单位长度的像素数(即每行),step1(1)
表示第二维度的单位长度的像素数(即每个元素,即通道数),二维矩阵不存在step1(2)
。如
200 x 300
,CV_16UC3
的矩阵,step1(0) = 300 x 3 = 900
,即等于列数*通道数,step1(1) = 3
,即为channels()
。需要注意的是几个固定的等式:
step1(i)=step[i]/elemsize1;
step[m-1]=elemsize;其中m=M.dims;
step1(m-1)=channels;
elemSize()=elemSize1() * channels()
矩阵 (M) 中数据元素的地址计算公式:
addr(Mi0,i1,…im-1) = M.data + M.step[0] * i0 + M.step[1] * i1 + … + M.step[m-1] * im-1 (其中m=M.dims)
下面测试:
cv::Mat m1(200, 300, CV_16UC3, cv::Scalar(50, 150, 200));
cout << "*m1.data = " << int(*m1.data) << endl;
cout << "m1.dims = " << m1.dims << endl;
cout << "m1.rows = " << m1.rows << endl;
cout << "m1.cols = " << m1.cols << endl;
cout << "m1.size = " << m1.size << endl;
cout << "m1.channels() = " << m1.channels() << endl;
cout << "m1.type() = " << m1.type() << endl;
cout << "m1.depth() = " << m1.depth() << endl;
cout << "m1.elemSize() = " << m1.elemSize()<<endl;
cout << "m1.elemSize1() = " << m1.elemSize1() << endl;
cout << "m1.step[0] = " << m1.step[0] << endl;
cout << "m1.step[1] = " << m1.step[1] << endl;
cout << "m1.step1(0) = " << m1.step1(0) << endl;
cout << "m1.step1(1) = " << m1.step1(1) << endl;
输出结果:
*m1.data = 50
m1.dims = 2
m1.rows = 200
m1.cols = 300
m1.size = 200 x 300
m1.channels() = 3
m1.type() = 18
m1.depth() = 2
m1.elemSize() = 6
m1.elemSize1() = 2
m1.step[0] = 1800
m1.step[1] = 6
m1.step1(0) = 900
m1.step1(1) = 3