i Mat中的step[i],step1,elemsize,elemsize1

Mat中的step[i], step1(i), , 在读取数据和数据转换的时候经常用到,分析了目前比较流行的几种说法,加入了一些自己的见解 。
文章目录
概念
指的是每个像素的字节数
指的是每个像素值的字节数(比如三通道的图像每个像素有三个像素值)
step是一个数组,用 step 数据属性可得到单位是字节的图像的有效宽度,即使图像的类型不是 uchar,step 仍然能提供行的字节数 。
举例说明
中Mat类的是每个像素的字节数,如果一个图像是3通道,每个通道是16位,那么其就是3*(16/8)=6,即每个元素占6个字节
中Mat类的是指每个像素每个通道的像素值所占的字节数,对应于上面就是2个字节
中Mat类的step,step是一个数组,用 step 数据属性可得到单位是字节的有效宽度 。即使图像的类型不是 uchar,step 仍然能提供行的字节数 。有以下关系
step1(i) = step[i] / elemsize1;step[m-1] = elemsize;
其中m是图像的维数,step1(m-1)=;
矩阵 (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;
(uchar) = 1,那么每一个数据元素大小为 1。即
M.() == 1
M.() == 1;
CV_8U 得到 M.depth() == 0, M.() == 1;
因为是二维矩阵,那么 step 数组只有两个值, step[0] 和 step[1] 分别代表一行的数据大小和一个元素的数据大小,则
M.step[0] == 4,
M.step[1] == 1
M.step1(0) == M.cols = 4;
M.step1(1) == 1;
假设上面的矩阵数据类型是 ,也就是三通道,则
M.dims == 2
M.() == 3
M.depth() == 0
M.() == 3 (每一个元素包含3个uchar值)
M.() == 1 ( / )
M.step[0] == M.cols * M.() == 12
M.step[1] == M.() * M.() == M.() == 3
上面是一篇博客里边提到的,说的不是太清楚,下面我再细讲一下关于step的概念,step其实是有效宽度,其与图像数据缓存的时候的数据对齐有关 。

i  Mat中的step[i],step1,elemsize,elemsize1

文章插图
在彩色图像中,图像数据缓冲区的前 3 字节表示左上角像素的三个通道的值,接下来的 3字节表示第 1 行的第 2 个像素,以此类推(注意默认的通道次序为 BGR) 。一个宽 W高 H 的图像所需的内存块大小为 W×H×3。不过出于性能上的考虑,我们会用几个额外的像素来填补行的长度 。这是因为,如果行数是某个数字(例如 8)的整数倍,图像处理的性能可能会提高,因此最好根据内存配置情况将数据对齐 。当然,这些额外的像素既不会显示也不被保存,它们的额外数据会被忽略 把经过填充的行的长度指定为有效宽度 。如果图像没有用额外的像素填充,那么有效宽度就等于实际的图像宽度 。我们已经学过,用 cols和 rows 属性可得到图像的宽度和高度 。与之类似,用 step 数据属性可得到单位是字节的有效宽度 。即使图像的类型不是 uchar,step 仍然能提供行的字节数 。用 step 属性可得到一行的总字节数(包括填充像素) 。通常可以用下面的方法得到第 j 行、 第 i 列的像素的地址:
// (j,i)像素的地址,即&image.at(j,i)data= http://www.kingceram.com/post/image.data+j*image.step+i*image.elemSize();
对于3维时(通道数不算另一维):