现在的位置: 首页 > 综合 > 正文

opencv学习笔记

2012年09月25日 ⁄ 综合 ⁄ 共 8035字 ⁄ 字号 评论关闭

1、窗口管理

//创建和定位新窗口
cvNamedWindow("win1", CV_WINDOW_AUTOSIZE); 
cvMoveWindow("win1", 100, 100); // offset from the UL corner of the screen

//载入图像
IplImage* img=0; 
img=cvLoadImage(fileName, CV_LOAD_IMAGE_COLOR);
if(!img) 
printf("Could not load image file: %s\n",fileName);

//显示图像
cvShowImage("win1",img);

//关闭窗口
cvDestroyWindow("win1");

//改变窗口大小
cvResizeWindow("win1",100,100); // new width/heigh in pixels

2、输入处理

处理鼠标事件

//先定义鼠标处理程序
//x,y相对于左上角的像素坐标
void mouseHandler(int event, int x, int y, int flags, void* param)
 {
    switch(event)
{
      case CV_EVENT_LBUTTONDOWN:
        if(flags & CV_EVENT_FLAG_CTRLKEY) 
          printf("Left button down with CTRL pressed\n");
        break; 
 
      case CV_EVENT_LBUTTONUP:
        printf("Left button up\n");
        break;
    }
 }
 //再注册该事件处理程序
 mouseParam=5;
 cvSetMouseCallback("win1",mouseHandler,&mouseParam);  //第三个参数可以设置为NULL
 
 

 处理键盘事件

 
 //按一定间隔检测键盘输入
 int key;
 key=cvWaitKey(10); // wait 10ms for input
 
 //中止程序等待键盘输入
 int key;
 key=cvWaitKey(0); // wait indefinitely for input
 
 //键盘输入循环处理程序
 while(1)
 {
    key=cvWaitKey(10);
    if(key==27) break; 
 
    switch(key)
{
      case 'h':
        ...
        break;
      case 'i':
        ...
        break;
    }
 }
 

 处理滑动条事件

 
 //定义一个滑动条处理程序
 void trackbarHandler(int pos)
 {
    printf("Trackbar position: %d\n",pos);
 }
 
 //注册该事件处理程序
 int trackbarVal=25;
 int maxVal=100;
 cvCreateTrackbar("bar1", "win1", &trackbarVal ,maxVal , trackbarHandler);
 
 //获取当前的滑动条位置
 int pos = cvGetTrackbarPos("bar1","win1");
 
 //设置滑动条位置
 cvSetTrackbarPos("bar1", "win1", 25);
 

 3、图像处理

 

 图像的内存分配与释放

 
 //分配内存给一幅新图像
 //size:cvSize(width,height);depth: 像素深度;channels: 像素通道数. Can be 1, 2, 3 or 4.
 IplImage* cvCreateImage(CvSize size, int depth, int channels);
 
// 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);

//释放图像
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);  // 注意通过cvCloneImage得到的图像
 // 也要用 cvReleaseImage 释放,否则容易产生内存泄漏
 
//设置/获取感兴趣区域ROI
void  cvSetImageROI(IplImage* image, CvRect rect);
void  cvResetImageROI(IplImage* image);
CvRect cvGetImageROI(const IplImage* image);

// 设置/获取感兴趣通道COI
void cvSetImageCOI(IplImage* image, int coi); // 0=all
int cvGetImageCOI(const IplImage* image);

图像读写

//从文件中读入图像
//OpenCV默认将读入的图像强制转换为一幅三通道彩色图像
IplImage* img=0; 
img=cvLoadImage(fileName);
if(!img) 
printf("Could not load image file: %s\n",fileName);  

img=cvLoadImage(fileName,flag);
// flag: >0 将读入的图像强制转换为一幅三通道彩色图像
//       =0 将读入的图像强制转换为一幅单通道灰度图像
//       <0 读入的图像通道数与所读入的文件相同.

//保存图像
if(!cvSaveImage(outFileName,img)) 
printf("Could not save: %s\n", outFileName);

访问图像像素

间接访问,效率低
//对于单通道字节型图像
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

直接访问,效率高
//对于单通道字节型图像
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);
((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

基于指针的直接访问

//对于单通道字节型图像
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;

图像转换

//字节型图像的灰度-彩色转换:
cvConvertImage(src, dst, flags=0);
src = float/byte grayscale/color image
dst = byte grayscale/color image
flags = CV_CVTIMG_FLIP     (垂直翻转图像)
        CV_CVTIMG_SWAP_RB  (置换 R 和 B 通道)

//彩色图像->灰度图像:
// Using the OpenCV conversion: 
cvCvtColor(cimg,gimg,CV_BGR2GRAY); // cimg -> gimg 
 
// Using a direct conversion: 
for(i=0;i<cimg->height;i++) for(j=0;j<cimg->width;j++) 
  gimgA[i][j]= (uchar)(cimgA[i][j].b*0.114 + 
                       cimgA[i][j].g*0.587 + 
                       cimgA[i][j].r*0.299);
  
//不同彩色空间之间的转换:
cvCvtColor(src,dst,code); // src -> dst
 code    = CV_<X>2<Y>
 <X>/<Y> = RGB, BGR, GRAY, HSV, YCrCb, XYZ, Lab, Luv, HLS 
 
 绘图指令
 //绘制矩形:
// 在点 (100,100) 和 (200,200) 之间绘制一矩形,边线用红色、宽度为 1
cvRectangle(img, cvPoint(100,100), cvPoint(200,200), cvScalar(0,0,255), 1);

//绘制圆形:
// 圆心为(100,100)、半径为20. 圆周绿色、宽度为1
cvCircle(img, cvPoint(100,100), 20, cvScalar(0,255,0), 1);

//绘制线段:
// 在 (100,100) 和 (200,200) 之间、线宽为 1 的绿色线段
cvLine(img, cvPoint(100,100), cvPoint(200,200), cvScalar(0,255,0), 1);

//绘制一组线段:
CvPoint  curve1[]={10,10,  10,100,  100,100,  100,10};
CvPoint  curve2[]={30,30,  30,130,  130,130,  130,30,  150,10};
CvPoint* curveArr[2]={curve1, curve2};
int      nCurvePts[2]={4,5};
int      nCurves=2;
int      isCurveClosed=1;
int      lineWidth=1; 
 
cvPolyLine(img,curveArr,nCurvePts,nCurves,isCurveClosed,cvScalar(0,255,255),lineWidth);
 
void cvPolyLine( CvArr* img, CvPoint** pts, int* npts, int contours, int is_closed,
                          CvScalar color, int thickness=1, int line_type=8, int shift=0 );
//img       图像。 
//pts       折线的顶点指针数组。 
//npts     折线的定点个数数组。也可以认为是pts指针数组的大小 
//contours   折线的线段数量。 
//is_closed  指出多边形是否封闭。如果封闭,函数将起始点和结束点连线。 
//color         折线的颜色。 
//thickness  线条的粗细程度。 
//line_type  线段的类型。参见cvLine。 
//shift          顶点的小数点位数

//绘制一组填充颜色的多边形:
cvFillPoly(img,curveArr,nCurvePts,nCurves,cvScalar(0,255,255));
 
//cvFillPoly用于一个单独被多边形轮廓所限定的区域内进行填充。函数可以填充复杂的区域,例如,有漏洞的区域和有交叉点的区域等等。
void cvFillPoly( CvArr* img, CvPoint** pts, int* npts, int contours,CvScalar color, int line_type=8, int shift=0 );
//img           图像。 
//pts           指向多边形的数组指针。 
//npts         多边形的顶点个数的数组。 
//contours   组成填充区域的线段的数量。 
//color         多边形的颜色。 
//line_type  组成多边形的线条的类型。 
//shift          顶点坐标的小数点位数。

//文本标注:
CvFont font;
double hScale=1.0;
double vScale=1.0;
int    lineWidth=1;
cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC, hScale,vScale,0,lineWidth); 
 
cvPutText (img,"My comment",cvPoint(200,400), &font, cvScalar(255,255,0));

4、视频处理

//初始化一个摄像头捕捉器:
CvCapture* capture = cvCaptureFromCAM(0); // capture from video device #0

//初始化一个视频文件捕捉器:
CvCapture* capture = cvCaptureFromAVI("infile.avi");

//捕捉一帧画面:
IplImage* img = 0; 
if(!cvGrabFrame(capture)) // capture a frame 
{             
  printf("Could not grab a frame\n\7");
  exit(0);
}
img=cvRetrieveFrame(capture);           // retrieve the captured frame

//释放视频流捕捉器:
cvReleaseCapture(&capture);

//获取视频流设备信息:
cvQueryFrame(capture); // 在读取视频流信息前,要先执行此操作
int frameH    = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
int frameW    = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
int fps       = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
int numFrames = (int) cvGetCaptureProperty(capture,  CV_CAP_PROP_FRAME_COUNT);

//获取帧图信息:
float posMsec   =       cvGetCaptureProperty(capture, CV_CAP_PROP_POS_MSEC);
int posFrames   = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES);
float posRatio  =       cvGetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO);

//设置从视频文件抓取的第一帧画面的位置:
// start capturing from a relative position of 0.9 of a video file
cvSetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO, (double)0.9);

//初始化视频编写器:
CvVideoWriter *writer = 0;
int isColor = 1;
int fps     = 25;  // or 30
int frameW  = 640; // 744 for firewire cameras
int frameH  = 480; // 480 for firewire cameras
writer=cvCreateVideoWriter("out.avi",CV_FOURCC('P','I','M','1'),
                           fps,cvSize(frameW,frameH),isColor);
  
//保持视频文件:
IplImage* img = 0; 
int nFrames = 50;
for(i=0;i<nFrames;i++){
  cvGrabFrame(capture);          // capture a frame
  img=cvRetrieveFrame(capture);  // retrieve the captured frame
  // img = cvQueryFrame(capture);
  cvWriteFrame(writer,img);      // add the frame to the file
}

//释放视频编写器:
cvReleaseVideoWriter(&writer);    

抱歉!评论已关闭.