OpenCV中 width 和 widthStep的区别:
width表示图像的每行像素数,widthStep表示存储一行像素需要的字节数。
在OpenCV里边,widthStep必须是4的倍数,从而实现字节对齐,有利于提高运算速度。
如果8U单通道图像宽度为3,那么widthStep是4,加一个字节补齐。这个图像的一行需要4个字节,只使用前3个,最后一个空着。
下面以三通道的图像为例讲解opencv如何访问图像像素并赋值?
方法一:
利用IplImage数据类型的imageData定位数据缓冲区来实现,imageData包含指向图像第一个像素数据的指针
例:
If( imgSource != 0 )//imgSource为IplImage*
{
for ( int i = 0; i < imgSource->height; ++i )
{
uchar * pucPixel = (uchar*)imgSource->imageData + i*imgSource->widthStep;
for ( int j = 0; j < imgSource->width; ++j )
{
pucPixel[3*j] = 0;//像素第一个通道的值
pucPixel[3*j + 1] = 0;//像素第二个通道的值
pucPixel[3*j + 2] = 0;//像素第三个通道的值
}
}
}
方法二:
使用 Mat::at 函数
- 原型 template<typename _Tp> inline _Tp& Mat::at(…) //其中参数有多个,也就是说 at 函数有多个重载
- 返回值为 Mat 类型, Mat 有个索引的重载,也就是 [] 符号的重载,用这个重载可以定位多通道数据,具体示例可以看下面代码
下面的代码把红色通道值大于128的颜色的置为白色
int main()
{
Mat img = imread("lena.jpg");
imshow("Lena Original", img);
for (int row = 0; row < img.rows; row++)
{
for (int col = 0; col < img.cols; col++)
{
/* 注意 Mat::at 函数是个模板函数, 需要指明参数类型, 因为这张图是具有红蓝绿三通道的图,
所以它的参数类型可以传递一个 Vec3b, 这是一个存放 3 个 uchar 数据的 Vec(向量). 这里
提供了索引重载, [2]表示的是返回第三个通道, 在这里是 Red 通道, 第一个通道(Blue)用[0]返回 */
if(img.at<Vec3b>(row, col)[2] > 128)
img.at<Vec3b>(row, col) = Vec3b(255, 255, 255);
}
}
imshow("Lena Modified", img);
cvWaitKey();
return 0;
}