OpenCV的概况和基本数据结构

来源:互联网 发布:如何查看域名注册商 编辑:程序博客网 时间:2024/04/30 00:16

本文主要自OpenCVChina,转载请注明出处http://blog.sina.com.cn/lucyloveayu

OpenCV是一个基于C/C++语言的开源图像处理函数库,其特点有:

1.       代码都是经过优化,可以用于实时处理图像;

2.       具有良好的可移植性;

3.       可以进行图像/视频的载入、保存和采集的常规操作;

4.       具有低级和高级的API

5.       提供了面向Intel IPP高效多媒体函数的接口,可以针对使用的IntelCPU优化代码,提高程序新跟那个(OpenCV自从2.0版本以后已经不需IPP,所以不再提供相关的接口)

OpenCV功能】

1.       图像数据操作(内存分配与释放,图像复制,设定和转换);

2.       图像/视频的输入和输出(支持文件或者摄像头的输入,图像/视频文件的输出;

3.       矩阵/向量的数据操作以及线性代数运算(矩阵乘积、矩阵方程求解、特征值、

奇异值分解);

4.       支持多种动态数据结构(链表、队列、数据集、树、图);

5.       基本图像处理(去噪、边缘检测、角点检测、采样与插值、色彩变换、形态学处理、直方图、图像金字塔结构);

6.       结构分析(连通域/分支、轮廓处理、距离转换、图像矩、模板匹配、霍夫变幻、多项式逼近、曲线拟合、椭圆拟合、狄劳尼三角化;

7.       摄像头定标(寻找和跟踪定标模式、参数定标、基本矩阵估计、单位矩阵估计、立体视觉匹配);

8.       运动分析(光流、动作分割、目标跟踪);

9.       目标识别(特征方法、HMM模型);

10.   基本的GUI(显示图像/视频、键盘/鼠标操作、滑动条);

11.   图像标注(直线、曲线、多边形、文本标注)。

OpenCV基本模块】

cv——核心函数库

cvaux——辅助函数库

cxcore——数据结构与线性代数库

highgui——GUI函数库

ml——机器学习函数库

 


OpenCV命名规则】

A.      函数名

cvActionTargetMod(…)

 

Action=核心功能(core functionality)(egsetcreate

Target=目标图像区域(target image area egcontourpolygon

Mod=(可选的)调整语(optional modifiers(eg:argument type)

B.      矩阵数据类型

CV_(S|U|F)

 

S=符号整形

U=无符号整形

F=浮点型

 

egCV_8UC1是指一个8位无符号整形单通道矩阵,

             CV_32FC2是指一个32位浮点型双通道矩阵)

C.      图像数据类型

IPL_DEPTH(S|U|F)

Eg:

IPL_DEPTH_8U图像像素数据是8位无符号整形。

IPL_DEPTH_32P图像像素数据是32位浮点型。

【头文件包含】

#include——核心函数库

#include——辅助函数库

#include——机器学习库

#include——GUI函数库

#include//一般不需要,因为cv.h已经包含该头文件 数据结构与线性代数库

 

 

 

OpenCV中的基本数据结构】

1.       图像数据结构

A.      IPL图像

IPLImage

Int  nChannels

颜色通道的数目(1,2,3,4

Int  depth

像素的位深

IPL_DEPTH_8U

IPL_DEPTH_16S

IPL_DEPTH_32F

IPL_DEPTH_64F

Int width

图像宽度(像素为单位)

Int height

图像高度

Char * imageData

图像数据指针

彩色图像按照BGR的顺序存储数据

Int dataOrder

0——将像素点不同的通道的值交错排在一起,形成单一的像素平面

1——把所有的像素同通道值排在一起,形成若干个通道平面,再把平面排列起来

Int origin

0 –像素原点=左上角

1 –像素原点为左下角(windows bitmaps

Style

Int widthStep

相邻行的同列点之间的字节数

Int imageSize

图像的大小(字节为单位)=height*widthStep

Struct _IplROI *roi

图像的感兴区域(ROI),ROI非空的会后对图像的处理仅限于ROI区域

Char *imageDataOrigin

图像数据未对齐时候的数据原点指针

(需要正确地重新分配图像内存)

Int align

图像数据的行对齐 4 or 8 byte alignment

Char colorModel[4]

颜色模型(OpenCV中没有此项)

2.       矩阵:

A.2D矩阵

CvMat(2D矩阵)

int  type

元素类型

int  step

整行长度字节数

Int  rows,cols

行、列数

int heightwidth

矩阵高度、宽度、与rowscols对应

Union data

 

 

 

 

Uchar *ptr

指向unsigned char矩阵的指针

 

Short *s

指向short矩阵的指针

 

Int * i

指向整形矩阵的指针

 

Float *fl

指向浮点型矩阵的指针

 

Double *db

指向双精度浮点型矩阵的指针

B N维矩阵

CvMatND(N-维矩阵)

Int  type

元素类型(uchar,short,int,float,double

Int dims

矩阵维数

Union   data

Uchar *Ptr

Short *s

Int  * I;

Float  *fl;

Double *db

Struct dim[]

各维信息

 

Size 元素数目

Step 元素间距 字节为单位

C CvSparseMat //N-维稀疏矩阵

D.一般矩阵

           CvArr* //仅仅作为函数定义的参数使用

                    //表明函数可以接受不同类型的矩阵作为参数

                    //矩阵的类型通过矩阵头部的前4个字节信息来确定

E标量

CvScalar  double   val[4] //4D向量

初始化:

CvScalar  s=cvScalar(double  val0,double  val1=0, double val2=0, double  val3=0);

CvScalar  s=cvScalar(20.0);

s.val[0]=20.0

 

3.       

CvPoint  p=cvPoint(int  x,int y);  //整形二维点

CvPoint 2D32f p=cvPoint2d32f(float x,float y);//浮点型二维点

Cvpoint3D32f p=cvPoint3D32f(float x,float y,float z);//浮点型三维点

4.       矩形框大小   (以像素为精度)

cvSize= cvSizeint widthint height

CvSize2D32f  r=cvSize2D32f(float width,float height);

 

5.       矩形框的偏置和大小:

CvRect  r=cvRectint  x, int  y, int width , int height

 

OpenCV的图像读写】

1.       从文件中读入图像:

OpenCV默认将读入的图像强制转换为一副三通道彩色图像:

IplImage *  img=0

Img=cvLoadImagefileName);

If(!img printf(“could  not  load  image file :% s\n”,filename;

OpenCV支持图像格式有:BMPDIBJPEGJPEPNGPBMPGMPPMSRRASTIFFTIF

可以按照如下的方式修改读入的方式:

     img=cvLoadImage(filename,flag)

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

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

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

2.       保存图像

If(!cvSaveImage(outFileName,img)) printf(“could not save :%s\n”,outFileName)

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

OpenCV访问图像像素】

         假设现在需要访问第k通道、第i行,第j列的像素,可以有如下的间接和直接访问两种方式:

1.       间接访问(单通道字节型图像)

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

CvScalar  s;

S=cvGet2D(img,i,j);//注意本函数中坐标参数的顺序与其它的openCV函数坐标参数顺序恰好相反,本函数中的i代表height,而j代表width

Printf(“intensity=%f\n”,s.val[0]);

s.val[0]=111;

cvSet2DimgI,j,s; //设置imgJi)位置的像素值为s

         间接访问(多通道字节型/浮点型图像)

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

         cvScalar s;

         s=cvGet2D(img,I,j)  //得到(ji)位置的像素值

         printf(“B=%fG=%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)//设置img的(ji)位置的像素的值为s

2.       直接访问(效率很高,但是很容易出错)

单通道字节型图像:

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

((uchar* )(img->imageData+i*img->widthstep))[j]=111;

多通道字节型图像:

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

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

((ucahr *)(img->imageData+i*img->widthStep))[j*img->nChannels+1]=112

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

多通道浮点型图像:

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

3.       基于指针的直接访问

单通道字节型图像:

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*setp+j]=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->nChanns

                   float *data       =float *img->imageData

                   data[i*step+j*Channels+k]=111

4.       基于C++ wrapper的直接访问(更加简单高效)

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

Template 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      RgbImage;

typedef      Image RgbImageFloat;

typedef      Image BwImage;

typedef      image            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_32F3)

RgbImageFloat imgAimg;

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

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

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

【图像转换】

1)  字节型图像的灰度——彩色转换

cvConcertImagesrc,dst,flags=0

 

src=float/byte  grayscale/color image

dst=byte grayscale/color imae

flags=CV_CVTIMG_FLIP     //垂直翻转图像

     CV_CVTIMG_SWAP_RB  //置换RB通道

2)  彩色图像->灰度图像

cvCvtColorcimggimgCV_BGR2GRAY  //cimg->gimg

//使用直接转换

for(i=0;iheight;i++)

for(j=0;jwidth;j++)

         gimgA[i][j]=(uchar)(cimgA[i][j].b*0.114+  //直接利用转换关系将图像用灰阶表示

                                                cimgA[i][j].g*0.587+

                                                cimgA[i][j].r*0.299);

3)  不同彩色空间之间的转换

cvCvColorsrcdstcode

code=CV_2

/=RGB,BGR,GRAY,HSV,YCrCb,XYZ,Lab,Luv,HLS

0 0