您的位置:首页 > 运维架构

OpenCV获取与设置像素点的值的几个方法

2013-09-21 08:46 169 查看
Title:

OpenCV
OpenCV像素值的获取与设置

Fn1:

使用Mat中对矩阵元素的地址定位的知识(参考博文:OpenCV中对Mat里面depth,dims,channels,step,data,elemSize和数据地址计算的理解)

Code1:

intmain()

{

//新建一个uchar类型的单通道矩阵(grayscaleimage灰度图)

Matm(400,400,CV_8U,Scalar(0));

for(intcol=0;col<400;col++)

{

for(introw=195;row<205;row++)

{

cout<<(int)(*(m.data+m.step[0]*row+m.step[1]*col))<<"==>";

//获取第[row,col]个像素点的地址并用*符号解析

*(m.data+m.step[0]*row+m.step[1]*col)=255;

cout<<(int)(*(m.data+m.step[0]*row+m.step[1]*col))<<endl;

}

}

imshow("canvas",m);

cvWaitKey();

return0;

}


Output1:

0==>255

0==>255

0==>255

0==>255

0==>255

0==>255

...






Code1只是演示了单通道的情况,对于多通道的例子,请看Code2然后再看Code3。

Fn2:

使用Mat::at函数

原型template<typename_Tp>inline_Tp&Mat::at(…)//其中参数有多个,也就是说at函数有多个重载
返回值为Mat类型,Mat有个索引的重载,也就是[]符号的重载,用这个重载可以定位多通道数据,具体示例可以看下面代码

下面的代码把红色通道值大于128的颜色的置为白色,左边为原图,右边为处理过后的图。

Code2:

intmain()

{

Matimg=imread("lena.jpg");

imshow("LenaOriginal",img);


for(introw=0;row<img.rows;row++)

{

for(intcol=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("LenaModified",img);

cvWaitKey();

return0;

}


Output2:





Code3:

这段代码用的是Fn1的方式,效果和Code2等价:

intmain()

{

Matimg=imread("lena.jpg");

imshow("LenaOriginal",img);


for(introw=0;row<img.rows;row++)

{

for(intcol=0;col<img.cols;col++)

{

//主要是这里的代码

if(*(img.data+img.step[0]*row+img.step[1]*col+img.elemSize1()*2)>128)

{

//[row,col]像素的第1通道地址被*解析(blue通道)

*(img.data+img.step[0]*row+img.step[1]*col)=255;

//[row,col]像素的第2通道地址被*解析(green通道),关于elemSize1函数的更多描述请见Fn1里所列的博文链接

*(img.data+img.step[0]*row+img.step[1]*col+img.elemSize1())=255;

//[row,col]像素的第3通道地址被*解析(red通道)

*(img.data+img.step[0]*row+img.step[1]*col+img.elemSize1()*2)=255;

}

}

}


imshow("LenaModified",img);

cvWaitKey();

return0;

}


Output3=Output2

Fn3:

使用Mat的一个模板子类Mat_<typename_Tp>的()符号重载定位一个像素

Code4:

intmain()

{

Matm(400,400,CV_8UC3,Scalar(255,255,255));

//m2是Mat_<Vec3b>类型的,因为m中元素的类型是CV_8UC3,可以用Vec3b存储3个通道的值

//注意Mat_<CV_8UC3>这种写法是错误的,因为CV_8UC3只是一个宏定义

//#defineCV_8UC3CV_MAKETYPE(CV_8U,3)

Mat_<Vec3b>m2=m;


//for循环画一个红色的实心圆

for(inty=0;y<m.rows;y++)

{

for(intx=0;x<m.rows;x++)

{

if(pow(double(x-200),2)+pow(double(y-200),2)-10000.0<0.00000000001)

{

//Mat_模板类实现了对()的重载,可以定位到一个像素

m2(x,y)=Vec3b(0,0,255);

}

}

}


imshow("Image",m);

cvWaitKey();

return0;

}


Output4:[看上去怎么有点不爽

]





Fn4:

使用Mat::ptr模板函数

Code5:

intmain()

{

Matm(400,400,CV_8UC3,Scalar(226,46,166));

imshow("Before",m);


for(introw=0;row<m.rows;row++)

{

if(row%5==0)

{

//data是uchar*类型的,m.ptr<uchar>(row)返回第row行数据的首地址

//需要注意的是该行数据是按顺序存放的,也就是对于一个3通道的Mat,一个像素有

//有3个通道值,[B,G,R][B,G,R][B,G,R]...所以一行长度为:

//sizeof(uchar)*m.cols*m.channels()个字节

uchar*data=m.ptr<uchar>(row);

for(intcol=0;col<m.cols;col++)

{

data[col*3]=102;//第row行的第col个像素点的第一个通道值Blue

data[col*3+1]=217;//Green

data[col*3+2]=239;//Red

}

}

}

imshow("After",m);


cout<<(int)m.at<Vec3b>(0,0)[0]<<',';//利用Fn1介绍的方法输出一下像素值到控制台

cout<<(int)m.at<Vec3b>(0,0)[1]<<',';

cout<<(int)m.at<Vec3b>(0,0)[2]<<endl;


cvWaitKey();

return0;

}


Output5:





End:

Author:Ggicci

谢谢阅读,有误希望指正!

--OpenCV初学者
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: