Showing posts with label opencv. Show all posts
Showing posts with label opencv. Show all posts

Sunday, 12 September 2010

binding opencv2.1 and python2.6.6 in mac os x snow leopard

Here is my way to solve the Opencv binding problem in Mac, it is not easy to bind Python and Opencv together, and hope it will help for your own mac. and you better have macports install in your computer.

First, you need to download and install Python(i use python2.6.6). and make sure the python locate at /usr/bin, not /opt/local/bin( you can type " which python"), I suggest not to use the python installed via macports, but from the python.org, or the python locate will be "opt/local/bin", which make the opencv binding fail, also the numpy&scipy lib can't be installed from dmg. And you can check the python locations by typing "type -a python". It is said that you can change the python locate using python_select(which can be installed using macports), but seems it don't work for me, so i just simply type "sudo rm /opt/local/bin/python" to remove it, then the python come to "/urs/bin/python".

Second, you need to download the sourcecode of Opencv2.1 follow http://opencv.willowgarage.com/wiki/Mac_OS_X_OpenCV_Port the second way( don't use the mac port), Use cmake and build, if there are any dependency problem, you can use macports to download the required lib. I am not sure whether numpy for python is required for opencv building, but it only be successful built while i have numpy installed.

Third, after python and opencv are correctly installed, you can find out the "cv.so" in your opencv folder, for me is "/Users/flydreamersu/opencv/lib", then in your python, you can write:
>>> import sys
>>> sys.path.append("/Users/flydreamersu/opencv/lib")
>>> import cv

I think opencv is loaded without error.

Tuesday, 15 May 2007

opencv编程入门3

图像处理



分配与释放图像空间




  • 分配图像空间:
    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: 1, 2, 3 or 4.
         注意数据为交叉存取.彩色图像的数据编排为b0 g0 r0 b1 g1 r1 ...

    举例:


    // 分配一个单通道字节图像
    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);



  • 设定/获取兴趣区域:
    void   cvSetImageROI(IplImage* image, CvRect rect);
    void   cvResetImageROI(IplImage* image);
    vRect cvGetImageROI(const IplImage* image);

    大部分OpenCV函数都支持ROI.



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

    大部分OpenCV函数暂不支持COI.





读取存储图像




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

       Supported image formats: 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("Could not save: %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);
      CvScalar s;
      s=cvGet2D(img,i,j); // get the (i,j) pixel value
      printf("intensity=%f\n",s.val[0]);
      s.val[0]=111;
      cvSet2D(img,i,j,s); // set the (i,j) pixel value



    • 对多通道浮点或字节图像:
      IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
      CvScalar s;
      s=cvGet2D(img,i,j); // get the (i,j) 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 (i,j) 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/sizeof(uchar);
      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/sizeof(uchar);
      int channels    = img->nChannels;
      uchar* data     = (uchar *)img->imageData;
      data[i*step+j*channels+k] = 111;



    • 对单通道浮点图像(假设用4字节调整):
      IplImage* img   = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
      int height      = img->height;
      int width       = img->width;
      int step        = img->widthStep/sizeof(float);
      int channels    = img->nChannels;
      float * data     = (float *)img->imageData;
      data[i*step+j*channels+k] = 111;







  • 使用 c++ wrapper 进行直接存取: (简单高效)



    • 对单/多通道字节图像,多通道浮点图像定义一个 c++ wrapper:
      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;








图像转换




  • 转为灰度或彩色字节图像:
    cvConvertImage(src, dst, flags=0);

       src = float/byte grayscale/color image
       dst = byte grayscale/color image
       flags = CV_CVTIMG_FLIP      (flip vertically)
               CV_CVTIMG_SWAP_RB   (swap the R and B channels)



  • 转换彩色图像为灰度图像:



    使用OpenCV转换函数:


    cvCvtColor(cimg,gimg,CV_BGR2GRAY); // cimg -> gimg



    直接转换:


    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

    e.g.: CV_BGR2GRAY, CV_BGR2HSV, CV_BGR2Lab





绘图命令




  • 画长方体:
    // 用宽度为1的红线在(100,100)与(200,200)之间画一长方体
    cvRectangle(img, cvPoint(100,100), cvPoint(200,200), cvScalar(255,0,0), 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);



  • 画内填充色的多边形:
    cvFillPoly(img,curveArr,nCurvePts,nCurves,cvScalar(0,255,255));



  • 添加文本:
    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));

    Other possible fonts:


    CV_FONT_HERSHEY_SIMPLEX, CV_FONT_HERSHEY_PLAIN,
    CV_FONT_HERSHEY_DUPLEX, CV_FONT_HERSHEY_COMPLEX,
    CV_FONT_HERSHEY_TRIPLEX, CV_FONT_HERSHEY_COMPLEX_SMALL,
    CV_FONT_HERSHEY_SCRIPT_SIMPLEX, CV_FONT_HERSHEY_SCRIPT_COMPLEX,



opencv编程入门4




















矩阵操作



分配释放矩阵空间




  • 综述:

    • OpenCV有针对矩阵操作的C语言函数. 许多其他方法提供了更加方便的C++接口,其效率与OpenCV一样.

    • OpenCV将向量作为1维矩阵处理.

    • 矩阵按行存储,每行有4字节的校整.




  • 分配矩阵空间:
    CvMat* cvCreateMat(int rows, int cols, int type);

       type: 矩阵元素类型. 格式为CV_<bit_depth>(S|U|F)C<number_of_channels>.  
       例如: CV_8UC1 表示8位无符号单通道矩阵, CV_32SC2表示32位有符号双通道矩阵.

       例程:
       CvMat* M = cvCreateMat(4,4,CV_32FC1);



  • 释放矩阵空间:
    CvMat* M = cvCreateMat(4,4,CV_32FC1);
    cvReleaseMat(&M);



  • 复制矩阵:
    CvMat* M1 = cvCreateMat(4,4,CV_32FC1);
    CvMat* M2;
    M2=cvCloneMat(M1);



  • 初始化矩阵:
    double a[] = { 1,   2,   3,   4,
                    5,   6,   7,   8,
                    9, 10, 11, 12 };

    CvMat Ma=cvMat(3, 4, CV_64FC1, a);

    另一种方法:


    CvMat Ma;
    cvInitMatHeader(&Ma, 3, 4, CV_64FC1, a);



  • 初始化矩阵为单位阵:
    CvMat* M = cvCreateMat(4,4,CV_32FC1);
    cvSetIdentity(M); // 这里似乎有问题,不成功





存取矩阵元素




  • 假设需要存取一个2维浮点矩阵的第(i,j)个元素.



  • 间接存取矩阵元素:
    cvmSet(M,i,j,2.0); // Set M(i,j)
    t = cvmGet(M,i,j); // Get M(i,j)



  • 直接存取,假设使用4-字节校正:
    CvMat* M     = cvCreateMat(4,4,CV_32FC1);
    int n        = M->cols;
    float *data = M->data.fl;

    data[i*n+j] = 3.0;



  • 直接存取,校正字节任意:
    CvMat* M     = cvCreateMat(4,4,CV_32FC1);
    int    step   = M->step/sizeof(float);
    float *data = M->data.fl;

    (data+i*step)[j] = 3.0;



  • 直接存取一个初始化的矩阵元素:
    double a[16];
    CvMat Ma = cvMat(3, 4, CV_64FC1, a);
    a[i*4+j] = 2.0; // Ma(i,j)=2.0;





矩阵/向量操作




  • 矩阵-矩阵操作:
    CvMat *Ma, *Mb, *Mc;
    cvAdd(Ma, Mb, Mc);       // Ma+Mb    -> Mc
    cvSub(Ma, Mb, Mc);       // Ma-Mb    -> Mc
    cvMatMul(Ma, Mb, Mc);    // Ma*Mb    -> Mc



  • 按元素的矩阵操作:
    CvMat *Ma, *Mb, *Mc;
    cvMul(Ma, Mb, Mc);       // Ma.*Mb   -> Mc
    cvDiv(Ma, Mb, Mc);       // Ma./Mb   -> Mc
    cvAddS(Ma, cvScalar(-10.0), Mc); // Ma.-10 -> Mc




  • 向量乘积:
    double va[] = {1, 2, 3};
    double vb[] = {0, 0, 1};
    double vc[3];

    CvMat Va=cvMat(3, 1, CV_64FC1, va);
    CvMat Vb=cvMat(3, 1, CV_64FC1, vb);
    CvMat Vc=cvMat(3, 1, CV_64FC1, vc);

    double res=cvDotProduct(&Va,&Vb); // 点乘:    Va . Vb -> res
    cvCrossProduct(&Va, &Vb, &Vc);     // 向量积: Va x Vb -> Vc
    end{verbatim}

    注意 Va, Vb, Vc 在向量积中向量元素个数须相同.






  • 单矩阵操作:
    CvMat *Ma, *Mb;
    cvTranspose(Ma, Mb);       // transpose(Ma) -> Mb (不能对自身进行转置)
    CvScalar t = cvTrace(Ma); // trace(Ma) -> t.val[0]
    double d = cvDet(Ma);      // det(Ma) -> d
    cvInvert(Ma, Mb);          // inv(Ma) -> Mb



  • 非齐次线性系统求解:
    CvMat* A   = cvCreateMat(3,3,CV_32FC1);
    CvMat* x   = cvCreateMat(3,1,CV_32FC1);
    CvMat* b   = cvCreateMat(3,1,CV_32FC1);
    cvSolve(&A, &b, &x);     // solve (Ax=b) for x



  • 特征值分析(针对对称矩阵):
    CvMat* A   = cvCreateMat(3,3,CV_32FC1);
    CvMat* E   = cvCreateMat(3,3,CV_32FC1);
    CvMat* l   = cvCreateMat(3,1,CV_32FC1);
    cvEigenVV(&A, &E, &l);   // l = A的特征值 (降序排列)
                             // E = 对应的特征向量 (每行)



  • 奇异值分解SVD:
    CvMat* A   = cvCreateMat(3,3,CV_32FC1);
    CvMat* U   = cvCreateMat(3,3,CV_32FC1);
    CvMat* D   = cvCreateMat(3,3,CV_32FC1);
    CvMat* V   = cvCreateMat(3,3,CV_32FC1);
    cvSVD(A, D, U, V, CV_SVD_U_T|CV_SVD_V_T); // A = U D V^T

    标号使得 U 和 V 返回时被转置(若没有转置标号,则有问题不成功!!!).






视频序列操作



从视频序列中抓取一帧




  • OpenCV支持从摄像头或视频文件(AVI)中抓取图像.



  • 从摄像头获取初始化:
    CvCapture* capture = cvCaptureFromCAM(0); // capture from video device #0



  • 从视频文件获取初始化:
    CvCapture* capture = cvCaptureFromAVI("infile.avi");



  • 抓取帧:
    IplImage* img = 0; 
    if(!cvGrabFrame(capture)){               // 抓取一帧
       printf("Could not grab a frame\n\7");
       exit(0);
    }
    img=cvRetrieveFrame(capture);            // 恢复获取的帧图像

    要从多个摄像头同时获取图像, 首先从每个摄像头抓取一帧. 在抓取动作都结束后再恢复帧图像.  




  • 释放抓取源:
    cvReleaseCapture(&capture);

    注意由设备抓取的图像是由capture函数自动分配和释放的. 不要试图自己释放它.






获取/设定帧信息




  • 获取设备特性:
    cvQueryFrame(capture); // this call is necessary to get correct 
                            // capture properties
    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);

    获取所抓取帧在视频序列中的位置, 从首帧开始按[毫秒]算. 或者从首帧开始从0标号, 获取所抓取帧的标号. 或者取相对位置,首帧为0,末帧为1, 只对视频文件有效.




  • 设定所抓取的第一帧标号:
    // 从视频文件相对位置0.9处开始抓取
    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);

    其他有效编码:


    CV_FOURCC('P','I','M','1')     = MPEG-1 codec
    CV_FOURCC('M','J','P','G')     = motion-jpeg codec (does not work well)
    CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec
    CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 codec
    CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec
    CV_FOURCC('U', '2', '6', '3') = H263 codec
    CV_FOURCC('I', '2', '6', '3') = H263I codec
    CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec

    若把视频编码设为-1则将打开一个编码选择窗口(windows系统下).





  • 存储视频文件:
    IplImage* img = 0; 
    int nFrames = 50;
    for(i=0;i<nFrames;i++){
       cvGrabFrame(capture);           // 抓取帧
       img=cvRetrieveFrame(capture);   // 恢复图像
       cvWriteFrame(writer,img);       // 将帧添加入视频文件
    }

    若想在抓取中查看抓取图像, 可在循环中加入下列代码:


    cvShowImage("mainWin", img); 
    key=cvWaitKey(20);            // wait 20 ms

    若没有20[毫秒]延迟,将无法正确显示视频序列.




  • 释放视频存储器:
    cvReleaseVideoWriter(&writer);







原文地址 http://www.opencv.org.cn/forum/viewtopic.php?t=63&highlight=%E8%A7%86%E9%A2%91

opencv编程入门2

C程序实例




////////////////////////////////////////////////////////////////////////
//
// hello-world.cpp
//
// 一个简单的OpenCV程序
// 它从一个文件中读取图像,将色彩值颠倒,并显示结果.
//
////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <cv.h>
#include <highgui.h>


int main(int argc, char *argv[])
{
   IplImage* img = 0;
   int height,width,step,channels;
   uchar *data;
   int i,j,k;

   if(argc<2){
     printf("Usage: main <image-file-name>\n\7");
     exit(0);
   }

   // 载入图像  
   img=cvLoadImage(argv[1]);
   if(!img){
     printf("Could not load image file: %s\n",argv[1]);
     exit(0);
   }

   // 获取图像数据
   height     = img->height;
   width      = img->width;
   step       = img->widthStep;
   channels   = img->nChannels;
   data       = (uchar *)img->imageData;
   printf("Processing a %dx%d image with %d channels\n",height,width,channels);

   // 创建窗口
   cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE);
   cvMoveWindow("mainWin", 100, 100);

   // 反色图像
   for(i=0;i<height;i++) for(j=0;j<width;j++) for(k=0;k<channels;k++)
     data[i*step+j*channels+k]=255-data[i*step+j*channels+k];

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

   // wait for a key
   cvWaitKey(0);

   // release the image
   cvReleaseImage(&img );
   return 0;
}





GUI命令



窗口管理




  • 创建并放置一个窗口:
       cvNamedWindow("win1", CV_WINDOW_AUTOSIZE); 
       cvMoveWindow("win1", 100, 100); // 以屏幕左上角为起点的偏移量



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



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

    可显示彩色或灰度的字节/浮点图像。 彩色图像数据认定为BGR顺序.




  • 关闭窗口:
       cvDestroyWindow("win1");



  • 改变窗口尺寸:
       cvResizeWindow("win1",100,100); // 新的宽/高值(象素点)






输入设备




  • 响应鼠标事件:

    • 定义鼠标handler:
         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;
           }
         }

         // 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.



    • 直接获取键盘操作:
         int key;
         key=cvWaitKey(10); // 输入等待10ms



    • 等待按键并获取键盘操作:
         int key;
         key=cvWaitKey(0); // 无限等待键盘输入



    • 键盘输入循环:
         while(1){
           key=cvWaitKey(10);
           if(key==27) break;

           switch(key){
             case 'h':
               ...
               break;
             case 'i':
               ...
               break;
           }
         }






  • 处理滚动条事件:

    • 定义滚动条handler:
         void trackbarHandler(int pos)
         {
           printf("Trackbar position: %d\n",pos);
         }



    • 注册handler:
         int trackbarVal=25;
         int maxVal=100;
         cvCreateTrackbar("bar1", "win1", &trackbarVal ,maxVal , trackbarHandler);



    • 获取滚动条当前位置:
         int pos = cvGetTrackbarPos("bar1","win1");



    • 设定滚动条位置:
         cvSetTrackbarPos("bar1", "win1", 25);








OpenCV基础数据结构



图像数据结构




  • IPL 图像:
    IplImage
       |-- int   nChannels;      // 色彩通道数(1,2,3,4)
       |-- int   depth;          // 象素色深:
       |                        //    IPL_DEPTH_8U, IPL_DEPTH_8S,
       |                        //    IPL_DEPTH_16U,IPL_DEPTH_16S,
       |                        //    IPL_DEPTH_32S,IPL_DEPTH_32F,
       |                        //    IPL_DEPTH_64F
       |-- int   width;          // 图像宽度(象素点数)
       |-- int   height;         // 图像高度(象素点数)

       |-- char* imageData;     // 指针指向成一列排列的图像数据
       |                        // 注意色彩顺序为BGR
       |-- int   dataOrder;      // 0 - 彩色通道交叉存取 BGRBGRBGR,
       |                        // 1 - 彩色通道分隔存取 BBBGGGRRR
       |                        // 函数cvCreateImage只能创建交叉存取的图像
       |-- int   origin;         // 0 - 起点为左上角,
       |                        // 1 - 起点为右下角(Windows位图bitmap格式)
       |-- int   widthStep;      // 每行图像数据所占字节大小
       |-- int   imageSize;      // 图像数据所占字节大小 = 高度*每行图像数据字节大小
       |-- struct _IplROI *roi;// 图像ROI. 若不为NULL则表示需要处理的图像
       |                        // 区域.
       |-- char *imageDataOrigin; // 指针指向图像数据原点
       |                           // (用来校准图像存储单元的重新分配)
       |
       |-- int   align;          // 图像行校准: 4或8字节校准
       |                        // OpenCV不采用它而使用widthStep
       |-- char colorModel[4]; // 图像色彩模型 - 被OpenCV忽略






矩阵与向量




  • 矩阵:
    CvMat                       // 2维数组
       |-- int    type;           // 元素类型(uchar,short,int,float,double)
       |-- int    step;           // 一行所占字节长度
       |-- int    rows, cols;     // 尺寸大小
       |-- int    height, width; // 备用尺寸参照
       |-- union data;
          |-- uchar*   ptr;      // 针对unsigned char矩阵的数据指针
           |-- short*   s;        // 针对short矩阵的数据指针
           |-- int*     i;        // 针对integer矩阵的数据指针
           |-- float*   fl;       // 针对float矩阵的数据指针
           |-- double* db;       // 针对double矩阵的数据指针


    CvMatND                     // N-维数组
       |-- int    type;           // 元素类型(uchar,short,int,float,double)
       |-- int    dims;           // 数组维数
       |-- union data;
       |    |-- uchar*   ptr;      // 针对unsigned char矩阵的数据指针
       |    |-- short*   s;        // 针对short矩阵的数据指针
       |    |-- int*     i;        // 针对integer矩阵的数据指针
       |    |-- float*   fl;       // 针对float矩阵的数据指针
       |    |-- double* db;       // 针对double矩阵的数据指针
       |
       |-- struct dim[];         // 每个维的信息
           |-- size;             // 该维内元素个数
           |-- step;             // 该维内元素之间偏移量


    CvSparseMat // 稀疏N维数组



  • 通用数组:
    CvArr*      // 仅作为函数参数,说明函数接受多种类型的数组,例如:
                //     IplImage*, CvMat* 或者 CvSeq*.
                // 只需通过分析数组头部的前4字节便可确定数组类型




  • 标量:
    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]=10.0;

    注意:初始化函数与数据结构同名,只是首字母小写. 它不是C++的构造函数.






其他数据结构




  • 点:
    CvPoint       p = cvPoint(int x, int y);
    CvPoint2D32f p = cvPoint2D32f(float x, float y);
    CvPoint3D32f p = cvPoint3D32f(float x, float y, float z);
    例如:
    p.x=5.0;
    p.y=5.0;



  • 长方形尺寸:
    CvSize        r = cvSize(int width, int height);
    CvSize2D32f   r = cvSize2D32f(float width, float height);



  • 带偏移量的长方形尺寸:
    CvRect        r = cvRect(int x, int y, int width, int height);



OpenCV 编程入门1

OpenCV 编程入门


美国伊力诺理工学院计算机科学系Gady Adam


翻译:Mensch



2006年11月22日






内容






简介



OpenCV概述




  • 什么是OpenCV  

    • 开源C/C++计算机视觉库.

    • 面向实时应用进行优化.

    • 跨操作系统/硬件/窗口管理器.

    • 通用图像/视频载入、存储和获取.

    • 由中、高层API构成.

    • 为Intel®公司的 Integrated Performance Primitives (IPP) 提供了透明接口.




  • 特性:

    • 图像数据操作 (分配,释放, 复制, 设定, 转换).

    • 图像与视频 I/O (基于文件/摄像头输入, 图像/视频文件输出).

    • 矩阵与向量操作与线性代数计算(相乘, 求解, 特征值, 奇异值分解SVD).

    • 各种动态数据结构(列表, 队列, 集, 树, 图).

    • 基本图像处理(滤波, 边缘检测, 角点检测, 采样与插值, 色彩转换, 形态操作, 直方图, 图像金字塔).

    • 结构分析(连接成分, 轮廓处理, 距离转换, 模板匹配, Hough转换, 多边形近似, 线性拟合, 椭圆拟合, Delaunay三角化).

    • 摄像头标定 (寻找并跟踪标定模板, 标定, 基础矩阵估计, homography估计, 立体匹配).

    • 动作分析(光流, 动作分割, 跟踪).

    • 对象辨识 (特征方法, 隐马可夫链模型HMM).

    • 基本GUI(显示图像/视频, 键盘鼠标操作, 滚动条).

    • 图像标识 (直线, 圆锥, 多边形, 文本绘图)




  • OpenCV 模块:

    • cv - OpenCV 主要函数.

    • cvaux - 辅助 (实验性) OpenCV 函数.

    • cxcore - 数据结构与线性代数算法.

    • highgui - GUI函数.






资料链接




  • 参考手册:

    • <opencv-root>/docs/index.htm




  • 网络资源:

    • 官方网页: http://www.intel.com/technology/computing/opencv/



    • 软件下载: http://sourceforge.net/projects/opencvlibrary/






  • 书籍:

    • Open Source Computer Vision Library by Gary R. Bradski, Vadim Pisarevsky, and Jean-Yves Bouguet, Springer, 1st ed. (June, 2006).




  • 视频处理例程 (位于 <opencv-root>/samples/c/目录中):

    • 色彩跟踪: camshiftdemo

    • 点跟踪: lkdemo

    • 动作分割: motempl

    • 边缘检测: laplace




  • 图像处理例程(位于<opencv-root>/samples/c/目录中):

    • 边缘检测: edge

    • 分割: pyramid_segmentation

    • 形态: morphology

    • 直方图: demhist

    • 距离转换: distrans

    • 椭圆拟合 fitellipse







OpenCV 命名约定




  • 函数命名:
         cvActionTarget[Mod](...)

         Action = 核心功能(例如 设定set, 创建create)
         Target = 操作目标 (例如 轮廓contour, 多边形polygon)
         [Mod]   = 可选修饰词 (例如说明参数类型)



  • 矩阵数据类型:
         CV_<bit_depth>(S|U|F)C<number_of_channels>

         S = 带符号整数
         U = 无符号整数
         F = 浮点数

         例:    CV_8UC1 表示一个8位无符号单通道矩阵,
               CV_32FC2 表示一个32位浮点双通道矩阵.



  • 图像数据类型:
         IPL_DEPTH_<bit_depth>(S|U|F)

         例:    IPL_DEPTH_8U 表示一个8位无符号图像.
               IPL_DEPTH_32F 表示一个32位浮点数图像.



  • 头文件:
         #include <cv.h>
         #include <cvaux.h>
         #include <highgui.h>  
         #include <cxcore.h>    // 不必要 - 该头文件已在 cv.h 文件中包含


    编译命令
    Linux系统:

    g++ hello-world.cpp -o hello-world \
         -I /usr/local/include/opencv -L /usr/local/lib   \
         -lm -lcv -lhighgui -lcvaux
    Windows系统:
    注意在项目属性中设好OpenCV头文件以及库文件的路径.

Thursday, 8 March 2007

OpenCv 安装 配置 VC6.0

安装好 opencv 后


编译OpenCV


打开OpenCV安装目录下的_make文件夹,启动其中的opencv.dsw工程(如: C:\OpenCV\_make\opencv.dsw);在vc中选择build----batch build ,所有64位的都不选,然後点build。这样就生成了以後大家经常用到的一些libdll,包括releasedebug两个版本的。


在生成过程中可能会出现如下错误:


         fatal error LNK1181: 无法打开输入文件“cvauxd.lib

         error C2039: foreground_regions: 不是“CvFGDStatModel的成员”

解决的方法是:在“解决方案管理器”中打开“cvaux”项目的包含文件中(Include\External)的cvaux. h文件,找到上述foreground_regions成员,会发现此成员已被注释掉了,只要将其上一行末尾的“/”改为“*/”使该成员可见,再次启动项目,应该就可以编译通过了。 这个问题出现在OpenCV beta5 和 OpenCV RC1版本中,以后的版本会解决这个BUG。


启动_make目录下的另外一个工程“opencv_directshow.dsw” ,使其编译通过;


加入库文件及包含文件的方法


         C:\OpenCV\cv\include

         C:\OpenCV\cvaux\include

         C:\OpenCV\otherlibs\highgui

         C:\OpenCV\cxcore\include

         C:\OpenCV\otherlibs\cvcam\include

(上述文件属于常用文件,如果需要可自行添加另外的包含文件)加入库文件:


         C:\OpenCV\lib

配置项目: 
选择菜单"Project"->"Settings..."以激活项目配置对话框 .
在左边选择你的项目.
调节设置,对 Release 和 Debug 配置都有效:
选择 "Settings For:"->"All Configurations"
选择 "C/C++" tab -> "Preprocessor" category ->
"Additional Include Directories:".

加入用逗号分隔的相对路径 (对文件 .dsp 而言) 或绝对路径d:\opencv\cxcore\include,

d:\opencv\cv\include,d:\opencv\otherlibs\highgui, d:\opencv\cvaux\include(optionally,) 

选择 "Link" tab -> "Input" category -> "Additional library path:". 
加入输入库所在的路径 (cxcore[d].lib cv[d].lib hihghui[d].lib cvaux[d].lib) d:\opencv\lib

调节 "Debug" 配置:

 
选择 "Settings For:"->"Win32 Debug".
选择 "Link" tab -> "General" category -> "Object/library modules".

加入空格分隔的 cvd.lib,cxcored.lib highguid.lib,cvauxd.lib (optionally) 
可以改变输出文件的名称和位置。如想把产生的 .exe 文件放置于项目目录而不是Debug/ 子目录下,

可在 "Link" tab -> "General" category -> "Output file name:" 中键入 ./d.exe  
调节 "Release" 配置 


选择 "Settings For:"->"Win32 Release".
选择 "Link" tab -> "General" category -> "Object/library modules".

加入空格分隔的cv.lib cxcore.lib highgui.lib cvaux.lib (optionally) 



增加从属性项目到 workspace 中:


选择菜单: "Project" -> "Insert project into workspace".
选择 opencv\cv\make\cv.dsp.
同样步骤对opencv\cvaux\make\cvaux.dsp, opencv\otherlibs\highgui\highgui.dsp.
设置从属性:
选择菜单: "Project" -> "Dependencies..."
对 "cv" 选择 "cxcore",
对 "cvaux" 选择 "cv", "cxcore",
对 "highgui" 选择 "cxcore",
对你的项目,选择所有的: "cxcore", "cv", "cvaux", "highgui".
从属性配置保证了在源代码被改变的情况下,自动重新编译 opencv 库.



静态库设置:
   Opencv程序需要静态库设置,其release版本的静态库在系统的lib目录下,

其debug版本的静态库需要重新全编译所有的程序。
动态库设置:
   OPenCV启动时需要一些动态库的支持,这些动态库必须放在系统目录下或者当前目录

下。Cv097.dll,cvaux097.dll,cvcam097.dll,cxcore097.dll,

highguid097.dll,libguide40.dll