Using OpenCV with MFC - Grabbing using a USB Camera

  | Back |

I finally bought a USB camera and on this page I will show how to acquire and process images from an USB camera.

Before continuing with this guide be sure that the installation of the USB camera is correct - test the installation with e.g the HMMDemo application. Do not start with this guide before you your camera are working properly with the examples in OpenCV.

The step one here must have been run through before this section can be used.

Add the cvcam.dsp project into your workspace by pressing "Project", "Insert Project into workspace" and browse to the folder "C:\Program Files\Intel\opencv\otherlibs\cvcam\make_win", remember to right click on the project MyApplication and make it the the active project again. Click on "Project" then on "Dependencies" and with "MyApplication" active put an mark in the "cvcam" box and press OK.

Press Alt+F7 or click on "Project" in the menu bar and then on "Settings" to get the "Project Settings" dialog. Mark the Project "MyApplication". Choose "All Configuration" in the "Settings for" roll down menu.
Click on the tab "C/C++" and "Preprocessor" in the roll down menu.
In the "Additional include directories" add ",C:\Program Files\Intel\opencv\otherlibs\cvcam\include" to the comma separated list.

With "Win32 debug" active in the "Settings for" roll down menu. Choose the "Link" Tab and "input" in the "Category" roll down menu.

Add "cvcamd.lib" to the space separated "Object/library modules" list.
Add "cvcam.lib" to the space separated "Object/library modules" list with "Win32 Release" active.
Add "vfw32.lib" to the space separated "Object/library modules" list with "All Configurations" active.

Add the line "#include "cvcam.h" " below your other include directives either in MyApplication.h or MyIplClass.h if this file exists.

Add the following line just below the include directive to make an global function:

- - - Start cut'n paste - - -
void LiveProcess(IplImage *image);
- - - End cut'n paste - - -

In the CVB double click on the variable buffer and ad the following variables:

- - - Start cut'n paste - - -
     HWND hWnd;
     int cvcamone;
     BOOL GrabIsStarted;
     int ncams;

- - - End cut'n paste - - -

In the CVB double click on OnInitDialog() and add the code before the "return TRUE" command.
- - - Start cut'n paste - - -
     GrabIsStarted = FALSE;
     hWnd = AfxGetMainWnd()->m_hWnd;
     ncams = cvcamGetCamerasCount(); // returns the number of available cameras in the system
     cvcamSetProperty(0, CVCAM_PROP_ENABLE, &cvcamone); // Selects the 1-st found camera
     cvcamSetProperty(0, CVCAM_PROP_RENDER, &cvcamone); // We'll render stream from this source

     cvcamSetProperty(0, CVCAM_PROP_WINDOW, &hWnd); // Selects this window for video rendering
     cvcamSetProperty(0, CVCAM_PROP_CALLBACK, LiveProcess); // this callback will process every frame

     cvcamInit();

- - - End cut'n paste - - -

In the ResourceView Browser click on MyApplication resources then Dialog and finally double click on IDD_MYAPPLICATION_DIALOG to be able to edit the dialog. Resize the dialog to a size fitting the video output and remember also to adjust the two #defines IMAGE_WIDTH and IMAGE_HEIGHT. Add a button to the lower right part of the dialog -Right click on it and through properties change the ID: to "IDC_USB_GRAB" and the Caption to "USB Grab". Close the Properties dialog box and double click on the new button to add a function called "OnUsbGrab" Press OK to get to the code. Paste the following into the function:

- - - Start cut'n paste - - -
     CWnd *pButton; // Change the caption dependent on the grab state

     if (GrabIsStarted == FALSE)
     {
          cvcamStart( );// Now we are running

          GrabIsStarted = TRUE;
          pButton = GetDlgItem(IDC_USB_GRAB);
          pButton->SetWindowText("Stop");
     }
     else
     {
          cvcamStop( );
          GrabIsStarted = FALSE;
          pButton = GetDlgItem(IDC_USB_GRAB);
          pButton->SetWindowText("USB Grab");
     }

- - - End cut'n paste - - -

Double click on OnPaint() in the CVB and add the following code in the else statement.

- - - Start cut'n paste - - -
     if(GrabIsStarted != TRUE)
          DisplayMyData();
     CDialog::OnPaint();

- - - End cut'n paste - - -

In the FVB double click on MyApplication.ccp to open up this file and add the code after the first "#endif", this code does the real time processing of the acquired images from the USB camera.

- - - Start cut'n paste - - -
void LiveProcess(IplImage *image)
{
     IplImage* image1 = image;
     int i,j;

     assert (image);

     for(i=0; i < image1->height; i += 10)
     {
          for(j=(image1->widthStep)*i; j<(image1->widthStep)*(i+1); j+=image1->nChannels)
          {
               image1->imageData[j] = (char)255;
               image1->imageData[j+1] = 0;
               image1->imageData[j+2] = 0;
          }
     }
}

- - - End cut'n paste - - -

Finally double click on "InitInstance" of the class "CMyApplicationApp" and add following code after the line "cvReleaseImage(&dlg.TheImage);" :

- - - Start cut'n paste - - -
     cvcamExit();
- - - End cut'n paste - - -

Thats it! hit F5 to build and run your application! Press the Grab button to start grabbing, then on Stop. The callback function LiveProcess() uses OpenCV to do real time processing on the Images acquired from the USB camera.

Well, now we have a hole through, lets do something more interesting than drawing blue lines on the grabbed images:
At this url I found some image filters I would like to try.
In the file MyApplication.h add the include directive "#include "math.h"" after the other include directives, and add the define "#define PI 3.1415926535f" under the other defines then add the following line after the "void LiveProcess(IplImage *image);"

- - - Start cut'n paste - - -
void InitMatrix();
unsigned int* Matrix;

- - - End cut'n paste - - -

Go to the implementation of the function LiveProcess and add another global function below it:

- - - Start cut'n paste - - -
void InitMatrix()
{
     Matrix = new unsigned int[IMAGE_WIDTH*IMAGE_HEIGHT*IMAGE_CHANNELS];
     int halfH = IMAGE_HEIGHT/2;
     int halfW = IMAGE_WIDTH/2;
     float MaxRad = sqrt(halfH*halfH+halfW*halfW);

     int DistH,DistW,NewW,NewH,h,w;
     float DistRad,NewRad,Angle,NewAngle,factor,factor2;
     factor = 1;
     IplImage* Temp = cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT), IPL_DEPTH_8U, IMAGE_CHANNELS );
     int index=0;

     for( h =0;h < IMAGE_HEIGHT; h++ )
     {
          for(w = 0; w < IMAGE_WIDTH; w++)
          {
               DistH = h - halfH;
               DistW = w - halfW;

               DistRad = sqrt(DistH*DistH + DistW*DistW);

               if(DistH == 0)
               {
                    if (DistW == 0)
                         Angle = 0;
                    else if (DistW < 0)
                         Angle = PI;
                    else
                         Angle = 0;
               }
               else if (DistW == 0)
               {
                    if (DistH < 0)
                         Angle = PI/2;
                    else
                         Angle = 3*PI/2;
               }
               else if (DistH < 0)
               {
                    if( DistW < 0)
                         Angle = atan((float)DistW/(float)DistH) + PI/2;
                    else
                         Angle = atan(-(float)DistH/(float)DistW);
               }
               else
               {
                    if(DistW < 0)
                         Angle = 3*PI/2 - atan(-(float)DistW/(float)DistH);
                    else
                         Angle = 2*PI -atan((float)DistH/(float)DistW);
               }

               // This is the transformation default values
               NewAngle = Angle;
               NewRad = DistRad;

               // Different transformations
               // This do not work
               //factor2 = MaxRad*PI;
               //NewAngle = Angle + DistRad/factor2;

               //NewAngle = DistRad*IMAGE_HEIGHT/MaxRad;
               //NewRad = Angle*IMAGE_WIDTH/(2*PI);
               factor = 0.5;
               //NewRad = DistRad*DistRad/MaxRad;//Fisheye
               // This we try:
               NewRad = sqrt(DistRad*MaxRad);//Caricature
               // This is the transformation
               NewW = halfW + floor(factor * NewRad * cos(NewAngle));
               NewH = halfH - floor(factor * NewRad * sin(NewAngle));
               // End of transformation

               if(NewW < 0 )
                    NewW = 0;
               if(NewW > IMAGE_WIDTH-1)
                    NewW = IMAGE_WIDTH-1;

               if(NewH < 0)
                    NewH = 0;

               if(NewH > IMAGE_HEIGHT-1)
                    NewH = IMAGE_HEIGHT-1;

               for(index = 0; index < IMAGE_CHANNELS;index++)
                    Matrix[(h*IMAGE_WIDTH+w)* IMAGE_CHANNELS+index] = (NewH*IMAGE_WIDTH + NewW)* IMAGE_CHANNELS+index ;
          }
     }
}

- - - End cut'n paste - - -

Add the line in the start of the function "OnUsbGrab()"
- - - Start cut'n paste - - -
InitMatrix();
- - - End cut'n paste - - -

Change the contents of the function "LiveProcess(IplImage *image)" to
- - - Start cut'n paste - - -
     IplImage* image1 = image;
     IplImage* Temp = cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT), IPL_DEPTH_8U, IMAGE_CHANNELS );
     int i,j;

     assert (image);

     for(int index = 0;index < image->imageSize; index++ )
          Temp->imageData[ index ]= image1->imageData[ Matrix[index] ];

     memcpy(image1->imageData, Temp->imageData, image1->imageSize );
     cvReleaseImage(&Temp);

- - - End cut'n paste - - -

Go to the "CMyApplicationApp::InitInstance()" and add the line before the "return FALSE;" statement
- - - Start cut'n paste - - -
delete(Matrix);
- - - End cut'n paste - - -

Thats it! hit F5 to build and run your application, a pretty funny grab shows up, feel free to experiment with other transformations.

Press on the link to go back to the start go the tutorial.

^ back to top ^

 

Last updated:
May 3 - 2004: My counter from freewebcounter.com created popups, so a new counter is used.
July 11 2003 : Corrected some errors.
July 11 2003 : Did something more interesting in the callback than drawing blue lines.
May 11 2003 : uploaded