⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c+m+b mmvi opencv 编程入门.htm

📁 When I use opencv, I use this very useful paper to begin the study. This is all I searched from the
💻 HTM
📖 第 1 页 / 共 5 页
字号:
      <P></P>
      <UL>
        <LI>响应鼠标事件: 
        <UL>
          <LI>定义鼠标handler: <PRE>  void mouseHandler(int event, int x, int y, int flags, void* param)<BR>  {<BR>    switch(event){<BR>      case CV_EVENT_LBUTTONDOWN:<BR>        if(flags &amp; CV_EVENT_FLAG_CTRLKEY) <BR>          printf("Left button down with CTRL pressed\n");<BR>        break;<BR><BR>      case CV_EVENT_LBUTTONUP:<BR>        printf("Left button up\n");<BR>        break;<BR>    }<BR>  }<BR><BR>  // x,y:   针对左上角的像点坐标<BR><BR>  // event: CV_EVENT_LBUTTONDOWN,   CV_EVENT_RBUTTONDOWN,   CV_EVENT_MBUTTONDOWN,<BR>  //        CV_EVENT_LBUTTONUP,     CV_EVENT_RBUTTONUP,     CV_EVENT_MBUTTONUP,<BR>  //        CV_EVENT_LBUTTONDBLCLK, CV_EVENT_RBUTTONDBLCLK, CV_EVENT_MBUTTONDBLCLK,<BR>  //        CV_EVENT_MOUSEMOVE:<BR><BR>  // flags: CV_EVENT_FLAG_CTRLKEY, CV_EVENT_FLAG_SHIFTKEY, CV_EVENT_FLAG_ALTKEY,<BR>  //        CV_EVENT_FLAG_LBUTTON, CV_EVENT_FLAG_RBUTTON,  CV_EVENT_FLAG_MBUTTON<BR></PRE>
          <P></P>
          <LI>注册handler: <PRE>  mouseParam=5;<BR>  cvSetMouseCallback("win1",mouseHandler,&amp;mouseParam);<BR></PRE>
          <P></P></LI></UL>
        <P></P>
        <P></P>
        <LI>响应键盘事件: 
        <UL>
          <LI>键盘没有事件handler. 
          <P></P>
          <LI>直接获取键盘操作: <PRE>  int key;<BR>  key=cvWaitKey(10); // 输入等待10ms<BR></PRE>
          <P></P>
          <LI>等待按键并获取键盘操作: <PRE>  int key;<BR>  key=cvWaitKey(0); // 无限等待键盘输入<BR></PRE>
          <P></P>
          <LI>键盘输入循环: <PRE>  while(1){<BR>    key=cvWaitKey(10);<BR>    if(key==27) break;<BR><BR>    switch(key){<BR>      case 'h':<BR>        ...<BR>        break;<BR>      case 'i':<BR>        ...<BR>        break;<BR>    }<BR>  }<BR></PRE>
          <P></P></LI></UL>
        <P></P>
        <LI>处理滚动条事件: 
        <UL>
          <LI>定义滚动条handler: <PRE>  void trackbarHandler(int pos)<BR>  {<BR>    printf("Trackbar position: %d\n",pos);<BR>  }<BR></PRE>
          <P></P>
          <LI>注册handler: <PRE>  int trackbarVal=25;<BR>  int maxVal=100;<BR>  cvCreateTrackbar("bar1", "win1", &amp;trackbarVal ,maxVal , trackbarHandler);<BR></PRE>
          <P></P>
          <LI>获取滚动条当前位置: <PRE>  int pos = cvGetTrackbarPos("bar1","win1");<BR></PRE>
          <P></P>
          <LI>设定滚动条位置: <PRE>  cvSetTrackbarPos("bar1", "win1", 25);<BR></PRE>
          <P></P></LI></UL>
        <P></P></LI></UL>
      <P></P>
      <H1><A>OpenCV基础数据结构</A> </H1>
      <P></P>
      <H2><A>图像数据结构</A> </H2>
      <P></P>
      <UL>
        <LI>IPL 图像: <PRE>IplImage<BR>  |-- int  nChannels;     // 色彩通道数(1,2,3,4)<BR>  |-- int  depth;         // 象素色深: <BR>  |                       //   IPL_DEPTH_8U, IPL_DEPTH_8S, <BR>  |                       //   IPL_DEPTH_16U,IPL_DEPTH_16S, <BR>  |                       //   IPL_DEPTH_32S,IPL_DEPTH_32F, <BR>  |                       //   IPL_DEPTH_64F<BR>  |-- int  width;         // 图像宽度(象素点数)<BR>  |-- int  height;        // 图像高度(象素点数)<BR><BR>  |-- char* imageData;    // 指针指向成一列排列的图像数据<BR>  |                       // 注意色彩顺序为BGR<BR>  |-- int  dataOrder;     // 0 - 彩色通道交叉存取 BGRBGRBGR, <BR>  |                       // 1 - 彩色通道分隔存取 BBBGGGRRR<BR>  |                       // 函数cvCreateImage只能创建交叉存取的图像<BR>  |-- int  origin;        // 0 - 起点为左上角,<BR>  |                       // 1 - 起点为右下角(Windows位图bitmap格式)<BR>  |-- int  widthStep;     // 每行图像数据所占字节大小<BR>  |-- int  imageSize;     // 图像数据所占字节大小 = 高度*每行图像数据字节大小<BR>  |-- struct _IplROI *roi;// 图像ROI. 若不为NULL则表示需要处理的图像<BR>  |                       // 区域.<BR>  |-- char *imageDataOrigin; // 指针指向图像数据原点<BR>  |                          // (用来校准图像存储单元的重新分配)<BR>  |<BR>  |-- int  align;         // 图像行校准: 4或8字节校准<BR>  |                       // OpenCV不采用它而使用widthStep<BR>  |-- char colorModel[4]; // 图像色彩模型 - 被OpenCV忽略<BR></PRE>
        <P></P></LI></UL>
      <P></P>
      <P></P>
      <H2><A>矩阵与向量</A> </H2>
      <P></P>
      <UL>
        <LI>矩阵: <PRE>CvMat                      // 2维数组<BR>  |-- int   type;          // 元素类型(uchar,short,int,float,double)<BR>  |-- int   step;          // 一行所占字节长度<BR>  |-- int   rows, cols;    // 尺寸大小<BR>  |-- int   height, width; // 备用尺寸参照<BR>  |-- union data;<BR>     |-- uchar*  ptr;     // 针对unsigned char矩阵的数据指针<BR>      |-- short*  s;       // 针对short矩阵的数据指针<BR>      |-- int*    i;       // 针对integer矩阵的数据指针<BR>      |-- float*  fl;      // 针对float矩阵的数据指针<BR>      |-- double* db;      // 针对double矩阵的数据指针<BR><BR><BR>CvMatND                    // N-维数组<BR>  |-- int   type;          // 元素类型(uchar,short,int,float,double)<BR>  |-- int   dims;          // 数组维数<BR>  |-- union data;<BR>  |   |-- uchar*  ptr;     // 针对unsigned char矩阵的数据指针<BR>  |   |-- short*  s;       // 针对short矩阵的数据指针<BR>  |   |-- int*    i;       // 针对integer矩阵的数据指针<BR>  |   |-- float*  fl;      // 针对float矩阵的数据指针<BR>  |   |-- double* db;      // 针对double矩阵的数据指针<BR>  |<BR>  |-- struct dim[];        // 每个维的信息<BR>      |-- size;            // 该维内元素个数<BR>      |-- step;            // 该维内元素之间偏移量<BR><BR><BR>CvSparseMat // 稀疏N维数组<BR></PRE>
        <P></P>
        <LI>通用数组: <PRE>CvArr*     // 仅作为函数参数,说明函数接受多种类型的数组,例如:<BR>           //    IplImage*, CvMat* 或者 CvSeq*. <BR>           // 只需通过分析数组头部的前4字节便可确定数组类型</PRE>
        <P></P>
        <P></P>
        <LI>标量: <PRE>CvScalar<BR>  |-- double val[4]; //4D向量<BR></PRE>
        <P>初始化函数: </P><PRE>CvScalar s = cvScalar(double val0, double val1=0, double val2=0, double val3=0);<BR></PRE>
        <P>举例: </P><PRE>CvScalar s = cvScalar(20.0);<BR>s.val[0]=10.0;<BR></PRE>
        <P>注意:初始化函数与数据结构同名,只是首字母小写. 它不是C++的构造函数. </P>
        <P></P></LI></UL>
      <P></P>
      <H2><A>其他数据结构</A> </H2>
      <P></P>
      <UL>
        <LI>点: <PRE>CvPoint      p = cvPoint(int x, int y);<BR>CvPoint2D32f p = cvPoint2D32f(float x, float y);<BR>CvPoint3D32f p = cvPoint3D32f(float x, float y, float z);<BR>例如:<BR>p.x=5.0;<BR>p.y=5.0;<BR></PRE>
        <P></P>
        <LI>长方形尺寸: <PRE>CvSize       r = cvSize(int width, int height);<BR>CvSize2D32f  r = cvSize2D32f(float width, float height);<BR></PRE>
        <P></P>
        <LI>带偏移量的长方形尺寸: <PRE>CvRect       r = cvRect(int x, int y, int width, int height);<BR></PRE>
        <P></P></LI></UL>
      <P></P>
      <P></P>
      <H1><A>图像处理</A> </H1>
      <P></P>
      <H2><A>分配与释放图像空间</A> </H2>
      <P></P>
      <UL>
        <LI>分配图像空间: <PRE>IplImage* cvCreateImage(CvSize size, int depth, int channels);<BR><BR>  size:  cvSize(width,height);<BR><BR>  depth: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,<BR>         IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F, IPL_DEPTH_64F<BR><BR>  channels: 1, 2, 3 or 4. <BR>    注意数据为交叉存取.彩色图像的数据编排为b0 g0 r0 b1 g1 r1 ...<BR></PRE>
        <P>举例: </P><PRE>// 分配一个单通道字节图像<BR>IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); <BR><BR>// 分配一个三通道浮点图像<BR>IplImage* img2=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);<BR></PRE>
        <P></P>
        <LI>释放图像空间: <PRE>IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); <BR>cvReleaseImage(&amp;img);<BR></PRE>
        <P></P>
        <LI>复制图像: <PRE>IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); <BR>IplImage* img2;<BR>img2=cvCloneImage(img1);<BR></PRE>
        <P></P>
        <LI>设定/获取兴趣区域: <PRE>void  cvSetImageROI(IplImage* image, CvRect rect);<BR>void  cvResetImageROI(IplImage* image);<BR>vRect cvGetImageROI(const IplImage* image);<BR><BR>大部分OpenCV函数都支持ROI.<BR></PRE>
        <P></P>
        <LI>设定/获取兴趣通道: <PRE>void cvSetImageCOI(IplImage* image, int coi); // 0=all<BR>int cvGetImageCOI(const IplImage* image);<BR><BR>大部分OpenCV函数暂不支持COI.<BR></PRE>
        <P></P></LI></UL>
      <P></P>
      <H2><A>读取存储图像</A> </H2>
      <P></P>
      <UL>
        <LI>从文件中载入图像: <PRE>  IplImage* img=0; <BR>  img=cvLoadImage(fileName);<BR>  if(!img) printf("Could not load image file: %s\n",fileName);<BR><BR>  Supported image formats: BMP, DIB, JPEG, JPG, JPE, PNG, PBM, PGM, PPM,<BR>                           SR, RAS, TIFF, TIF<BR></PRE>
        <P>载入图像默认转为3通道彩色图像. 如果不是,则需加flag: </P><PRE>  img=cvLoadImage(fileName,flag);<BR><BR>  flag: &gt;0 载入图像转为三通道彩色图像<BR>        =0 载入图像转为单通道灰度图像<BR>        &lt;0 不转换载入图像(通道数与图像文件相同).<BR></PRE>
        <P></P>
        <LI>图像存储为图像文件: <PRE>  if(!cvSaveImage(outFileName,img)) printf("Could not save: %s\n",outFileName);<BR></PRE>
        <P>输入文件格式由文件扩展名决定. </P>
        <P></P></LI></UL>
      <P></P>
      <H2><A>存取图像元素</A> </H2>
      <P></P>
      <UL>
        <LI>假设需要读取在i行j列像点的第k通道. 其中, 行数i的范围为[0, height-1], 列数j的范围为[0, width-1], 
        通道k的范围为[0, nchannels-1]. 
        <P></P>
        <LI><EM>间接存取:</EM> (比较通用, 但效率低, 可读取任一类型图像数据) 
        <P></P>
        <UL>
          <LI>对单通道字节图像: <PRE>IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);<BR>CvScalar s;<BR>s=cvGet2D(img,i,j); // get the (i,j) pixel value<BR>printf("intensity=%f\n",s.val[0]);<BR>s.val[0]=111;<BR>cvSet2D(img,i,j,s); // set the (i,j) pixel value<BR></PRE>
          <P></P>
          <LI>对多通道浮点或字节图像: <PRE>IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);<BR>CvScalar s;<BR>s=cvGet2D(img,i,j); // get the (i,j) pixel value<BR>printf("B=%f, G=%f, R=%f\n",s.val[0],s.val[1],s.val[2]);<BR>s.val[0]=111;<BR>s.val[1]=111;<BR>s.val[2]=111;<BR>cvSet2D(img,i,j,s); // set the (i,j) pixel value<BR></PRE>
          <P></P></LI></UL>
        <P></P>
        <LI><EM>直接存取:</EM> (效率高, 但容易出错) 
        <P></P>
        <UL>
          <LI>对单通道字节图像: <PRE>IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);<BR>((uchar *)(img-&gt;imageData + i*img-&gt;widthStep))[j]=111;<BR></PRE>
          <P></P>
          <LI>对多通道字节图像: <PRE>IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);<BR>((uchar *)(img-&gt;imageData + i*img-&gt;widthStep))[j*img-&gt;nChannels + 0]=111; // B<BR>((uchar *)(img-&gt;imageData + i*img-&gt;widthStep))[j*img-&gt;nChannels + 1]=112; // G<BR>((uchar *)(img-&gt;imageData + i*img-&gt;widthStep))[j*img-&gt;nChannels + 2]=113; // R<BR></PRE>
          <P></P>
          <LI>对多通道浮点图像: <PRE>IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);<BR>((float *)(img-&gt;imageData + i*img-&gt;widthStep))[j*img-&gt;nChannels + 0]=111; // B<BR>((float *)(img-&gt;imageData + i*img-&gt;widthStep))[j*img-&gt;nChannels + 1]=112; // G<BR>((float *)(img-&gt;imageData + i*img-&gt;widthStep))[j*img-&gt;nChannels + 2]=113; // R<BR></PRE>
          <P></P></LI></UL>
        <P></P>
        <LI><EM>用指针直接存取 :</EM> (在某些情况下简单高效) 
        <P></P>
        <UL>
          <LI>对单通道字节图像: <PRE>IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);<BR>int height     = img-&gt;height;<BR>int width      = img-&gt;width;<BR>int step       = img-&gt;widthStep/sizeof(uchar);<BR>uchar* data    = (uchar *)img-&gt;imageData;<BR>data[i*step+j] = 111;<BR></PRE>
          <P></P>
          <LI>对多通道字节图像: <PRE>IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);<BR>int height     = img-&gt;height;<BR>int width      = img-&gt;width;<BR>int step       = img-&gt;widthStep/sizeof(uchar);<BR>int channels   = img-&gt;nChannels;<BR>uchar* data    = (uchar *)img-&gt;imageData;<BR>data[i*step+j*channels+k] = 111;<BR></PRE>
          <P></P>
          <LI>对单通道浮点图像(假设用4字节调整): <PRE>IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);<BR>int height     = img-&gt;height;<BR>int width      = img-&gt;width;<BR>int step       = img-&gt;widthStep/sizeof(float);<BR>int channels   = img-&gt;nChannels;<BR>float * data    = (float *)img-&gt;imageData;<BR>data[i*step+j*channels+k] = 111;<BR></PRE>
          <P></P></LI></UL>
        <P></P>
        <P></P>
        <LI><EM>使用 c++ wrapper 进行直接存取:</EM> (简单高效) 
        <P></P>
        <UL>
          <LI>对单/多通道字节图像,多通道浮点图像定义一个&nbsp;c++ wrapper: <PRE>template&lt;class T&gt; class Image<BR>{<BR>  private:<BR>  IplImage* imgp;<BR>  public:<BR>  Image(IplImage* img=0) {imgp=img;}<BR>  ~Image(){imgp=0;}<BR>  void operator=(IplImage* img) {imgp=img;}<BR>  inline T* operator[](const int rowIndx) {<BR>    return ((T *)(imgp-&gt;imageData + rowIndx*imgp-&gt;widthStep));}<BR>};<BR><BR>typedef struct{<BR>  unsigned char b,g,r;<BR>} RgbPixel;<BR><BR>typedef struct{<BR>  float b,g,r;<BR>} RgbPixelFloat;<BR><BR>typedef Image&lt;RgbPixel&gt;       RgbImage;<BR>typedef Image&lt;RgbPixelFloat&gt;  RgbImageFloat;<BR>typedef Image&lt;unsigned char&gt;  BwImage;<BR>typedef Image&lt;float&gt;          BwImageFloat;<BR></PRE>
          <P></P>
          <LI>单通道字节图像: <PRE>IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);<BR>BwImage imgA(img);<BR>imgA[i][j] = 111;<BR></PRE>
          <P></P>
          <LI>多通道字节图像: <PRE>IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);<BR>RgbImage  imgA(img);<BR>imgA[i][j].b = 111;<BR>imgA[i][j].g = 111;<BR>imgA[i][j].r = 111;<BR></PRE>
          <P></P>
          <LI>多通道浮点图像: <PRE>IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);<BR>RgbImageFloat imgA(img);<BR>imgA[i][j].b = 111;<BR>imgA[i][j].g = 111;<BR>imgA[i][j].r = 111;<BR></PRE>
          <P></P></LI></UL>
        <P></P></LI></UL>
      <P></P>
      <H2><A>图像转换</A> </H2>
      <P></P>
      <UL>
        <LI>转为灰度或彩色字节图像: <PRE>cvConvertImage(src, dst, flags=0);<BR><BR>  src = float/byte grayscale/color image<BR>  dst = byte grayscale/color image<BR>  flags = CV_CVTIMG_FLIP     (flip vertically)<BR>          CV_CVTIMG_SWAP_RB  (swap the R and B channels)<BR></PRE>
        <P></P>
        <LI>转换彩色图像为灰度图像: 
        <P></P>
        <P><BR>使用OpenCV转换函数: </P><PRE>cvCvtColor(cimg,gimg,CV_BGR2GRAY); // cimg -&gt; gimg<BR></PRE>
        <P></P>
        <P><BR>直接转换: </P><PRE>for(i=0;i&lt;cimg-&gt;height;i++) for(j=0;j&lt;cimg-&gt;width;j++) <BR>  gimgA[i][j]= (uchar)(cimgA[i][j].b*0.114 + <BR>                       cimgA[i][j].g*0.587 + <BR>                       cimgA[i][j].r*0.299);<BR></PRE>
        <P></P>
        <LI>颜色空间转换: 
        <P></P><PRE>cvCvtColor(src,dst,code); // src -&gt; dst<BR><BR>  code    = CV_&lt;X&gt;2&lt;Y&gt;<BR>  &lt;X&gt;/&lt;Y&gt; = RGB, BGR, GRAY, HSV, YCrCb, XYZ, Lab, Luv, HLS<BR><BR>e.g.: CV_BGR2GRAY, CV_BGR2HSV, CV_BGR2Lab<BR></PRE>
        <P></P></LI></UL>
      <P></P>
      <H2><A>绘图命令</A> </H2>
      <P></P>
      <UL>
        <LI>画长方体: <PRE>// 用宽度为1的红线在(100,100)与(200,200)之间画一长方体<BR>cvRectangle(img, cvPoint(100,100), cvPoint(200,200), cvScalar(255,0,0), 1);<BR></PRE>
        <P></P>
        <LI>画圆: <PRE>// 在(100,100)处画一半径为20的圆,使用宽度为1的绿线<BR>cvCircle(img, cvPoint(100,100), 20, cvScalar(0,255,0), 1);<BR></PRE>
        <P></P>
        <LI>画线段: <PRE>// 在(100,100)与(200,200)之间画绿色线段,宽度为1<BR>cvLine(img, cvPoint(100,100), cvPoint(200,200), cvScalar(0,255,0), 1);<BR></PRE>
        <P></P>
        <LI>画一组线段: <PRE>CvPoint  curve1[]={10,10,  10,100,  100,100,  100,10};<BR>CvPoint  curve2[]={30,30,  30,130,  130,130,  130,30,  150,10};<BR>CvPoint* curveArr[2]={curve1, curve2};<BR>int      nCurvePts[2]={4,5};<BR>int      nCurves=2;<BR>int      isCurveClosed=1;<BR>int      lineWidth=1;<BR><BR>cvPolyLine(img,curveArr,nCurvePts,nCurves,isCurveClosed,cvScalar(0,255,255),lineWidth);<BR></PRE>
        <P></P>
        <LI>画内填充色的多边形: <PRE>cvFillPoly(img,curveArr,nCurvePts,nCurves,cvScalar(0,255,255));<BR></PRE>
        <P></P>
        <LI>添加文本: <PRE>CvFont font;<BR>double hScale=1.0;<BR>double vScale=1.0;<BR>int    lineWidth=1;<BR>cvInitFont(&amp;font,CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC, hScale,vScale,0,lineWidth);<BR><BR>cvPutText (img,"My comment",cvPoint(200,400), &amp;font, cvScalar(255,255,0));<BR></PRE>
        <P>Other possible fonts: </P><PRE>CV_FONT_HERSHEY_SIMPLEX, CV_FONT_HERSHEY_PLAIN,<BR>CV_FONT_HERSHEY_DUPLEX, CV_FONT_HERSHEY_COMPLEX,<BR>CV_FONT_HERSHEY_TRIPLEX, CV_FONT_HERSHEY_COMPLEX_SMALL,<BR>CV_FONT_HERSHEY_SCRIPT_SIMPLEX, CV_FONT_HERSHEY_SCRIPT_COMPLEX,<BR></PRE>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -