本节主要介绍OpenCV中图像分配、释放几种方式和访问图像元素实现方式。
对图像分配和释放操作可以通过以下几种方式实现。
1. 分配图像分配图像的函数原型为:
Iplimage* cvCreateImage(CvSize size, int depth, int channels);其中size可使用函数cvSize(width,height);depth 为像素深度用比特表示,包括以下几种:
channels 为每个像素值的通道数,可以是1,2,3或4.通道是交叉排列的,一幅彩色图通常的排列顺序是B0G0R0B1G1R1B2G2R2.........
例如:分配一个单通道单字节图像的语句和一个3通道浮点数图像的语句是
Ipllmage *im1 = cvCreateImage(cvGet(640,480),IPL_DEPTH_8U,1); //单通道单字节图像 Ipllmage *im2 = cvCreateImage(cvGet(640,480),IPL_DEPTH_32F,3); //3通道浮点数图像
2. 释放图像
释放图像的函数原型为:
void cvReleaseImage(IplImage**);
例如:
Ipllmage *im1 = cvCreateImage(cvGet(640,480),IPL_DEPTH_8U,1); //单通道单字节图像 cvReleaseImage(&im1);
3. 复制图像
复制图像的函数原型为:
Ipllmage*cvCloneImage(Ipllmage*);
4. 设置或得到感兴趣区域ROI
函数原型分别为:
void cvSetImageROI(Ipllmage* image, CvRect rect); void cvResedtImageROI(Ipllmage* image); CvRect cvGetImageROI(const Ipllmage* image);大多数OpenCV函数都支持ROI .
实例:图像反转
图像反转代码
#include <opencv/cv.h> #include <opencv/highgui.h> int main(int argc, char *argv[]) { IplImage* img = cvLoadImage("test.jpg"); if(!img){ printf("Could not load image file\n"); exit(0); } int step,channels; uchar *data; step = img->widthStep; data = (uchar *)img->imageData; cvNamedWindow("Win", CV_WINDOW_AUTOSIZE); cvMoveWindow("Win", 100, 100); for(int i=0;int i<img->height;i++) for(int j=0;j<img->width;j++) for(int k=0;k<img->nChannels;k++) data[i*step+j*(img->nChannels)+k]=255-data[i*step+j*(img->nChannels)+k]; cvShowImage("Win", img ); cvWaitKey(0); cvReleaseImage(&img ); return 0; }输出结果效果:
图1 原始图像 图2测试图像输出结果
假设要访问图像第k通道,第i行、第j列的像素值,那么可采用的方式如下所示:
1.间接方式
这是一种常用的方式,可以访问任何类型的图像,但是效率不高。
对单通道单字节图像可采用如下语句:
Ipllmage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); CvScale sVal = cvGet2D(img,i,j); // get the (i,j) pixel value s.val[0] = 120; cvSet2D(img,i,j,sval); // set the (i,j) pixel value对多通道单字节/浮点数图像可采用如下语句:
Ipllmage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); CvScale sVal = cvGet2D(img,i,j); // get the (i,j) pixel value s.val[0] = 120; s.val[1] = 120; s.val[2] = 120; cvSet2D(img,i,j,sval); // set the (i,j) pixel value
2.直接方式
直接访问效率高,但容易出错。
对单通道单字节图像可采用如下语句:
Ipllmage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); ((uchar*)(img->imageData +i*img->widthStep))[j] = 120;对多通道单字节/浮点数图像可采用如下语句:
Ipllmage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); ((uchar*)(img->imageData +i*img->widthStep))[j*img->nChannels+ 0] = 120; //B ((uchar*)(img->imageData +i*img->widthStep))[j*img->nChannels+ 1] = 120; //G ((uchar*)(img->imageData +i*img->widthStep))[j*img->nChannels+ 2] = 120; //R
3.用指针访问
在某种情况下,这是简单高效的访问方式。
对单通道单字节图像可采用如下语句:
Ipllmage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); int height = img->height; int width = img->width; int step = img->widthStep/sizeof(uchar); uchar* data =(uchar*)img->imageData; data[i*step +j] =120;对多通道单字节/浮点数图像可采用如下语句:
Ipllmage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); int height = img->height; int width = img->width; int step = img->widthStep/sizeof(uchar); int channels = img->nChannels; uchar* data =(uchar*)img->imageData; data[i*step + j*channels + k] =120;
关于Image Engineering & Computer Vision的更多讨论与交流,敬请关注本博和新浪微博songzi_tea.