Tag Archives: reference

A small talk about “Reference” or “citation”.

Usually, we call a person FIRST NAME + LAST NAME in western country.

For instance, my name is Inkyu Sa.

The order is opposite in a way of most asian countries such as South Korea or China.

When you need to write up paper, might cite other many references.

Then you must clearly presents authors name on the Reference section.

Most conference papers are written in “LASTNAME, The first character of the first name”

For example, my name can be put in reference section “Sa, I.”.

If there are more than 2 authors, the reference might be this.

“Sa, I. and Park, H.”

If there are more than 3 authors, the reference might be this.

“Sa, I., Park, H., and Sa, Y.”

It is confusing that if there are two people who have the same character of their first name.

For instance, my sons name are Sa Yohan and Sa Yosep. Their name is put on the reference section as exactly same.

How can we distinguish this?

OpenCV essential reference.

Illinois Institute of Technology

 

Abstract:

The purpose of this document is to get you started quickly with OpenCV without having to go through lengthy reference manuals. Once you understand these basics you will be able to consult the OpenCV manuals on a need basis. 

 

 

 

http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html

Contents

 

 

 

Introduction

 

Description of OpenCV

 

  • General description
    • Open source computer vision library in C/C++.
    • Optimized and intended for real-time applications.
    • OS/hardware/window-manager independent.
    • Generic image/video loading, saving, and acquisition.
    • Both low and high level API.
    • Provides interface to Intel’s Integrated Performance Primitives (IPP) with processor specific optimization (Intel processors).

     

  • Features:
    • Image data manipulation (allocation, release, copying, setting, conversion).
    • Image and video I/O (file and camera based input, image/video file output).
    • Matrix and vector manipulation and linear algebra routines (products, solvers, eigenvalues, SVD).
    • Various dynamic data structures (lists, queues, sets, trees, graphs).
    • Basic image processing (filtering, edge detection, corner detection, sampling and interpolation, color conversion, morphological operations, histograms, image pyramids).
    • Structural analysis (connected components, contour processing, distance transform, various moments, template matching, Hough transform, polygonal approximation, line fitting, ellipse fitting, Delaunay triangulation).
    • Camera calibration (finding and tracking calibration patterns, calibration, fundamental matrix estimation, homography estimation, stereo correspondence).
    • Motion analysis (optical flow, motion segmentation, tracking).
    • Object recognition (eigen-methods, HMM).
    • Basic GUI (display image/video, keyboard and mouse handling, scroll-bars).
    • Image labeling (line, conic, polygon, text drawing)

     

  • OpenCV modules:
    • cv – Main OpenCV functions.
    • cvaux – Auxiliary (experimental) OpenCV functions.
    • cxcore – Data structures and linear algebra support.
    • highgui – GUI functions.

     

 

Resources

 

  • Reference manuals:
    • <opencv-root>/docs/index.htm

     

  • Web resources:
    • Official webpage: http://www.intel.com/technology/computing/opencv/ 
    • Software download: http://sourceforge.net/projects/opencvlibrary/ 

     

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

     

  • Sample programs for video processing (in <opencv-root>/samples/c/):
    • color tracking: camshiftdemo
    • point tracking: lkdemo
    • motion segmentation: motempl
    • edge detection: laplace

     

  • Sample programs for image processing (in <opencv-root>/samples/c/):
    • edge detection: edge
    • segmentation: pyramid_segmentation
    • morphology: morphology
    • histogram: demhist
    • distance transform: distrans
    • ellipse fitting: fitellipse

     

 

 

OpenCV naming conventions

 

  • Function naming conventions:
        cvActionTargetMod(...)
    
        Action = the core functionality (e.g. set, create)
        Target = the target image area (e.g. contour, polygon)
        Mod    = optional modifiers (e.g. argument type)

     

  • Matrix data types:
        CV_&lt;bit_depth&gt;(S|U|F)C&lt;number_of_channels&gt;
    
        S = Signed integer
        U = Unsigned integer
        F = Float 
    
        E.g.: CV_8UC1 means an 8-bit unsigned single-channel matrix, 
              CV_32FC2 means a 32-bit float matrix with two channels.

     

  • Image data types:
        IPL_DEPTH_&lt;bit_depth&gt;(S|U|F)
    
        E.g.: IPL_DEPTH_8U means an  8-bit unsigned image.
              IPL_DEPTH_32F means a 32-bit float image.

     

  • Header files:
        #include &lt;cv.h&gt;
        #include &lt;cvaux.h&gt;
        #include &lt;highgui.h&gt;  
        #include &lt;cxcore.h&gt;   // unnecessary - included in cv.h

     

 

Compilation instructions

 

  • Linux:
    g++ hello-world.cpp -o hello-world \
        -I /usr/local/include/opencv -L /usr/local/lib  \
        -lm -lcv -lhighgui -lcvaux

     

  • Windows:
    In the project preferences set the path to the OpenCV header files and
    the path to the OpenCV library files.

     

 

 

Example C Program

////////////////////////////////////////////////////////////////////////
//
// hello-world.cpp
//
// This is a simple, introductory OpenCV program. The program reads an
// image from a file, inverts it, and displays the result. 
//
////////////////////////////////////////////////////////////////////////
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;math.h&gt;
#include &lt;cv.h&gt;
#include &lt;highgui.h&gt;

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

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

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

  // get the image data
  height    = img-&gt;height;
  width     = img-&gt;width;
  step      = img-&gt;widthStep;
  channels  = img-&gt;nChannels;
  data      = (uchar *)img-&gt;imageData;
  printf("Processing a %dx%d image with %d channels\n",height,width,channels); 

  // create a window
  cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE); 
  cvMoveWindow("mainWin", 100, 100);

  // invert the image
  for(i=0;i&lt;height;i++) for(j=0;j&lt;width;j++) for(k=0;k&lt;channels;k++)
    data[i*step+j*channels+k]=255-data[i*step+j*channels+k];

  // show the image
  cvShowImage("mainWin", img );

  // wait for a key
  cvWaitKey(0);

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

 

 

GUI commands

 

Window management

 

  • Create and position a window:
      cvNamedWindow("win1", CV_WINDOW_AUTOSIZE); 
      cvMoveWindow("win1", 100, 100); // offset from the UL corner of the screen

     

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

     

  • Display an image:
      cvShowImage("win1",img);

    Can display a color or grayscale byte/float-image. A byte image is assumed to have values in the range $[0..255]$. A float image is assumed to have values in the range $[0..1]$. A color image is assumed to have data in BGR order.

     

  • Close a window:
      cvDestroyWindow("win1");

     

  • Resize a window:
      cvResizeWindow("win1",100,100); // new width/heigh in pixels

     

 

 

Input handling

 

  • Handle mouse events:
    • Define a mouse handler:
        void mouseHandler(int event, int x, int y, int flags, void* param)
        {
          switch(event){
            case CV_EVENT_LBUTTONDOWN:
              if(flags &amp; 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:   pixel coordinates with respect to the UL corner
      
        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

       

    • Register the handler:
        mouseParam=5;
        cvSetMouseCallback("win1",mouseHandler,&amp;mouseParam);

       

     

     

  • Handle keyboard events:
    • The keyboard does not have an event handler. 
    • Get keyboard input without blocking:
        int key;
        key=cvWaitKey(10); // wait 10ms for input

       

    • Get keyboard input with blocking:
        int key;
        key=cvWaitKey(0); // wait indefinitely for input

       

    • The main keyboard event loop:
        while(1){
          key=cvWaitKey(10);
          if(key==27) break;
      
          switch(key){
            case 'h':
              ...
              break;
            case 'i':
              ...
              break;
          }
        }

       

     

  • Handle trackbar events:
    • Define a trackbar handler:
        void trackbarHandler(int pos)
        {
          printf("Trackbar position: %d\n",pos);
        }

       

    • Register the handler:
        int trackbarVal=25;
        int maxVal=100;
        cvCreateTrackbar("bar1", "win1", &amp;trackbarVal ,maxVal , trackbarHandler);

       

    • Get the current trackbar position:
        int pos = cvGetTrackbarPos("bar1","win1");

       

    • Set the trackbar position:
        cvSetTrackbarPos("bar1", "win1", 25);

       

     

 

Basic OpenCV data structures

 

Image data structure

 

  • IPL image:
    IplImage
      |-- int  nChannels;     // Number of color channels (1,2,3,4)
      |-- int  depth;         // Pixel depth in bits: 
      |                       //   IPL_DEPTH_8U, IPL_DEPTH_8S, 
      |                       //   IPL_DEPTH_16U,IPL_DEPTH_16S, 
      |                       //   IPL_DEPTH_32S,IPL_DEPTH_32F, 
      |                       //   IPL_DEPTH_64F
      |-- int  width;         // image width in pixels
      |-- int  height;        // image height in pixels
      |-- char* imageData;    // pointer to aligned image data
      |                       // Note that color images are stored in BGR order
      |-- int  dataOrder;     // 0 - interleaved color channels, 
      |                       // 1 - separate color channels
      |                       // cvCreateImage can only create interleaved images
      |-- int  origin;        // 0 - top-left origin,
      |                       // 1 - bottom-left origin (Windows bitmaps style)
      |-- int  widthStep;     // size of aligned image row in bytes
      |-- int  imageSize;     // image data size in bytes = height*widthStep
      |-- struct _IplROI *roi;// image ROI. when not NULL specifies image
      |                       // region  to be processed.
      |-- char *imageDataOrigin; // pointer to the unaligned origin of image data
      |                          // (needed for correct image deallocation)
      |
      |-- int  align;         // Alignment of image rows: 4 or 8 byte alignment
      |                       // OpenCV ignores this and uses widthStep instead
      |-- char colorModel[4]; // Color model - ignored by OpenCV

     

 

 

Matrices and vectors

 

  • Matrices:
    CvMat                      // 2D array
      |-- int   type;          // elements type (uchar,short,int,float,double) and flags
      |-- int   step;          // full row length in bytes
      |-- int   rows, cols;    // dimensions
      |-- int   height, width; // alternative dimensions reference
      |-- union data;
          |-- uchar*  ptr;     // data pointer for an unsigned char matrix
          |-- short*  s;       // data pointer for a short matrix
          |-- int*    i;       // data pointer for an integer matrix
          |-- float*  fl;      // data pointer for a float matrix
          |-- double* db;      // data pointer for a double matrix
    
    CvMatND                    // N-dimensional array
      |-- int   type;          // elements type (uchar,short,int,float,double) and flags
      |-- int   dims;          // number of array dimensions
      |-- union data;
      |   |-- uchar*  ptr;     // data pointer for an unsigned char matrix
      |   |-- short*  s;       // data pointer for a short matrix
      |   |-- int*    i;       // data pointer for an integer matrix
      |   |-- float*  fl;      // data pointer for a float matrix
      |   |-- double* db;      // data pointer for a double matrix
      |
      |-- struct dim[];        // information for each dimension
          |-- size;            // number of elements in a given dimension
          |-- step;            // distance between elements in a given dimension
    
    CvSparseMat // SPARSE N-dimensional array

     

  • Generic arrays:
    CvArr*     // Used only as a function parameter to specify that the
               // function accepts arrays of more than a single type, such
               // as: IplImage*, CvMat* or even CvSeq*. The particular array 
               // type is determined at runtime by analyzing the first 4
               // bytes of the header of the actual array.

     

     

  • Scalars:
    CvScalar
      |-- double val[4]; //4D vector

    Initializer function:

    CvScalar s = cvScalar(double val0, double val1=0, double val2=0, double val3=0);

    Example:

    CvScalar s = cvScalar(20.0);
    s.val[0]=10.0;

    Note that the initializer function has the same name as the data structure only starting with a lower case character. It is not a C++ constructor.

     

 

Other data structures

 

  • Points:
    CvPoint      p = cvPoint(int x, int y);
    CvPoint2D32f p = cvPoint2D32f(float x, float y);
    CvPoint3D32f p = cvPoint3D32f(float x, float y, float z);
    
    E.g.:
    p.x=5.0;
    p.y=5.0;

     

  • Rectangular dimensions:
    CvSize       r = cvSize(int width, int height);
    CvSize2D32f  r = cvSize2D32f(float width, float height);

     

  • Rectangular dimensions with offset:
    CvRect       r = cvRect(int x, int y, int width, int height);

     

 

 

Working with images

 

Allocating and releasing images

 

  • Allocate an image:
    IplImage* cvCreateImage(CvSize size, int depth, int channels);
    
      size:  cvSize(width,height);
    
      depth: pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,
        IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F, IPL_DEPTH_64F
    
      channels: Number of channels per pixel. Can be 1, 2, 3 or 4. The channels 
        are interleaved. The usual data layout of a color image is
        b0 g0 r0 b1 g1 r1 ...

    Examples:

    // 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);

     

  • Release an image:
    IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); 
    cvReleaseImage(&amp;img);

     

  • Clone an image:
    IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); 
    IplImage* img2;
    img2=cvCloneImage(img1);

     

  • Set/get the region of interest:
    void  cvSetImageROI(IplImage* image, CvRect rect);
    void  cvResetImageROI(IplImage* image);
    vRect cvGetImageROI(const IplImage* image);
    
    The majority of OpenCV functions support ROI.

     

  • Set/get the channel of interest:
    void cvSetImageCOI(IplImage* image, int coi); // 0=all
    int cvGetImageCOI(const IplImage* image);
    
    The majority of OpenCV functions do NOT support COI.

     

 

Reading and writing images

 

  • Reading an image from a file:
      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

    By default, the loaded image is forced to be a 3-channel color image. This default can be modified by using:

      img=cvLoadImage(fileName,flag);
    
      flag: &gt;0 the loaded image is forced to be a 3-channel color image
            =0 the loaded image is forced to be a 1 channel grayscale image
            &lt;0 the loaded image is loaded as is (with number of channels in the file).

     

  • Writing an image to a file:
      if(!cvSaveImage(outFileName,img)) printf("Could not save: %s\n",outFileName);

    The output file format is determined based on the file name extension.

     

 

Accessing image elements

 

  • Assume that you need to access the $k$-th channel of the pixel at the $i$-row and $j$-th column. The row index $i$ is in the range $[0,\mbox{height}-1]$. The column index $j$ is in the range$[0,\mbox{width}-1]$. The channel index $k$ is in the range $[0,\mbox{nchannels}-1]$
  • Indirect access: (General, but inefficient, access to any type image) 
    • For a single-channel byte image:
      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

       

    • For a multi-channel float (or byte) image:
      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

       

     

  • Direct access: (Efficient access, but error prone) 
    • For a single-channel byte image:
      IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
      ((uchar *)(img-&gt;imageData + i*img-&gt;widthStep))[j]=111;

       

    • For a multi-channel byte image:
      IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
      ((uchar *)(img-&gt;imageData + i*img-&gt;widthStep))[j*img-&gt;nChannels + 0]=111; // B
      ((uchar *)(img-&gt;imageData + i*img-&gt;widthStep))[j*img-&gt;nChannels + 1]=112; // G
      ((uchar *)(img-&gt;imageData + i*img-&gt;widthStep))[j*img-&gt;nChannels + 2]=113; // R

       

    • For a multi-channel float image:
      IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
      ((float *)(img-&gt;imageData + i*img-&gt;widthStep))[j*img-&gt;nChannels + 0]=111; // B
      ((float *)(img-&gt;imageData + i*img-&gt;widthStep))[j*img-&gt;nChannels + 1]=112; // G
      ((float *)(img-&gt;imageData + i*img-&gt;widthStep))[j*img-&gt;nChannels + 2]=113; // R

       

     

  • Direct access using a pointer: (Simplified and efficient access under limiting assumptions) 
    • For a single-channel byte image:
      IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
      int height     = img-&gt;height;
      int width      = img-&gt;width;
      int step       = img-&gt;widthStep/sizeof(uchar);
      uchar* data    = (uchar *)img-&gt;imageData;
      data[i*step+j] = 111;

       

    • For a multi-channel byte image:
      IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
      int height     = img-&gt;height;
      int width      = img-&gt;width;
      int step       = img-&gt;widthStep/sizeof(uchar);
      int channels   = img-&gt;nChannels;
      uchar* data    = (uchar *)img-&gt;imageData;
      data[i*step+j*channels+k] = 111;

       

    • For a multi-channel float image (assuming a 4-byte alignment):
      IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
      int height     = img-&gt;height;
      int width      = img-&gt;width;
      int step       = img-&gt;widthStep/sizeof(float);
      int channels   = img-&gt;nChannels;
      float * data    = (float *)img-&gt;imageData;
      data[i*step+j*channels+k] = 111;

       

     

     

  • Direct access using a c++ wrapper: (Simple and efficient access) 
    • Define a c++ wrapper for single-channel byte images, multi-channel byte images, and multi-channel float images:
      template&lt;class T&gt; 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-&gt;imageData + rowIndx*imgp-&gt;widthStep));}
      };
      
      typedef struct{
        unsigned char b,g,r;
      } RgbPixel;
      
      typedef struct{
        float b,g,r;
      } RgbPixelFloat;
      
      typedef Image&lt;RgbPixel&gt;       RgbImage;
      typedef Image&lt;RgbPixelFloat&gt;  RgbImageFloat;
      typedef Image&lt;unsigned char&gt;  BwImage;
      typedef Image&lt;float&gt;          BwImageFloat;

       

    • For a single-channel byte image:
      IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
      BwImage imgA(img);
      imgA[i][j] = 111;

       

    • For a multi-channel byte image:
      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;

       

    • For a multi-channel float image:
      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;

       

     

 

Image conversion

 

  • Convert to a grayscale or color byte-image:
    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)

     

  • Convert a color image to grayscale: 
    Using the OpenCV conversion:

    cvCvtColor(cimg,gimg,CV_BGR2GRAY); // cimg -&gt; gimg

     
    Using a direct conversion:

    for(i=0;i&lt;cimg-&gt;height;i++) for(j=0;j&lt;cimg-&gt;width;j++) 
      gimgA[i][j]= (uchar)(cimgA[i][j].b*0.114 + 
                           cimgA[i][j].g*0.587 + 
                           cimgA[i][j].r*0.299);

     

  • Convert between color spaces: 
    cvCvtColor(src,dst,code); // src -&gt; dst
    
      code    = CV_&lt;X&gt;2&lt;Y&gt;
      &lt;X&gt;/&lt;Y&gt; = RGB, BGR, GRAY, HSV, YCrCb, XYZ, Lab, Luv, HLS
    
    e.g.: CV_BGR2GRAY, CV_BGR2HSV, CV_BGR2Lab

     

 

Drawing commands

 

  • Draw a box:
    // draw a box with red lines of width 1 between (100,100) and (200,200)
    cvRectangle(img, cvPoint(100,100), cvPoint(200,200), cvScalar(255,0,0), 1);

     

  • Draw a circle:
    // draw a circle at (100,100) with a radius of 20. Use green lines of width 1
    cvCircle(img, cvPoint(100,100), 20, cvScalar(0,255,0), 1);

     

  • Draw a line segment:
    // draw a green line of width 1 between (100,100) and (200,200)
    cvLine(img, cvPoint(100,100), cvPoint(200,200), cvScalar(0,255,0), 1);

     

  • Draw a set of polylines:
    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);

     

  • Draw a set of filled polygons:
    cvFillPoly(img,curveArr,nCurvePts,nCurves,cvScalar(0,255,255));

     

  • Add text:
    CvFont font;
    double hScale=1.0;
    double vScale=1.0;
    int    lineWidth=1;
    cvInitFont(&amp;font,CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC, hScale,vScale,0,lineWidth);
    
    cvPutText (img,"My comment",cvPoint(200,400), &amp;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,

     

 

 

Working with matrices

 

Allocating and releasing matrices

 

  • General:
    • OpenCV has a C interface to matrix operations. There are many alternatives that have a C++ interface (which is more convenient) and are as efficient as OpenCV.
    • Vectors are obtained in OpenCV as matrices having one of their dimensions as 1.
    • Matrices are stored row by row where each row has a 4 byte alignment.

     

  • Allocate a matrix:
    CvMat* cvCreateMat(int rows, int cols, int type);
    
      type: Type of the matrix elements. Specified in form
      CV_&lt;bit_depth&gt;(S|U|F)C&lt;number_of_channels&gt;.  E.g.: CV_8UC1 means an
      8-bit unsigned single-channel matrix, CV_32SC2 means a 32-bit signed
      matrix with two channels.
    
      Example:
      CvMat* M = cvCreateMat(4,4,CV_32FC1);

     

  • Release a matrix:
    CvMat* M = cvCreateMat(4,4,CV_32FC1);
    cvReleaseMat(&amp;M);

     

  • Clone a matrix:
    CvMat* M1 = cvCreateMat(4,4,CV_32FC1);
    CvMat* M2;
    M2=cvCloneMat(M1);

     

  • Initialize a matrix:
    double a[] = { 1,  2,  3,  4,
                   5,  6,  7,  8,
                   9, 10, 11, 12 };
    
    CvMat Ma=cvMat(3, 4, CV_64FC1, a);

    Alternatively:

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

     

  • Initialize a matrix to identity:
    CvMat* M = cvCreateMat(4,4,CV_32FC1);
    cvSetIdentity(M); // does not seem to be working properly

     

 

Accessing matrix elements

 

  • Assume that you need to access the $(i,j)$ cell of a 2D float matrix. 
  • Indirect matrix element access:
    cvmSet(M,i,j,2.0); // Set M(i,j)
    t = cvmGet(M,i,j); // Get M(i,j)

     

  • Direct matrix element access assuming a 4-byte alignment:
    CvMat* M    = cvCreateMat(4,4,CV_32FC1);
    int n       = M-&gt;cols;
    float *data = M-&gt;data.fl;
    
    data[i*n+j] = 3.0;

     

  • Direct matrix element access assuming possible alignment gaps:
    CvMat* M    = cvCreateMat(4,4,CV_32FC1);
    int   step  = M-&gt;step/sizeof(float);
    float *data = M-&gt;data.fl;
    
    (data+i*step)[j] = 3.0;

     

  • Direct matrix element access of an initialized matrix:
    double a[16];
    CvMat Ma = cvMat(3, 4, CV_64FC1, a);
    a[i*4+j] = 2.0; // Ma(i,j)=2.0;

     

 

Matrix/vector operations

 

  • Matrix-matrix operations:
    CvMat *Ma, *Mb, *Mc;
    cvAdd(Ma, Mb, Mc);      // Ma+Mb   -&gt; Mc
    cvSub(Ma, Mb, Mc);      // Ma-Mb   -&gt; Mc
    cvMatMul(Ma, Mb, Mc);   // Ma*Mb   -&gt; Mc

     

  • Elementwise matrix operations:
    CvMat *Ma, *Mb, *Mc;
    cvMul(Ma, Mb, Mc);      // Ma.*Mb  -&gt; Mc
    cvDiv(Ma, Mb, Mc);      // Ma./Mb  -&gt; Mc
    cvAddS(Ma, cvScalar(-10.0), Mc); // Ma.-10 -&gt; Mc

     

     

  • Vector products:
    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(&amp;Va,&amp;Vb); // dot product:   Va . Vb -&gt; res
    cvCrossProduct(&amp;Va, &amp;Vb, &amp;Vc);    // cross product: Va x Vb -&gt; Vc
    end{verbatim}

    Note that Va, Vb, Vc, must be 3 element vectors in a cross product.

     

     

  • Single matrix operations:
    CvMat *Ma, *Mb;
    cvTranspose(Ma, Mb);      // transpose(Ma) -&gt; Mb (cannot transpose onto self)
    CvScalar t = cvTrace(Ma); // trace(Ma) -&gt; t.val[0] 
    double d = cvDet(Ma);     // det(Ma) -&gt; d
    cvInvert(Ma, Mb);         // inv(Ma) -&gt; Mb

     

  • Inhomogeneous linear system solver:
    CvMat* A  = cvCreateMat(3,3,CV_32FC1);
    CvMat* x  = cvCreateMat(3,1,CV_32FC1);
    CvMat* b  = cvCreateMat(3,1,CV_32FC1);
    cvSolve(&amp;A, &amp;b, &amp;x);    // solve (Ax=b) for x

     

  • Eigen analysis (of a symmetric matrix):
    CvMat* A  = cvCreateMat(3,3,CV_32FC1);
    CvMat* E  = cvCreateMat(3,3,CV_32FC1);
    CvMat* l  = cvCreateMat(3,1,CV_32FC1);
    cvEigenVV(&amp;A, &amp;E, &amp;l);  // l = eigenvalues of A (descending order)
                            // E = corresponding eigenvectors (rows)

     

  • Singular value decomposition:
    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

    The flags cause U and V to be returned transposed (does not work well without the transpose flags).

     

 

Working with video sequences

 

Capturing a frame from a video sequence

 

  • OpenCV supports capturing images from a camera or a video file (AVI). 
  • Initializing capture from a camera:
    CvCapture* capture = cvCaptureFromCAM(0); // capture from video device #0

     

  • Initializing capture from a file:
    CvCapture* capture = cvCaptureFromAVI("infile.avi");

     

  • Capturing a frame:
    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

    To obtain images from several cameras simultaneously, first grab an image from each camera. Retrieve the captured images after the grabbing is complete.

     

  • Releasing the capture source:
    cvReleaseCapture(&amp;capture);

    Note that the image captured by the device is allocated/released by the capture function. There is no need to release it explicitly.

     

 

Getting/setting frame information

 

  • Get capture device properties:
    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);

    The total frame count is relevant for video files only. It does not seem to be working properly.

     

     

  • Get frame information:
    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);

    Get the position of the captured frame in [msec] with respect to the first frame, or get its index where the first frame starts with an index of 0. The relative position (ratio) is 0 in the first frame and 1 in the last frame. This ratio is valid only for capturing images from a file.

     

  • Set the index of the first frame to capture:
    // start capturing from a relative position of 0.9 of a video file
    cvSetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO, (double)0.9);

    This only applies for capturing from a file. It does not seem to be working properly.

     

 

Saving a video file

 

  • Initializing a video writer:
    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);

    Other possible codec codes:

    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

    A codec code of -1 will open a codec selection window (in windows).

     

     

  • Writing the video file:
    IplImage* img = 0; 
    int nFrames = 50;
    for(i=0;i&lt;nFrames;i++){
      cvGrabFrame(capture);          // capture a frame
      img=cvRetrieveFrame(capture);  // retrieve the captured frame
      cvWriteFrame(writer,img);      // add the frame to the file
    }

    To view the captured frames during capture, add the following in the loop:

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

    Note that without the 20[msec] delay the captured sequence is not displayed properly.

     

  • Releasing the video writer:
    cvReleaseVideoWriter(&amp;writer);

     

 

 

Reference in c and c++

그러니까참조자의 Reference 는 Call-by-Reference의 그 참조자가 맞습니다.

참조자는 또 뭐시당가??

간단히 말하면 원래 변수의 별명! 그러므로 원래 변수가 가진 값과 주소 모두 같음!
거의 변수와 같은 형태로, 지역적 참조자는 지역을 벗어나면 소멸하게 된다. 변수로 취급해도 무방하다고…
중요한 것은 이런 참조자가 활용되는 건 power한 함수의 사용을 위해서임. 변수에 별명이나 붙여주자고 쓰는게 아님.

* 변수란 무엇인가? 잠깐 되짚고 넘어가자.

할당된 메모리 공간에 붙여진 이름으로, 이 이름을 통해 해당 메모리 공간에 접근할 수 있음.

참조자의 선언엔 & 연산자를 사용한다.

어디서 많이 봤다. 어디서 봤는고 하니…그 죽일놈의 포인터! 망할 포인터! 으어어어거! ….여튼 포인터에서 썼었지?

* & 연산자는 주소반환 연산자.

변수 앞에 붙어 그 변수의 주소를 리턴.
그런데, 변수 선언 앞에 붙으면 참조자의 선언이 된다!

ex) &연산자의 두가지 기능

main내부
{
int num;
int *ptr = #    // 변수 num 앞에 붙어 포인터변수 ptr에 num의 주소를 저장
int &ref = num;     // ref 변수의 선언 앞에 붙어 변수 num에 대한 참조자 ref를 선언
}

주의하라! 참조자는 선언과 동시에 초기화되어야 하며, 한번 초기화된 후엔 다른 변수를 참조하도록 바꿀 수 없다.

또한 NULL 초기화나 (일반적으로)상수에 대한 참조도 불가능하다.

참조자의 또다른 특징

– 한 개의 변수에 여러 개의 참조자를 선언할 수 있다.별명이 여러개인 사람을 생각하면 쉬울듯

– 참조자에 대한 참조자도 선언이 가능하다.

– 포인터 변수에 대해서도 참조자의 선언이 가능하다.

ex) 포인터 변수에 대한 참조자의 선언 형태 확인

int num=10;
int *ptr=#
int **dptr=&ptr;

int &ref=num;
int*(&pref)=ptr;
int**(&dpref)=dptr;

C++의 Call-by-Reference 는 두가지로 나뉜다

포인터에 의한 Call-by-Reference 와 참조자에 의한 Call-by-Reference.

이 두 개의 구별을 위해 포인터에 의한 Call-by-Reference는 Call-by-Address라고 불리기도 한다.
포인터에 의한 Call-by-Reference는 곧 주소값을 전달하는 것이기 때문.

* Call-by-Reference, 포인터와 참조자 비교

ex) 포인터를 이용한 swap 함수

void SwapByPtr(int *p1,int *p2)
{
int *temp = p1;
p1 = p2;
p2 = temp;
}

ex) 참조자를 이용한 swap 함수

void SwapByRef(int &r1,int &r2)
{
int &temp = r1;
r1 = r2;
r2 = temp;
}

직접 돌려보기 바람.
여담이지만 temp 라는 같은 이름의 변수가 보이나 이들은 함수 내에서만 존재하는 지역변수니까 안충돌함 ‘ㅅ’

여튼 둘 다 전달받은 인자를 이용해 함수 밖의 변수를 수정하지만, 포인터는 주소를 받고, 참조자는 참조함으로서 이뤄지는게 차이.

* 참조자의 성질 기억남? 참조자는 선언과 동시에 초기화되어야 한다고 했었다.
그런데 여기 매개변수 선언시에는 초기화가 안되어있다. 왜 가능할까?
그건 매개변수는 함수호출시에 전달받은 인자로 초기화하겠다는 의미를 가지고있기 때문이다.

자, 그리고 const 키워드의 등장이다.

이 키워드는 무슨 역할?  그렇다. 변수를 상수화 하는데 쓰인다. 상수는 값 변경이 불가능한 수라고 했었다.
그런데 const 키워드가 참조자 앞에 붙으면 어떻게 될까.

const 참조자는 세가지 필요성에 의해 쓰인다. (더 있는지도 모르지만 난 세개만 안다)

– 함수 정의시 참조자를 통한 값 변경을 하지 않겠다는 의미를 나타낼 때 사용

– const 변수를 참조하기 위해 사용

– 상수를 참조하기 위해 사용

둘 다 뭔소린가 싶다. 특히 마지막. 참조자는 상수참조를 못한댔는데 이번엔 할 수 있댄다. 뭐냐?
순서대로 알아보자.

– 함수 정의시 참조자를 통한 값 변경을 하지 않겠다

이게 무슨 소린고 하니, 코드의 가독성 문제다.
C에서는 Call-by-Reference가 필요할 때, 포인터를 쓰면 되었다.
포인터는 Call-by-Value 에서 굳이 쓸 필요가 없기 때문에 main 내부에서
함수 호출만 봐도 Call-by-Value인지 Call-by-Reference인지 바로 구분이 가능했다.

하지만 C++에서는 포인터와 참조자 둘 다 쓸 수 있다고 했었다. 여기서 문제가 생긴다.
포인터는 그대로다. 그러나
참조자는 함수 호출만 봐서는 Call-by-Value인지 Call-by-Reference인지 구분이 불가능!
최소한 함수 원형을 확인해야만 이걸 알 수 있기에, 함수 선언부에 const 를 붙여 값 변경을 하지 않겠단 말을 하는 것.

자, 그럼 const 참조자가 들어가는 함수는 어떤 호출일까? 바로 Call-by-Value!

ex) 참조자는 함수 호출만으로는 어떤 호출형태인지 구분할 수 없다. (포인터는 귀찮아서 생략)

main 내부
{
int num=10;

Func(num);
}

어떤 호출인지 구분이 불가능하다. 함수 원형을 확인해야한다.
확인하기 전에, Func 함수의 형태로 예상되는 것엔 뭐가 있나?(반환형 제외. 매개변수만 확인)

1:  Func(int);     2:  Func(int&);

그럼 호출구문만 보고 Call-by-Value인지 Call-by-Reference인지 구분할 수 있는가?구분할 수 없다.

그러니 Call-by-Value라면 Func(const int&);라고 선언해서 값의 변경을 막고,

Call-by-Reference 라면 Func(int&); 라고 선언해준다.

* 이런 이유로, 참조자를 아예 사용하지 않는 프로그래머도 있다고 한다. 참조자가 아예 없으면 이런 고민도 없대나…
근데 참조자가 포인트보다 써먹기는 더 쉽잖아….

- const 변수를 참조하기 위한 const 참조자

const 변수는 상수처럼 인식되어 값 변경이 되지않는다고 했다.
헌데 이 const 변수를 참조자가 참조해서 함수 내에서 값 변경을 해버린다면?

당연히 의도하지 않은 결과다. 그래서컴파일러는 참조자가 const 변수를 참조하는 것을 막는다.
대신 const 참조자라면 const 변수를 참조할 수 있게 해뒀다.

ex) const 참조자의 const 변수 참조

main 내부
{
const int num=10;
const int &ref = num;  //int &ref=num; 은 에러난다.
}

– 상수를 참조하기 위한 const 참조자

예제 하나로 설명 끗
ex) 상수참조 const 참조자

main내부
{
const int &ref=50;
}

이 경우, 50이란 상수는 임시 변수가 되어 결과적으론 두번째의 const 변수 참조와 같은 결과.
아 도대체 왜 상수 참조가 필요한 지 모르겠다. 그냥 그런갑다 하고 넘어가자.

참조형 또한 변수의 한 형태로 취급할 수 있다고 말했었나? 아마 했었던 거 같은데.

여튼 그렇기 때문에 참조자는 함수의 반환형으로도 쓰일 수 있다.

ex) 참조형으로 반환되는 함수와 일반형으로 반환되는 함수의 차이

int& RefRetFuncOn(int& ref) // ①번
{
return ++ref;
}

int RefRetFuncTo(int& ref) // ②번
{
return ++ref;
}

main 내부
{
int num1=1;
int &num2 = RefRetFuncOn(num1);
//리턴형이 참조형인 함수니 선언도 참조형으로.
/* 함수 내의 매개변수 ref는 num1의 참조자. ref가 참조형으로 반환되므로 num2 는 ref의 참조자가 된다.

num1 = ref = num2 가 성립하고, 함수가 종료되면서 지역변수인 ref는 소멸. 결국 num1 = num2 가 된다.

귀찮아서 생략했는데, 확인을 위해 num1,num2 두 변수에 서로 다른 연산을 한 후 cout 함수로 출력해보세요.
아니면 그냥 주소반환 연산자 붙여서 출력해보든가.
같은 값이 나올 거임. 만약 할 사람이 있다면 말이지만…ㅎ…. */

int num1=1;
int num3 = RefRetFuncTo(num1);
//리턴형이 int 형이므로 선언도 int형
/* 똑같이 ref는 num1의 참조자. ref의 값만 int형으로 반환되므로 num3은 ref와 같은 값을 갖는 int형 변수가 된다.

num1 = ref 지만 num3 == ref 일 뿐, num3 = ref는 아니다. 그리고 ref는 함수종료로 소멸.
이거 이해 못하면 C부터 다시 보든가. 내가 설명 존못이든가.

여튼 여기도 num1이랑 num3에 대해 연산해보거나
주소 출력해보면 이번엔 서로 다른 값이 나올거임. 그럼 서로 다른 변수라는걸 알겠지. */

아, 난 좀 친절한 거 같아. 직접 해보라고 과제까지 내주다니(?) 개드립 쩌네여

그리고 마지막. 잘못된 참조형의 반환일단 예제부터 보자.

ex) 잘못된 참조형의 반환

int& RetFunc(int n)
{
int i=10;
i+=n;
return i;
}

main 내부
{
int num1=10;
int& num2=RetFunc(num1);
}

. num2 는 무슨 값이 될까? 20. 이라고 하겠지.뭐, 좋아 그건 그렇다 치고

num2 가 참조하는 건 뭐지? 함수 내부의 지역변수인i다. 근데 이 i란 놈은 함수가 종료되면 사라진다

그래서 컴파일 경고(!) 가 난다. 에러는 안난대요. 어쩌면 잘 돌아갈 수도 있음. 근데 언제나 잘될거라고 보장못함. 이런이야기

결론 : 함수 내부의 지역변수를 참조형으로 반환하지 말자.


+@ 반환형에 따른 반환값 저장.

아까 저 위에 있던 예제에서 가져온 함수요.

int& RefRetFuncOn(int& ref) // ①번. 이 놈은 리턴값이 int 형 변수와 int& 형 참조자에 둘다 저장이 됨.

int RefRetFuncTo(int& ref)  //  ②번. 근데 이놈은 int형 변수에만 저장이 됨.