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

OpenCv入门(三)-图像处理基本函数01

2017-12-28 16:53 591 查看
图像处理

1、图像的内存分配与释放

(1) 分配内存给一幅新图像:

IplImage* cvCreateImage(CvSize size, int depth, int channels);

size: cvSize(width,height);

depth: 像素深度: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,

IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F, IPL_DEPTH_64F

channels: 像素通道数. Can be 1, 2, 3 or 4.

各通道是交错排列的. 一幅彩色图像的数据排列格式如下:

b0 g0 r0 b1 g1 r1 ...

示例:

// Allocate a 1-channel byte image

IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);

// Allocate a 3-channel float image

IplImage* img2=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);

(2) 释放图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);

cvReleaseImage(&img);

3) 复制图像:

IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);

IplImage* img2;

img2=cvCloneImage(img1); // 注意通过cvCloneImage得到的图像

// 也要用 cvReleaseImage 释放,否则容易产生内存泄漏

(4) 设置/获取感兴趣区域ROI: (ROI:R
4000
egion Of Interest)

void cvSetImageROI(IplImage* image, CvRect rect);

void cvResetImageROI(IplImage* image);

CvRect cvGetImageROI(const IplImage* image);

大多数OpenCV函数都支持 ROI.

(5) 设置/获取感兴趣通道COI: (COI:channel of interest)

void cvSetImageCOI(IplImage* image, int coi); // 0=all

int cvGetImageCOI(const IplImage* image);

大多数OpenCV函数不支持 COI.

2、图像读写

(1) 从文件中读入图像:

IplImage* img=0;

img=cvLoadImage(fileName);

if(!img) printf("Could not load image file: %s\n",fileName);

支持的图像格式: BMP, DIB, JPEG, JPG, JPE, PNG, PBM, PGM, PPM,

SR, RAS, TIFF, TIF

OpenCV默认将读入的图像强制转换为一幅三通道彩色图像. 不过可以按以下方法修改读入方式:

img=cvLoadImage(fileName,flag);

flag: >0 将读入的图像强制转换为一幅三通道彩色图像

=0 将读入的图像强制转换为一幅单通道灰度图像

<0 读入的图像通道数与所读入的文件相同.

(2) 保存图像:

if(!cvSaveImage(outFileName,img)) printf("Could not save: %s\n", outFileName);

保存的图像格式由 outFileName 中的扩展名确定.



3、访问图像像素

(1) 假设你要访问第k通道、第i行、第j列的像素。

(2) 间接访问: (通用,但效率低,可访问任意格式的图像)

对于单通道字节型图像

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);

CvScalar s;

s=cvGet2D(img,i,j); // get the (j,i) pixel value, 注意cvGet2D与cvSet2D中坐标参数的顺序与其它opencv函数坐标参数顺序恰好相反.本函数中i代表y轴,即height;j代表x轴,即weight.

printf("intensity=%f\n",s.val[0]);

s.val[0]=111;

cvSet2D(img,i,j,s); // set the (j,i) pixel value

对于多通道字节型/浮点型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);

CvScalar s;

s=cvGet2D(img,i,j); // get the (j,i) pixel value

printf("B=%f, G=%f, R=%f\n",s.val[0],s.val[1],s.val[2]);

s.val[0]=111;

s.val[1]=111;

s.val[2]=111;

cvSet2D(img,i,j,s); // set the (j,i) pixel value



(3) 直接访问: (效率高,但容易出错)

对于单通道字节型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);

((uchar *)(img->imageData + i*img->widthStep))[j]=111; (img->imageData即数组首指针,i为行数,img->widthStep每行所占字节数)

&nb
f5e1
sp; 对于多通道字节型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);

((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B

((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G

((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R

对于多通道浮点型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);

((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B

((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G

((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R



(4) 基于指针的直接访问: (简单高效)

对于单通道字节型图像:

IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);

int height = img->height;

int width = img->width;

int step = img->widthStep;

uchar* data = (uchar *)img->imageData;

data[i*step+j] = 111;

对于多通道字节型图像:

IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);

int height = img->height;

int width = img->width;

int step = img->widthStep;

int channels = img->nChannels;

uchar* data = (uchar *)img->imageData;

data[i*step+j*channels+k] = 111;

对于多通道浮点型图像(假设图像数据采用4字节(32位)行对齐方式):

IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);

int height = img->height;

int width = img->width;

int step = img->widthStep;

int channels = img->nChannels;

float * data = (float *)img->imageData;

data[i*step+j*channels+k] = 111;



(5) 基于 c++ wrapper 的直接访问: (更简单高效) (封装?C++封装没怎么学,要用再仔细学)

首先定义一个 c++ wrapper ‘Image’,然后基于Image定义不同类型的图像:

template<class T> class Image

{

private:

IplImage* imgp;

public:

Image(IplImage* img=0) {imgp=img;}

~Image(){imgp=0;}

void operator=(IplImage* img) {imgp=img;}

inline T* operator[](const int rowIndx) {

return ((T *)(imgp->imageData + rowIndx*imgp->widthStep));}

};

typedef struct{

unsigned char b,g,r;

} RgbPixel;

typedef struct{

float b,g,r;

} RgbPixelFloat;

typedef Image<RgbPixel> RgbImage;

typedef Image<RgbPixelFloat> RgbImageFloat;

typedef Image<unsigned char> BwImage;

typedef Image<float> BwImageFloat;

对于单通道字节型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);

BwImage imgA(img);

imgA[i][j] = 111;

对于多通道字节型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);

RgbImage imgA(img);

imgA[i][j].b = 111;

imgA[i][j].g = 111;

imgA[i][j].r = 111;

对于多通道浮点型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);

RgbImageFloat imgA(img);

imgA[i][j].b = 111;

imgA[i][j].g = 111;

imgA[i][j].r = 111;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: