data[i*step+j*channels+k]=255-data[i*step+j*channels+k];
//显示图像
cvShowImage("mainWin",img);
//waitforakey
cvWaitKey(0);
//releasetheimage
cvReleaseImage(&img);
return0;
}
∙GUI命令
窗口管理
∙创建并放置一个窗口:
cvNamedWindow("win1",CV_WINDOW_AUTOSIZE);
cvMoveWindow("win1",100,100);//以屏幕左上角为起点的偏移量
∙读入图像:
IplImage*img=0;
img=cvLoadImage(fileName);
if(!
img)printf("Couldnotloadimagefile:
%s\n",fileName);
∙显示图像:
cvShowImage("win1",img);
∙可显示彩色或灰度的字节/浮点图像。
彩色图像数据认定为BGR顺序.
∙关闭窗口:
∙cvDestroyWindow("win1");
∙改变窗口尺寸:
cvResizeWindow("win1",100,100);//新的宽/高值(象素点)
输入设备
∙响应鼠标事件:
∙定义鼠标handler:
voidmouseHandler(intevent,intx,inty,intflags,void*param)
{
switch(event){
caseCV_EVENT_LBUTTONDOWN:
if(flags&CV_EVENT_FLAG_CTRLKEY)
printf("LeftbuttondownwithCTRLpressed\n");
break;
caseCV_EVENT_LBUTTONUP:
printf("Leftbuttonup\n");
break;
}
}
//x,y:
针对左上角的像点坐标
//event:
CV_EVENT_LBUTTONDOWN,CV_EVENT_RBUTTONDOWN,CV_EVENT_MBUTTONDOWN,
//CV_EVENT_LBUTTONUP,CV_EVENT_RBUTTONUP,CV_EVENT_MBUTTONUP,
//CV_EVENT_LBUTTONDBLCLK,CV_EVENT_RBUTTONDBLCLK,CV_EVENT_MBUTTONDBLCLK,
//CV_EVENT_MOUSEMOVE:
//flags:
CV_EVENT_FLAG_CTRLKEY,CV_EVENT_FLAG_SHIFTKEY,CV_EVENT_FLAG_ALTKEY,
//CV_EVENT_FLAG_LBUTTON,CV_EVENT_FLAG_RBUTTON,CV_EVENT_FLAG_MBUTTON
∙注册handler:
mouseParam=5;
cvSetMouseCallback("win1",mouseHandler,&mouseParam);
∙响应键盘事件:
∙键盘没有事件handler.
∙直接获取键盘操作:
intkey;
key=cvWaitKey(10);//输入等待10ms
∙等待按键并获取键盘操作:
intkey;
key=cvWaitKey(0);//无限等待键盘输入
∙键盘输入循环:
while
(1){
key=cvWaitKey(10);
if(key==27)break;
switch(key){
case'h':
...
break;
case'i':
...
break;
}
}
∙处理滚动条事件:
∙定义滚动条handler:
voidtrackbarHandler(intpos)
{
printf("Trackbarposition:
%d\n",pos);
}
∙注册handler:
inttrackbarVal=25;
intmaxVal=100;
cvCreateTrackbar("bar1","win1",&trackbarVal,maxVal,trackbarHandler);
∙获取滚动条当前位置:
intpos=cvGetTrackbarPos("bar1","win1");
∙设定滚动条位置:
cvSetTrackbarPos("bar1","win1",25);
OpenCV基础数据结构
图像数据结构
IPL图像:
IplImage
|--intnChannels;//色彩通道数(1,2,3,4)
|--intdepth;//象素色深:
|//IPL_DEPTH_8U,IPL_DEPTH_8S,
|//IPL_DEPTH_16U,IPL_DEPTH_16S,
|//IPL_DEPTH_32S,IPL_DEPTH_32F,
|//IPL_DEPTH_64F
|--intwidth;//图像宽度(象素点数)
|--intheight;//图像高度(象素点数)
|--char*imageData;//指针指向成一列排列的图像数据
|//注意色彩顺序为BGR
|--intdataOrder;//0-彩色通道交叉存取BGRBGRBGR,
|//1-彩色通道分隔存取BBBGGGRRR
|//函数cvCreateImage只能创建交叉存取的图像
|--intorigin;//0-起点为左上角,
|//1-起点为右下角(Windows位图bitmap格式)
|--intwidthStep;//每行图像数据所占字节大小
|--intimageSize;//图像数据所占字节大小=高度*每行图像数据字节大小
|--struct_IplROI*roi;//图像ROI.若不为NULL则表示需要处理的图像
|//区域.
|--char*imageDataOrigin;//指针指向图像数据原点
|//(用来校准图像存储单元的重新分配)
|
|--intalign;//图像行校准:
4或8字节校准
|//OpenCV不采用它而使用widthStep
|--charcolorModel[4];//图像色彩模型-被OpenCV忽略
矩阵与向量
∙矩阵:
∙CvMat//2维数组
|--inttype;//元素类型(uchar,short,int,float,double)
|--intstep;//一行所占字节长度
|--introws,cols;//尺寸大小
|--intheight,width;//备用尺寸参照
|--uniondata;
|--uchar*ptr;//针对unsignedchar矩阵的数据指针
|--short*s;//针对short矩阵的数据指针
|--int*i;//针对integer矩阵的数据指针
|--float*fl;//针对float矩阵的数据指针
|--double*db;//针对double矩阵的数据指针
CvMatND//N-维数组
|--inttype;//元素类型(uchar,short,int,float,double)
|--intdims;//数组维数
|--uniondata;
||--uchar*ptr;//针对unsignedchar矩阵的数据指针
||--short*s;//针对short矩阵的数据指针
||--int*i;//针对integer矩阵的数据指针
||--float*fl;//针对float矩阵的数据指针
||--double*db;//针对double矩阵的数据指针
|
|--structdim[];//每个维的信息
|--size;//该维内元素个数
|--step;//该维内元素之间偏移量
CvSparseMat//稀疏N维数组
∙通用数组:
CvArr*//仅作为函数参数,说明函数接受多种类型的数组,例如:
//IplImage*,CvMat*或者CvSeq*.
//只需通过分析数组头部的前4字节便可确定数组类型
∙标量:
CvScalar
|--doubleval[4];//4D向量
初始化函数:
∙CvScalars=cvScalar(doubleval0,doubleval1=0,doubleval2=0,doubleval3=0);
∙举例:
CvScalars=cvScalar(20.0);
s.val[0]=10.0;
∙注意:
初始化函数与数据结构同名,只是首字母小写.它不是C++的构造函数.
其他数据结构
∙点:
CvPointp=cvPoint(intx,inty);
CvPoint2D32fp=cvPoint2D32f(floatx,floaty);
CvPoint3D32fp=cvPoint3D32f(floatx,floaty,floatz);
例如:
p.x=5.0;
p.y=5.0;
∙长方形尺寸:
CvSizer=cvSize(intwidth,intheight);
CvSize2D32fr=cvSize2D32f(floatwidth,floatheight);
∙带偏移量的长方形尺寸:
CvRectr=cvRect(intx,inty,intwidth,intheight);
∙图像处理
分配与释放图像空间
∙分配图像空间:
IplImage*cvCreateImage(CvSizesize,intdepth,intchannels);
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:
1,2,3or4.
注意数据为交叉存取.彩色图像的数据编排为b0g0r0b1g1r1...
举例:
//分配一个单通道字节图像
IplImage*img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
//分配一个三通道浮点图像
IplImage*img2=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
∙释放图像空间:
IplImage*img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
cvReleaseImage(&img);
∙复制图像:
IplImage*img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
IplImage*img2;
img2=cvCloneImage(img1);
∙设定/获取兴趣区域:
voidcvSetImageROI(IplImage*image,CvRectrect);
voidcvResetImageROI(IplImage*image);
vRectcvGetImageROI(constIplImage*image);
大部分OpenCV函数都支持ROI.
∙设定/获取兴趣通道:
voidcvSetImageCOI(IplImage*image,intcoi);//0=all
intcvGetImageCOI(constIplImage*image);
大部分OpenCV函数暂不支持COI.
读取存储图像
∙从文件中载入图像:
IplImage*img=0;
img=cvLoadImage(fileName);
if(!
img)printf("Couldnotloadimagefile:
%s\n",fileName);
Supportedimageformats:
BMP,DIB,JPEG,JPG,JPE,PNG,PBM,PGM,PPM,
SR,RAS,TIFF,TIF
载入图像默认转为3通道彩色图像.如果不是,则需加flag:
img=cvLoadImage(fileName,flag);
flag:
>0载入图像转为三通道彩色图像
=0载入图像转为单通道灰度图像
<0不转换载入图像(通道数与图像文件相同).
∙图像存储为图像文件:
if(!
cvSaveImage(outFileName,img))printf("Couldnotsave:
%s\n",outFileName);
输入文件格式由文件扩展名决定.
存取图像元素
∙假设需要读取在i行j列像点的第k通道.其中,行数i的范围为[0,height-1],列数j的范围为[0,width-1],通道k的范围为[0,nchannels-1].
∙间接存取:
(比较通用,但效率低,可读取任一类型图像数据)
∙对单通道字节图像:
IplImage*img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
CvScalars;
s=cvGet2D(img,i,j);//getthe(i,j)pixelvalue
printf("intensity=%f\n",s.val[0]);
s.val[0]=111;
cvSet2D(img,i,j,s);//setthe(i,j)pixelvalue
∙对多通道浮点或字节图像:
IplImage*img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
CvScalars;
s=cvGet2D(img,i,j);//getthe(i,j)pixelvalue
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);//setthe(i,j)pixelvalue
∙直接存取:
(效率高,但容易出错)
∙对单通道字节图像:
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_8U,3);
((ucha