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

Opencv--Iplimage中像素操作

2016-02-24 14:20 225 查看
首先,我们要知道几个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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: