一、基础概念
1、data:unchar类型的指针,指向Mat矩阵的首地址,可以理解为表示一个房屋的门牌号。
2、elemSize:
elem是element(元素)的缩写,表示矩阵中每一个元素的数据大小,如果Mat中的数据类型是CV_8UC1,那么 elemSize==1;如果是CV_8UC3或CV_8SC3,那么elemSize==3;如果是CV_16UC3或者CV_16SC3,那么 elemSize==6;即elemSize是以8位(一个字节)为一个单位,乘以通道数和8位的整数倍
可以理解为整个房间可以睡多少人,这个时候就得累计上房间内所有床位数(通道)和每张床的容纳量了;
3、step:
step这里指出的是图像在各个梯级上的字节数大小,而这里的梯级指的是构成图像的名层次。
上图三维图像由一个一个名面(第一级)构成,每一个平面由一行一行(第二级)构成,每行由一个一个点(第三级)构成。
同理:二维图像由一行一行(第一级)构成,而每一行又由一个一个点(第二级)构成。
Mat中的step[0]就是我们每一个第一级,在内存中占据的字节数量。例如,二维图像中step[0]就是每一行(第一级)在矩阵内存中,占据的字节的数量。也就是说step[i]就是第i+1级在矩阵内存中占据的字节的数量。
M 数组的数据布局是由阵列 M.step[]定义的,使元素的地址(i0,。。。。iM.dims-1),其中 0<= ik < M.size [k],可以计算为:
addr( Mi0 ;:::;iM.dims-1) = M.data+ M.step[ 0]*i0 + M.step[ 1] *i1 + .…+ M.step[ M:dims- 1] iM:dims- 1
2维的数组的情况下根据上述公式被减至:
addr( Mi,j)= M.data+ M.step[ 0]*i+ M.step[ 1] *j
// 此代码展示将彩色图转换为灰度图
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("C:/Users/lenovo/Pictures/Saved Pictures/Lena.png");
Mat dst;
cv::Size size = src.size();
typedef double pixel_t; // 定义像素类型
if (dst.empty())
dst.create(size, CV_64F);
uchar* srcData = src.data;
pixel_t* dstData = (pixel_t*) dst.data;
int dstStep = dst.step / sizeof(dstData[0]); // sizeof(dstData[0])=8,因为像素数据类型为double, 64位,8字节.
int srcStep = src.step / sizeof(srcData[0]); // step表示每行的字节数
int numRow = src.rows;
int numCol = src.cols;
int numChannel = src.channels();
cout << "numRow:" << numRow << endl;
cout << "numCol:" << numCol << endl;
cout << "src.channels:" << numChannel << endl;
cout << "src.step:" << src.step << endl;
cout << "sizeof(dstData[0]):" << sizeof(dstData[0])<<" "<<"dstStep:"<< dstStep << endl;
cout << "sizeof(srcData[0]):" << sizeof(srcData[0]) <<" "<<"srcStep:"<< srcStep <<endl;
for (int j = 0; j < src.cols; j++)
{
for (int i = 0; i < src.rows; i++)
{
double b = *(srcData + src.step*i + src.channels() * j + 0) / 255.0;
double g = *(srcData + src.step*i + src.channels() * j + 1) / 255.0;
double r = *(srcData + src.step*i + src.channels() * j + 2) / 255.0;
*(dstData + dstStep*i + dst.channels()*j) = (b + g + r) / 3;
}
}
cv::imshow("image", dst);
waitKey();
}
代码运行结果:
Ref:
1、https://blog.csdn.net/dcrmg/article/details/52294259(Opencv Mat矩阵中data、size、depth、elemSize、step等属性的理解)
2、https://blog.csdn.net/qianqing13579/article/details/45318279(OpenCV中Mat属性step,size,step1,elemSize,elemSize1)
3、https://blog.csdn.net/lanmeng_smile/article/details/47864615(opencv的Mat中step)