首先,我们要知道几个opencv常用的数据类型:IPlImage。Mat,cvMat。
笔者在一个项目中,花了大量的时间用IplImage类型载入图片,然后转成Mat类型操作,再转成IPlImage类型进行显示,这样做当然是因为Mat矩阵能够轻松的操作,但是也给程序带来冗杂的代码。如下:
<span style="font-size:18px;">IplImage* outputpFrame = NULL;//转IplImage用 IplImage* outputpFr = NULL; IplImage* outputpBk = NULL;</span>
三者的关系之前已经讨论过: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; }