OpenCV访问图像像素的方法

  因为OpenCV的版本一直在更新,2.2之前的版本(老方法)和2.2之后版本(新方法)访问图像像素的方法有所不同;2.2之前的更多的是用C来写的,2.2之后用了更多的C++;形式也向matlab靠拢;老的方法可以再新的版本下用,下面分别把两种访问方式的各种方法总结如下:

 

老方法

方法一用IplImage结构体来访问图像像素,用结构体里的数据指针imageDate来访问像素(直接访问)

              程序例子如下:

<span style="font-size:24px;">IplImage* img=cvLoadImage("D:\\matlabpic\\005.bmp",0);//第二个参数0是一通道,1(默认)是3通道
	for (int i=0;i<img->height;i++)       //直接访问
	{
		for (int j=0;j<img->width;j++)     
		{
			((uchar *)(img->imageData+i*img->widthStep))[j]=255;
			
		}
		
	}</span>

这段程序作用非常简单,就是将载入的图像的每个像素都弄成白色,可以很清楚的看出是否真的访问到了每个像素点。

    若是多通道,是每个像素的1、2、3、4通道,然后下一个像素,这样储存的。

                 还有一种写法是这样的

<span style="font-size:24px;">uchar* data=(uchar *)img->imageData;  
    int step = img->widthStep/sizeof(uchar);  
   
    for(int i=0;i<img->height;i++)  
    for(int j=0;j<img->width;j++)  
      data[i*step+j]=0;</span>
跟上边的那段程序没有本质区别,都是用到结构体IplImage中的数据指针imageDate,然后利用一维数组的方法访问。只是看着更清晰一些。


方法二:使用cvGet2D()函数和cvSet2D()函数访问(间接访问)

              cvGet2D()函数获取像素值;返回值类型是CvScalar类型的结构体

             程序例子:

<span style="font-size:24px;">    CvScalar s;
	
for(int y = 0; i < img->height; y++) 
 {    
	for(int x = 0; j < img->width; x++) 
	{      s = cvGet2D(img, i, j);   
	} 
 } </span>
s.val[0],s.val[1],s.val[2],s.val[3],输出不同通道的值,类型为double.


        也可以这样写

<span style="font-size:24px;">double data;  
    for(int i=0;i<img->height;i++)  
    for(int j=0;j<img->width;j++)  
        data =cvGet2D(img,i,j).val[0]; </span>

 

cvSet2D同理

   程序例子:

 CvScalar s;
	  s.val[0]=0;
    for(int i=0;i<img->height;i++)  
    for(int j=0;j<img->width;j++)  
            cvSet2D(img,i,j,s);



新方法

2.2之后引进了类Mat,跟MATLAB中的矩阵有点像,


两条虚线之间是转来的,原po主写的很好了,我也懒的画图了
—— —— —— ——
还是先看Mat的存储形式。Mat和Matlab里的数组格式有点像,但一般是二维向量,如果是灰度图,一般存放 <uchar>类型;如果是RGB彩色图,存放 <Vec3b>类型。
单通道灰度图数据存放格式:

多通道的图像中,每列并列存放通道数量的子列,如RGB三通道彩色图:

注意通道的顺序反转了:BGR。通常情况内存足够大的话图像的每一行是连续存放的,也就是在内存上图像的所有数据存放成一行,这中情况在访问时可以提供很大方便。可以用  isContinuous()函数来判断图像数组是否为连续的。
—— —— —— ——


访问方法如下:

方法一:

Mat类中的成员函数at

程序例子

单通道

 Mat img=imread("D:\\matlabpic\\01.jpg");  //连函数名字都起的和MATLAB一样
<span style="white-space:pre">	</span>imshow("img",img);
for(int i=0;i<img.rows;i++)  
    for(int j=0;j<img.cols;j++)  
		img.at<uchar>(i,j)=0;
多通道

for(int i=0;i<img.rows;i++)  
    for(int j=0;j<img.cols;j++)  
		//img.at<uchar>(i,j)=0;
	{ 
		img.at<Vec3b>(i,j)[0]=10;
		img.at<Vec3b>(i,j)[1]=20;
		img.at<Vec3b>(i,j)[2]=50;
	 }


方法二

Mat类中的成员函数ptr

单通道

for(int i=0;i<img.rows;i++)  
    for(int j=0;j<img.cols* img.channels();j++)
img.ptr<uchar>(i)[j]=0;
多通道

 for(int i=0;i<img.rows;i++)  
    for(int j=0;j<img.cols*img.channels();j++)
{img.ptr<uchar>(i)[j*img.channels()+0]=16;
	 img.ptr<uchar>(i)[j*img.channels()+1]=123;
	 img.ptr<uchar>(i)[j*img.channels()+2]=211;
	 }



还有一点要注意,OPenCV里面多通道是保存的顺序是BGR,刚好和MATLAB里面的RGB相反


找了资料,学习,整理,刚好一天,小疲惫,不过还是蛮开心的。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值