Opencv--Iplimage中像素操作

首先,我们要知道几个opencv常用的数据类型:IPlImage。Mat,cvMat。

笔者在一个项目中,花了大量的时间用IplImage类型载入图片,然后转成Mat类型操作,再转成IPlImage类型进行显示,这样做当然是因为Mat矩阵能够轻松的操作,但是也给程序带来冗杂的代码。如下:

<span style="font-size:18px;">IplImage* outputpFrame = NULL;//转IplImage用
IplImage* outputpFr = NULL;
IplImage* outputpBk = NULL;</span>

这样是要建立一个中间变量。所有的形式可以参考IPlImage与Mat,cvMat之间的转换方法代码。

三者的关系之前已经讨论过:http://blog.csdn.net/samkieth/article/details/49475065


那么,我们看看如何对IPlImage直接进行像素操作:

1如果变成灰度图,就是单通道图像,获取的就是每一个像素点的灰度值

IplImage* img = cvLoadImage("yu.jpg", 0);  
for (int i = 0; i < img->height; i++)  
{  
  for (int j = 0; j < img->width; j++)  
  {  
    //方法一:使用cvGet2D()函数间接访问  
    CvScalar s = cvGet2D(img, i, j);//其中i代表y轴(第i行),即height;j代表x轴(第j列),即width。  
    cout<<"gray value="<<s.val[0]<<endl;  
    //方法二:使用直接访问  
    uchar val = ((uchar *)(img->imageData + i*img->widthStep))[j];//i和j的意义同上  
    cout<<"gray value="<<val);  
  }  
}  

2如果是三通道图像,获取的就是每一个像素点的BGR值,然后分别获取B值,G值和R值

IplImage* img = cvLoadImage("test.bmp", 1);  
for (int i = 0; i < img->height; i++)  
{  
  for (int j = 0; j < img->width; j++)  
  {  
    //方法一:使用cvGet2D()函数间接访问  
    CvScalar s=cvGet2D(img,i,j); //其中i代表y轴(第i行),即height;j代表x轴(第j列),即width。  
    cout<<"B="<<s.val[0]<<"G="<<s.val[1]<<"R="<<s.val[2]<<endl;//注意是BGR顺序
  
    //方法二:使用直接访问  
    int bVal = ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]; // B  
    int gVal = ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]; // G  
    int rVal = ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]; // R  
    cout<<"B="<<Bval<<"G="<<Gval<<"R="<<Rval<<endl;//注意是BGR顺序  
  }  
}  


配置好OpenCV以后,包含以下两个头文件:

#include "cv.h"

#include "highgui.h"  

IplImage* image=cvLoadImage("D:\\123.jpg",-1);

//函数cvLoadImage()的第1个参数是图像文件的路径.

//第2个参数是读取图像的方式:-1表示按照图像本身的类型来读取,1表示强制彩色化,0表示

//强制灰值化.

if(image==NULL)

{  

MessageBox("无法读取图像数据!", "提示",MB_OK);

//在MFC工程中这样用  

//若在win32控制台程序中,用printf("无法读取图像数据!\n"); 

return;

//不作任何操作,就不会执行后面的程序了

}

cvNamedWindow("图像显示",CV_WINDOW_AUTOSIZE);

//该函数的功能是按照指定方式创建一个窗口,用于显示图像.

//第1个参数是窗口的名称,自己可以任意设置

//第2个参数表示窗口的大小会自动根据图像尺寸而变化

cvShowImage("图像显示",image);

//该函数的功能是在指定的窗口上显示图像.

//第1个参数是显示图像窗口的名称

//第2个参数是要显示的图像

cvSaveImage("D:\\saveImage.jpg",image);

//该函数的功能是将图像另存为

//第1个参数是保存的路径,自己可以设置其它路径

//第2个参数是要保存的图像

cvWaitKey(0);

//一直等待按键 没有这句的话 图像不能正常显示

cvReleaseImage(&image);

//释放图像内存

cvDestroyWindow("图像显示");

//销毁窗口资源 //,



split函数的主要功能是把一个彩色图像分割成3个通道,方便进一步的图像处理,具体说明如下:

split Divides a multi-channel array into several single-channel arrays.
C++: void split(const Mat& mtx, Mat* mv)
C++: void split(const Mat& mtx, vector& mv)

其实还有一个函数merge可以实现相反的操作,简单说明如下:

merge Composes a multi-channel array from several single-channel arrays.
C++: void merge(const Mat* mv, size_t count, OutputArray dst)
C++: void merge(const vector& mv, OutputArray dst)

其示例代码如下:

#include "stdafx.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include
#include
using namespace cv;
int main( int argc, char** argv )
{
   Mat src, srcOfMerge;
   vector mv;
   /// Read image ( same size, same type )
   src = imread("d:\\images\\WindowsLogo.jpg");
   if( !src.data ) { printf("Error loading src \n"); return -1; }
   split(src,mv);
   /// Create Windows
   namedWindow("RGB", 1);
   namedWindow("R", 1);
   namedWindow("R", 1);
   namedWindow("R", 1);
   namedWindow("srcOfMerge", 1);
   imshow( "RGB", src);
   imshow("R",mv[0]);
   imshow("G",mv[1]);
   imshow("B",mv[2]);
   merge(mv,srcOfMerge);
   imshow("srcOfMerge",srcOfMerge);
   waitKey(0);
   return 0;
}


发布了68 篇原创文章 · 获赞 46 · 访问量 22万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览