OpenCV 如何对图像的像素进行操作
对图像的像素进行操作,我们可以实现空间增强,反色,大部分图像特效系列都是基于像素操作等目的。先来看一下内存空间中图像矩阵,也就是Mat的矩阵数值部分是怎么存储的:
如果图像是一幅灰度图像,他就像这样,从左到右,从上到下,依次是矩阵的每一行每一列,这时候矩阵M(i,j)的值自然就是当前点的灰度值了。
而对于一幅彩色图像,由于它的像素分量channel并不是一个,所以每一列又分为了几个channel。拿常见的RGB图像来说,就像这样:
从这张图上,就可以比较清楚地看出来在内存中矩阵是如何存储多channel图像的了。这里要注意的是在RGB模型中,每一个子列依次为BGR,也就是正好是颠倒的,第一个分量是蓝色,第二个是绿色,第三个是红色。
清楚了图像在内存中的存储方式,我们也就可以来进行像素值的操作了。在这里,我们举这样一个例子。我们对一幅灰度图像的灰度值进行变换:
小于100的灰度值被统一映射为0;100到200之间的灰度值被映射为100;大于200的灰度值被映射为200.
主函数如下:
int main()
{
string picName="lena.jpg";
Mat A=imread (picName,CV_LOAD_IMAGE_GRAYSCALE); //读入灰度图像
uchar table[256]; //映射表,规定了变换前后灰度值的对应关系 table[gray_value_before]=gray_value_after
for (int i=0;i<256;i++)
{
table[i]=i/100*100; //这里利用了C++的语言特性i/100只会留下整数部分
}
imshow("变换前",A);
Mat B=ChangeImg (A,table); //变换函数
imshow ("变换后",B);
waitKey ();
return 0;
}
首先,我们用指针方式对图像的像素点灰度值进行操作:
Mat ChangeImg(Mat &img,const uchar* table)
{
CV_Assert(img.depth ()!=sizeof(uchar)); //声明只对深度8bit的图像操作
int channels=img.channels (); //获取图像channel
int nrows=img.rows; //矩阵的行数
int ncols=img.cols*channels; //矩阵的总列数=列数*channel分量数
if (img.isContinuous ()) //判断矩阵是否连续,若连续,我们相当于只需要遍历一个一维数组
{
ncols*=nr