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

图像处理

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:Region 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每行所占字节数)

       对于多通道字节型图像:

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;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值