本文主要是介绍Mat中的step[i],step1(i),elemsize,elemsize1,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Mat中的step[i], step1(i), elemsize, elemsize1在读取数据和数据转换的时候经常用到,分析了目前比较流行的几种说法,加入了一些自己的见解。
文章目录
- 概念
- 举例说明
- 代码演示
概念
elemsize指的是每个像素的字节数
elemsize1指的是每个像素值的字节数(比如三通道的图像每个像素有三个像素值)
step是一个数组,用 step 数据属性可得到单位是字节的图像的有效宽度,即使图像的类型不是 uchar,step 仍然能提供行的字节数。
举例说明
-
opencv中Mat类的elemsize是每个像素的字节数,如果一个图像是3通道,每个通道是16位,那么其elemsize就是3*(16/8)=6,即每个元素占6个字节
-
opencv中Mat类的elemsize1是指每个像素每个通道的像素值所占的字节数,对应于上面就是2个字节
-
opencv中Mat类的step,step是一个数组,用 step 数据属性可得到单位是字节的有效宽度。即使图像的类型不是 uchar,step 仍然能提供行的字节数。有以下关系
step1(i) = step[i] / elemsize1;
step[m-1] = elemsize;
其中m是图像的维数,step1(m-1)=channels;
矩阵 (M) 中数据元素的地址计算公式:
$addr(Mi_0,i_1,…i_{m-1}) = M.data + M.step[0] * i0 + M.step[1] * i1 + … + M.step[m-1] * im-1 $
(其中 m = M.dims M的维度)
下面举例:对于2维的情况:
一个 3 X 4 的矩阵,假设其数据类型为 CV_8U,也就是单通道的 uchar 类型
这是一个二维矩阵,那么维度为 2 即:
M.dims == 2
M.rows == 3;
M.cols == 4;
sizeof(uchar) = 1,那么每一个数据元素大小为 1 。即
M.elemSize() == 1
M.elemSize1() == 1;
CV_8U 得到 M.depth() == 0, M.channels() == 1;
因为是二维矩阵,那么 step 数组只有两个值, step[0] 和 step[1] 分别代表一行的数据大小和一个元素的数据大小,则
M.step[0] == 4,
M.step[1] == 1
M.step1(0) == M.cols = 4;
M.step1(1) == 1;
假设上面的矩阵数据类型是 CV_8UC3,也就是三通道,则
M.dims == 2
M.channels() == 3
M.depth() == 0
M.elemSize() == 3 (每一个元素包含3个uchar值)
M.elemSize1() == 1 (elemSize / channels)
M.step[0] == M.cols * M.elemSize() == 12
M.step[1] == M.channels() * M.elemSize1() == M.elemSize() == 3
上面是一篇博客里边提到的,说的不是太清楚,下面我再细讲一下关于step的概念,step其实是有效宽度,其与图像数据缓存的时候的数据对齐有关。
// (j,i)像素的地址,即&image.at(j,i)
data= image.data+j*image.step+i*image.elemSize();
对于3维时(通道数不算另一维):
上面是一个 3 X 4 X 6 的矩阵,假设其数据类型为 CV_16SC4,也就是 short 类型
M.dims == 3 ; M.channels() == 4 ;
M.elemSize1() == sizeof(short) == 2 ;
M.rows == M.cols == –1;
M.elemSize() == M.elemSize1() * M.channels() == M.step[M.dims-1] == M.step[2] == 2 * 4 == 8;
M.step[0] == 4 * 6 * M.elemSize() == 192;
M.step[1] == 6 * M.elemSize() == 48;
M.step[2] == M.elemSize() == 8;
M.step1(0) == M.step[0] / M.elemSize() == 192 / 2 == 96 (第一维度(即面的元素个数) * 通道数);
M.step1(1) == M.step[1] / M.elemSize() == 48 / 2 == 24(第二维度(即行的元素个数/列宽) * 通道数);
M.step1(2) == M.step[2] / M.elemSize() == M.channels() == 4(第三维度(即元素) * 通道数);
代码演示
void myLog(Mat src)
{int dim = src.dims;for (int i = 0; i < dim; i++){cout << src.type() <<" step[" <<i << "]:"<< src.step[i] << "\t";cout << src.type() << " step1[" << i << "]:" << src.step1(i) << endl;}cout << src.type() << " elemSize:" << src.elemSize() << "\t";cout << src.type() << " elemSize1:" << src.elemSize1() << endl;
}int main(int argc, char** argv)
{Mat test = Mat(3, 4, CV_8UC1);myLog(test);Mat test1 = Mat(3, 4, CV_8UC3);myLog(test1);Mat test2 = Mat(3, 4, CV_16SC4);myLog(test2);int sz[3] = { 3, 4, 6};//sz指定数组尺寸大小3*4*6uchar* p; //用于访问像素Mat test3(3, sz, CV_16SC4);//指定n维,当前为3维;for (int i = 0; i < 3; i++) //行数for (int j = 0; j < 4; j++)//列数for (int k = 0; k < 6; k++)//高{p = test3.data + test3.step[0] * i + test3.step[1] * j + test3.step[2] * k; //访问m_nut(i,j,k)(*p) = i + j + k; // 为当前访问的像素赋值}myLog(test3);return 0;
}
结果:
参考:https://blog.csdn.net/LIYUAN123ZHOUHUI/article/details/52922951
这篇关于Mat中的step[i],step1(i),elemsize,elemsize1的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!