Using OpenCV with MFC

  | About Me | Links | Loading a bmp | Using OpenCV | Loading a tiff | Using a Matrox Frame grabber | Using a USB camera | Contact Me |

Looking into the Yahoo OpenCV Community I noticed that a lot of the questions to the message board, was related to how start working with the Library, this page will give a newcomer a easy way to be able to use the library and a little tutorial on MFC using Microsoft Visual Studio.

My background is embedded programming in C, not C++ or MFC so the structure and methods used might not be "by the book", but I will try to explain my steps in a simple and intuitive way, if you have any suggestion or corrections I will be very glad to receive them.

Before start the OpenCV must be downloaded and installed. I strongly advice to use the default folder: "C:\Program Files\Intel\OpenCV" (some regional windows settings puts the installed programs in a "localized" folder making it difficult to use downloaded visual studio workspaces), remember that the library dll's must be in the system search path.
Open the project "CV.dsp" in the "C:\Program Files\Intel\opencv\cv\make" folder and do a rebuild all -If any errors occur (ignore the warnings) do not continue with this tutorial. Solve all problems before continuing!

If any problems occurs under the installation -do remember to read the FAQ before sending any questions to the OpenCV Community. A good installation description can be found in this message #11925. A lot of the questions from newcomers (and others) is also duplicates of older questions -Use the search facility to find related questions, there are a great chance that your question have been answered before (At the beginning of 2003 way over 10.000 messages have been submitted to the Community, your question/problem might be among them).

Now Let's start:

In Visual Studio (VS) click on "File" and "New" to create a new project. Mark the "MFC AppWizard (exe)" and specify the project name e.g. "MyApplication". Click Ok.

New Project
Click on the thumbnail to view the actual FileNew dialog box.

In the first step of the MFC AppWizard choose a Dialog Based application and specify the language, click Next two times to get to step 3 of 4.

Step one of the MFC app Wizard
Click on the thumbnail to view the wizard step one dialog box.

In step 3 of 4 of the MFC App wizard set a mark in the radio button "As a static linked library" in "How would you use the MFC Library?". Somehow the memory leaks is avoided by this setting!!. Click Next, Finish and Ok.


Click on the thumbnail to view the wizard step 3 of 4 dialog box.

The next step is to embed the OpenCV workspace into the project, it is described very well in the FAQ. But I will give it another try here. 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" write a comma separated list of include directories. You can use either relative or absolute paths, write: "C:\Program Files\Intel\opencv\cv\include,C:\Program Files\Intel\opencv\otherlibs\highgui".

Specify Include directories
Click on the thumbnail to view the Project Settings dialog box for include directories.

Still with "All Configuration" in the "Settings for" roll down menu. Choose the "Link" Tab and "input" in the "Category" roll down menu.
Write, again a comma separated list of the relevant library paths: "C:\Program Files\Intel\opencv\lib" in the "Additional Library Path" edit box.

Dialog box for specifying additional libraries
Click on the thumbnail to view the Project Settings dialog box for additional libraries.

Now the Debug and release versions of the libraries must be specified.
With "Win32 Debug" marked in the "Settings for" roll down menu.
Choose the "Link" Tab and "input" in the "Category" roll down menu.
Write a space separated list of libraries: "cvd.lib HighGUId.lib" in the "Object/library modules "edit box.
Change the "Settings for" roll down menu to "Win32 Release". Write "cv.lib HighGUI.lib" in the "Object/library modules" edit box and press OK.


The OpenCV workspace is inserted in the workspace by choosing the "Project" menu and then "Insert Project into Workspace". Browse to and select "C:\Program Files\Intel\opencv\cv\make\cv.dsp" and "C:\Program Files\Intel\opencv\otherlibs\highgui\highgui.dsp".
Specify the Dependencies by clicking on the menu point "Project" and then "Dependencies...". Select "MyApplication" in the roll down menu and set a mark in the "CV" and "HighGUI" box, then select "HighGUI" in the rolldown and set a mark in "CV" and click on close.


Click on the thumbnail to view the Project Dependencies settings dialog.

The Work space browser can be used to browse the project by the ClassView/ResourceView/FileView (CVB,RVB,FVB)panes and is a fast way to access the code

Use the browser to access your code quickly
Click on the thumbnail to view the Work space browser.

Now right click on "MyApplication Files" in the FVB and roll down to "Set as active project" to specify this project as the one to build and debug on.

Now let start working with the library:

Double click on MyApplication.h and add the lines:

- - - Start cut'n paste - - -
#include "cv.h"
#include "HighGUI.h"
#define IMAGE_WIDTH 128
#define IMAGE_HEIGHT 128
#define IMAGE_CHANNELS 3
- - - End cut'n paste - - -

just below the "#include resource.h" line.

In the CVB right click on the CMyApplicationDlg class and add a member variable of type "IplImage*" and variable name "TheImage" let it be public.
Double click on the created variable in the CVB window and add the following lines below it but let them be protected:

- - - Start cut'n paste - - -
     BITMAPINFO* bmi;
     BITMAPINFOHEADER* bmih;
     RGBQUAD* palette;
     unsigned int buffer[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256];

- - - End cut'n paste - - -


Double click on OnInitDialog() again in the CVB and add the following lines after the "// TODO: Add extra initialization here" comment:

- - - Start cut'n paste - - -
     // Create the IPL image
     CvSize ImgSize;
     ImgSize.width = IMAGE_WIDTH;
     ImgSize.height = IMAGE_HEIGHT;
     TheImage = cvCreateImage( ImgSize, IPL_DEPTH_8U, IMAGE_CHANNELS );

     // Initialize the IPL image -actually not necessary

     //Grayscale
     if (TheImage->nChannels == 1)
     {
          float dx = (TheImage->width / 256.0f);

          for ( int w = 0; w < TheImage->width; w++ )
          for (int h = 0; h < TheImage->height; h++)
          {
               TheImage->imageData[ TheImage->height * w + h] = (char)(w / dx ); // Copy data to ipl
          }
     }
     else if(TheImage->nChannels == 3) //The image is RGB
     {
          IplImage* Temp = cvCreateImage( ImgSize, IPL_DEPTH_8U, 1 );

          int h,w;
          float dx = (Temp->width / 256.0f) ;

          for ( w = 0; w < Temp->width; w++ )
               for (h = 0; h < Temp->height; h++)
                    Temp->imageData[ Temp->height * w + h] = (char)(w / dx ); // Copy data to ipl
          cvSetImageCOI( TheImage, 1); //Choose the blue channel of interest
          cvCopy(Temp,TheImage);

          for ( w = 0; w < Temp->width; w++ )
               for (h = 0; h < Temp->height; h++)
                    Temp->imageData[ Temp->height * w + h] = (char)(255 - w / dx ); // Copy green data to ipl
          cvSetImageCOI( TheImage, 2); //Choose the green channel of interest
          cvCopy(Temp,TheImage);

          for ( w = 0; w < Temp->width; w++ )
               for (h = 0; h < Temp->height; h++)
                    Temp->imageData[ Temp->height * w + h] = (char)(w / dx ); // Copy red data to ipl
          cvSetImageCOI( TheImage, 3); //Choose the red channel of interest
          cvCopy(Temp,TheImage);

          cvReleaseImage(&Temp);
     }

- - - End cut'n paste - - -

This creates a IPL image and initializes the image data to a grayscale ramp function, black in top and white in bottom.

Just below the code inserted above insert the following code:

- - - Start cut'n paste - - -
     //Initialize the BMP display buffer
     bmi = (BITMAPINFO*)buffer;
     bmih = &(bmi->bmiHeader);
     memset( bmih, 0, sizeof(*bmih));
     bmih->biSize = sizeof(BITMAPINFOHEADER);
     bmih->biWidth = IMAGE_WIDTH;
     bmih->biHeight = -IMAGE_HEIGHT;
     bmih->biPlanes = 1;
     bmih->biCompression = BI_RGB;
     bmih->biBitCount = 8 * TheImage->nChannels;
     palette = bmi->bmiColors;
     if (TheImage->nChannels == 1)
          {
          for( int i = 0; i < 256; i++ )
          {
               palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
               palette[i].rgbReserved = 0;
          }
     }
- - - End cut'n paste - - -

This creates a display buffer for drawing our IPL image

Click again on the CMyApplicationDlg class and add a member function of type void and called DisplayMyData, double click on it to get to the function and add the lines:

- - - Start cut'n paste - - -
     CPaintDC dc(this);
     CDC* pDC = &dc;

     int res = StretchDIBits(
          pDC->GetSafeHdc(), //dc
          0, //x dest
          0, //y dest
          int(IMAGE_WIDTH), //x dest dims
          int(IMAGE_HEIGHT), //y dest dims
          0, // src x
          0, // src y
          IMAGE_WIDTH, // src dims
          IMAGE_HEIGHT, // src dims
          TheImage->imageData, // array of DIB bits
          (BITMAPINFO*)bmi, // bitmap information
          DIB_RGB_COLORS, // RGB or palette indexes
          SRCCOPY); // raster operation code

     // Update Window, force View to redraw.
     RedrawWindow(
          NULL, // handle to window
          NULL, // update rectangle
          RDW_INVALIDATE // handle to update region
          );

- - - End cut'n paste - - -

Couble click on the function OnPaint() and add the line:

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

in the else bracket part, before the line "CDialog::OnPaint();"

Click on InitInstance() in the CVB and add the following line after the two "// TODO:" to clean up the memory:

- - - Start cut'n paste - - -
     cvReleaseImage(&dlg.TheImage);
- - - End cut'n paste - - -

Thats it! hit F5 to build and run your application!

Click Here to customize the project by loading a bmp file into the ipl structure.

^ back to top ^

 

Last updated:
July 10 - 2003: Made the handling of gray scale or color dependent of one define.
June 21 - 2003: Minor change corrected spelling.
June 18 - 2003: Removed dependency of the IPL library
May 27 - 2003: Corrected the install path to C:\Program Files\Intel\OpenCV.
May 11 - 2003: Adding use of USB camera.
May 6 - 2003: Moving the displayed Ipl image to position 0,0 in StretchDIBits().
May 5 - 2003: Memory leak work-around.