OpenCV学习笔记(一) OpenCV的概…

来源:互联网 发布:学会plc编程工资高吗 编辑:程序博客网 时间:2024/06/06 02:46

  本文主要自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 areaegcontourpolygon

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 bytealignment

Char colorModel[4]

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

2.      矩阵:

A.2D矩阵

CvMat(2D矩阵)

int  type

元素类型

int  step

整行长度字节数

Int  rows,cols

行、列数

int heightwidth

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

Union data

 

 

 

 

Uchar *ptr

指向unsignedchar矩阵的指针

 

Short *s

指向short矩阵的指针

 

Int * i

指向整形矩阵的指针

 

Float *fl

指向浮点型矩阵的指针

 

Double *db

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

BN维矩阵

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 元素间距 字节为单位

CCvSparseMat//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 2D32fp=cvPoint2d32f(float x,float y);//浮点型二维点

Cvpoint3D32fp=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(!imgprintf(“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)

Intheight          =img->height;

Intwidth    =img->width;

IntStep     =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)

RgbImageFloatimgAimg;

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

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

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

【图像转换】

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

cvConcertImagesrc,dst,flags=0

 

src=float/byte  grayscale/colorimage

dst=byte grayscale/colorimae

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

 

原创粉丝点击