Top Banner
Using OpenCV with MFC 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.
31
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Using OpenCV With MFC

Using OpenCV with MFC

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.

Page 2: Using OpenCV With MFC

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.

Page 3: Using OpenCV With MFC

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.

Page 4: Using OpenCV With MFC

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

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.

Page 5: Using OpenCV With MFC

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.

Page 6: Using OpenCV With MFC

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

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.

Page 7: Using OpenCV With MFC

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

Page 8: Using OpenCV With MFC

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:

Page 9: Using OpenCV With MFC

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

Page 10: Using OpenCV With MFC

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!

Using OpenCV with MFC - Loading a

bmp-file

Here I will add code that will load a bitmap file into an IplImage, as a step before using the OpenCV library to do some image processing.

Now right click on "MyApplication classes" in the CVB and then on "New Class" to create a class to do some image processing with the library, make it a "Generic

Page 11: Using OpenCV With MFC

Class" and name it "MyIplClass"

Click on the thumbnail to view the New class Dialog Box.

This creates and adds two new files to the project work space, "MyIplClass.ccp" and "MyIplClass.h" can be seen in the FVB, with constructor MyIplClass() destructor ~MyIplClass() in the CVB. Double click on "MyApplication.h" and add the line: - - - Start cut'n paste - - - #include "MyIplClass.h" - - - End cut'n paste - - - Below the "include resource.h" and move the other include directives to "MyIplClass.h" (double click on FVB to get there) just before the class declaration also do a include of ipl.h: - - - Start cut'n paste - - - #include "cv.h" #include "HighGUI.h" #define IMAGE_WIDTH 128 #define IMAGE_HEIGHT 128 - - - End cut'n paste - - -

Page 12: Using OpenCV With MFC

Right click on "MyIplClass" in the CVB and add a public member variable "IplImage*" called "m_Ipl". Double click on the constructor "MyIplClas()" to get to the code and add the following lines: - - - Start cut'n paste - - - // Create the IPL image m_Ipl = cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT), IPL_DEPTH_8U, 1 ); // Use this line if the bitmap is 24 bit //m_Ipl = cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT), IPL_DEPTH_8U, 3 ); - - - End cut'n paste - - - And double click on the destructor ~MyIplClass() in the CVB and add the code: - - - Start cut'n paste - - - cvReleaseImage(&m_Ipl); - - - End cut'n paste - - - Right click on "MyIplClass" in the CVB and add a member function called GetIplData(IplImage* ipl) and of type void. Double click on the new function and add the line: - - - Start cut'n paste - - - memcpy(ipl->imageData, m_Ipl->imageData, m_Ipl->imageSize); - - - End cut'n paste - - -

Right click on "MyIplClass" in the CVB and add a member function called LoadBMP(CString FileName) of type void with the lines: - - - Start cut'n paste - - - // Do it the easy way with HighGUI BMP, DIB,JPEG, JPG, JPE,PNG,PBM, PGM, PPM, SR, RAS, TIFF, TIF // m_Ipl = cvLoadImage( FileName, 0); // Or the hard way: BOOL ok = TRUE; CFile SrcFile; char *ReadBuffer; // Pointer to read buffer char *OutputBuffer; // Pointer to output buffer BITMAPFILEHEADER BmpFileHeader; unsigned int BmpHeadSize; char *BmpHeadPtr;

Page 13: Using OpenCV With MFC

BITMAPINFOHEADER *BmpInfoPtr; int i; if ( !SrcFile.Open( FileName, ( CFile::modeRead | CFile::typeBinary), NULL ) ) { AfxMessageBox("Could not open file"); } // Read the BMP File header ok = ok && ( SrcFile.Read( &BmpFileHeader, sizeof( BmpFileHeader )) == sizeof( BmpFileHeader )); // Test settings in BMP file header. ok = ok && ( BmpFileHeader.bfType == 'MB' ); /* Bitmap file */ // Find the size of the rest of the BMP header BmpHeadSize = BmpFileHeader.bfOffBits - sizeof( BmpFileHeader ); // Allocate space for the rest of the BMP header BmpHeadPtr = new char[ BmpHeadSize ]; ok = ok && ( BmpHeadPtr != NULL ); // Read the rest of the BMP header - Info part and color table part ok = ok && ( SrcFile.Read( BmpHeadPtr, BmpHeadSize ) == BmpHeadSize ); // Make a cast to the type we think is the Info part of the header BmpInfoPtr = ( BITMAPINFOHEADER* ) BmpHeadPtr; // Test settings in BMP info header. ok = ok && ( BmpInfoPtr->biSize == sizeof( BITMAPINFOHEADER ) ); ok = ok && ( BmpInfoPtr->biWidth == IMAGE_WIDTH ); ok = ok && ( BmpInfoPtr->biHeight == IMAGE_HEIGHT ); ok = ok && ( BmpInfoPtr->biPlanes == 1 ); ok = ok && ( BmpInfoPtr->biBitCount == 8 ); // Use this line if the bitmap is 24 bit // ok = ok && ( BmpInfoPtr->biBitCount == 24 ); ok = ok && ( BmpInfoPtr->biCompression == BI_RGB ); ok = ok && ( BmpInfoPtr->biSizeImage == IMAGE_HEIGHT * IMAGE_WIDTH ); // Use this line if the bitmap is 24 bit //ok = ok && ( BmpInfoPtr->biSizeImage == IMAGE_HEIGHT * IMAGE_WIDTH * 3 );

Page 14: Using OpenCV With MFC

if (ok) { // Allocate a buffer for destination data ReadBuffer = new char[ BmpInfoPtr->biSizeImage ]; // Read the BMP data from the source file SrcFile.Read( ReadBuffer, BmpInfoPtr->biSizeImage ); // Allocate a buffer for upside down corrected data OutputBuffer = new char[ BmpInfoPtr->biSizeImage ]; for(i = 0; i < IMAGE_HEIGHT; i++) { memcpy(&OutputBuffer[(IMAGE_HEIGHT - i - 1) * IMAGE_WIDTH], &ReadBuffer[i * IMAGE_WIDTH], IMAGE_WIDTH); // Use this line if the bitmap is 24 bit // memcpy(&OutputBuffer[(IMAGE_HEIGHT - i - 1) * IMAGE_WIDTH*3], &ReadBuffer[i * IMAGE_WIDTH*3], IMAGE_WIDTH*3); } // Now copy the read data to the IPL structure memcpy(m_Ipl->imageData, OutputBuffer, BmpInfoPtr->biSizeImage ); delete OutputBuffer; delete ReadBuffer; } else { AfxMessageBox("Wrong image size"); } delete BmpHeadPtr; SrcFile.Close(); - - - End cut'n paste - - -

Now click on the RVB (Resource View Browser), then on "MyApplication resources" then double click on "ID_MYAPPLICATION_DIALOG" this brings you to the Dialog Editor Window. Drag a button from the tool line to a corner of your dialog, right click on the button and then click on the "Properties"to be able to edit the properties for this control. In the "ID:" field write "IDC_PROCESS" and in the "Caption" field write "Process" close the properties window. Double click on the created button to make a function named "OnProcess" and get to the code part of this function. Add the lines:

Page 15: Using OpenCV With MFC

- - - Start cut'n paste - - - MyIplClass *Img= new MyIplClass; CString filename; // This file should be part of the OpenCV kit. filename = "C:\\Program Files\\Intel\\opencv\\tests\\cv\\testdata\\snakes\\ring.bmp"; Img->LoadBMP(filename); Img->GetIplData( TheImage ); delete Img; RedrawWindow(NULL, NULL, RDW_INVALIDATE ); //Force update of dialog; - - - End cut'n paste - - - Thats it hit F5 to build and run, when the "Process" button is pressed the ring appears.

Using OpenCV with MFC -

Customizing: step two

Here I will use OpenCV on the bitmap loaded on step one. In the CVB right click on "MyIplClass" and then on "Add member function", let the type be "void" and in "function declaration" write "ProcessIpl()". I will do all the image processing inside this function. I'll use the CVSnake on the bitmap and display the result In the function "ProcessIpl" add the code below: - - - Start cut'n paste - - - IplImage *IplTmp1,*IplTmp2,*IplTmp3; IplTmp1 = cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT), IPL_DEPTH_8U, 1 ); IplTmp2 = cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT), IPL_DEPTH_8U, 1 ); IplTmp3 = cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT), IPL_DEPTH_8U, 1 ); int ThressValue = 90; float alpha = 3;

Page 16: Using OpenCV With MFC

float beta = 5; float gamma = 2; CvSize win; CvTermCriteria criteria; int jumpPoint; CvPoint *WholePointArray; CvPoint *PointArray; const int NUMBER_OF_SNAKE_POINTS= 50; PointArray = (CvPoint *)malloc(NUMBER_OF_SNAKE_POINTS * sizeof(CvPoint)); cvCopyImage( m_Ipl,IplTmp3); //IplTmp3 is the image to draw temp results to cvCopyImage( m_Ipl, IplTmp1);//(src,dst) copy to Working ipl image (IplTmp1 and IplTmp2 is working containers) // Make a average filtering cvSmooth(IplTmp1,IplTmp2,CV_BLUR,31,15); // iplBlur( IplTmp1, IplTmp2, 31, 31, 15, 15); //Don't use IPL //Do a threshold cvThreshold(IplTmp2,IplTmp1,ThressValue,255,CV_THRESH_BINARY); //iplThreshold(IplTmp2,IplTmp1,ThressValue); // DistImg is thressholded image (IplTmp1)//Don't use IPL // expand the thressholded image of ones -smoothing the edge. //And move start position of snake out since there are no ballon force cvDilate( IplTmp1, IplTmp2, NULL, 3); //Find the contours CvMemStorage *storage; CvSeq* contour = NULL; storage = cvCreateMemStorage (0); cvFindContours( IplTmp2,storage, &contour,sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE ); //Run through the found coutours while( contour != NULL ) { if ( contour ->total >= NUMBER_OF_SNAKE_POINTS) { cvSmooth(m_Ipl,IplTmp2,CV_BLUR,7,3); //iplBlur( m_Ipl, IplTmp2, 7, 7, 3, 3); // Put blured image in TempImg//Don't use IPL WholePointArray = (CvPoint *)malloc(contour->total * sizeof(CvPoint)); cvCvtSeqToArray(contour, WholePointArray, CV_WHOLE_SEQ); //Copy the contour to a array

Page 17: Using OpenCV With MFC

// Number of jumps between the desired points (downsample only!) jumpPoint = (int)(contour->total / NUMBER_OF_SNAKE_POINTS); for (int i=0; i < NUMBER_OF_SNAKE_POINTS; i++) { PointArray[i].x = WholePointArray[ (int)( i*jumpPoint)].x; PointArray[i].y = WholePointArray[ (int)( i*jumpPoint)].y; } // Now for the snake criteria.maxIter = 100; // Do max N iterations criteria.epsilon = 1; // If only N points is moved then terminate criteria.type = CV_TERMCRIT_EPS|CV_TERMCRIT_ITER; win.width = 21; // search for energi minimizing in this area around snake points win.height = 21; // Be sure that width and heigth is uneven // Iterate snake cvSnakeImage(IplTmp2, PointArray, NUMBER_OF_SNAKE_POINTS, &alpha, &beta, &gamma, CV_VALUE, win, criteria,1); // Draw snake on image int n = NUMBER_OF_SNAKE_POINTS; cvPolyLine( IplTmp3, &PointArray, &n, 1,1, 255, 3,8 ); free(WholePointArray); } //Get next contour contour = contour->h_next; } //Clean up free (contour); free(PointArray); cvReleaseMemStorage(&storage); //Save result cvCopyImage( IplTmp3, m_Ipl);//(src,dst) // Clean up cvReleaseImage(&IplTmp1); cvReleaseImage(&IplTmp2); cvReleaseImage(&IplTmp3);

Page 18: Using OpenCV With MFC

- - - End cut'n paste - - - Then go to the OnProcess() through the CVB and add following line just after the line "Img->LoadBMP(filename);" - - - Start cut'n paste - - - Img->ProcessIpl(); - - - End cut'n paste - - - Thats it hit F5 to build and run, when the "Process" button is pressed the ring appears with a superimposed "snake".

Using OpenCV with MFC - Loading a

tif-file

Here I will add code that will load a tif file into an IplImage.

To load a tiff-file a whole lot of code must be written and this is out of scope of this little tutorial. So I will use a library found on the internet to do this in a easy way. This library is called libtiff and the easies way to find them is to use google, search for "libtiff binaries windows". I found them here named "libtiff_bin_354.zip" but they might have moved -so use google to locate them. Extract the zip file to a temporary folder, then move only the subfolder "libtiff" to "C:\Program Files" so that the dll, lib and h-files is located in the folder "C:\Program Files\libtiff" -Add this folder to the search path or move the file "libtiff.dll" into e.g. "C:\Windows\system32". (To keep the documentation for the library the html folder can be a subfolder of libtiff).

Now press Alt-F7 to get to the "Project settings" and choose "All Confiurations" in the "Settings For:" with "MyApplication" highlighted. In the "Link" pane choose "Input" in the roll down menu of the "Category:" field, and add " libtiff.lib" to the "Object/library modules:" field, the filenames in the field must be space separated e.g "OpenCV.lib libtiff.lib". Add the path of the library "C:\Program Files\libtiff" to the "Additional library path:"

Page 19: Using OpenCV With MFC

the path names must be comma separated e.g "C:\Program Files\Intel\opencv\lib,C:\Program Files\libtiff". Now go to the "C/C++" pane and with "Preprocessor" chosen on the "Category:" roll down menu add the path to the library in the "Additional include directories:" e.g "C:\Program Files\Intel\opencv\cv\include,C:\Program Files\libtiff"

Use the FVB and double click on "MyIplClass.h" and include the library after the other include directives with: - - - Start cut'n paste - - - #include "tiff.h" #include "tiffio.h" - - - End cut'n paste - - -

In the CVB right click on "MyIplClass" and add the void member function "LoadTiff(CString FileName)" and add the following code to the function body: - - - Start cut'n paste - - - int npixels; unsigned int w,h,Width,Height; unsigned long* TIFFImageData; TIFF* tif= TIFFOpen(FileName, "r"); // Open filename if (tif!=NULL) { TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &Width); // get size TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &Height); if ( (Width == IMAGE_WIDTH) || (Height == IMAGE_HEIGHT) ) { npixels = Width * Height; TIFFImageData = (uint32*) _TIFFmalloc(npixels * sizeof (uint32)); // allocate temp memory if (TIFFImageData == NULL) m_Ipl = NULL; if ( !TIFFReadRGBAImage(tif, Width, Height, TIFFImageData, 0) ) m_Ipl = NULL; for ( w = 0; w < Width; w++ ) for (h = 0; h < Height; h++)

Page 20: Using OpenCV With MFC

m_Ipl->imageData[Height*w + h]=(char)TIFFImageData[Height*w + h]; // Copy data to ipl _TIFFfree(TIFFImageData); // Release temp memory } else { AfxMessageBox("Wrong size of tiff image"); } TIFFClose(tif); } - - - End cut'n paste - - -

Now find a program to convert ring.bmp to a tiff file e.g. Paint Shop Pro and save it as "ring.tif" in the same folder, go to "OnProcess()" with the CVB and change the lines with the file name and load function to: - - - Start cut'n paste - - - filename = "C:\\Program Files\\Intel\\opencv\\tests\\cv\\testdata\\snakes\\ring.tif"; Img->LoadTiff(filename); - - - End cut'n paste - - - Thats it hit F5 to build and run, when the "Process" button is pressed the ring appears with a superimposed "snake". The interesting fact is that the final snake have another appearance compared with the result from the bmp-file.

Using OpenCV with MFC - Using a

matrox meteor II-MC

Here I will add code that grab frames from a Matrox Meteor II-MC and other Matrox frame grabbers.

Before continuing with this guide be sure that the installation of the framegrabber is ok - test the installation with the Intellicam application. If the Intellicam application can connect with your camera it should be possible to continue.

Page 21: Using OpenCV With MFC

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

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\Matrox Imaging\mil\include" to the comma separated list. Still with "All Configuration" in the "Settings for" roll down menu. Choose the "Link" Tab and "input" in the "Category" roll down menu and add "C:\Program Files\Matrox Imaging\mil\library\winnt\msc\dll" to the comma separated "Additional Library path". Add "mil.lib" to the space separated "Object/library modules" list.

Open MyIplClass.h and add the following include directive under the others. - - - Start cut'n paste - - - #include "mil.h" - - - End cut'n paste - - -

Double click on TheImage member variable of CMyApplicationDlg in the CVB and add the following code below it: - - - Start cut'n paste - - - MIL_ID MilApplication; // Application identifier. MIL_ID MilSystem; // System identifier. MIL_ID MilDigitizer; // Digitizer identifier. MIL_ID MilImage; // Image buffer identifier. MIL_ID MilDisplay; long NumberOfDigitizer; // Number of digitizers available on the system long SizeX; // Buffer Size X long SizeY; // Buffer Size Y long DigSizeX; // Digitizer input width long DigSizeY; // Digitizer input heigh long Band; // Number of input color bands of the digitizer BOOL GrabIsStarted; // State of the grab HWND hWnd; - - - End cut'n paste - - -

Doubleclick on OnInitDialog() and add the following code to allocate and initialize the Matrox Meteor Framegrabber before the "return TRUE;" statement.

Page 22: Using OpenCV With MFC

- - - Start cut'n paste - - - // Allocate an application MappAlloc(M_DEFAULT,&MilApplication); // Allocate a system MsysAlloc(M_SYSTEM_SETUP,M_DEF_SYSTEM_NUM,M_COMPLETE,&MilSystem); // Inquire number of digitizers available on the system MsysInquire(MilSystem,M_DIGITIZER_NUM,&NumberOfDigitizer); // Digitizer is available if (NumberOfDigitizer) { // Allocate a digitizer MdigAlloc(MilSystem,M_DEFAULT,M_CAMERA_SETUP,M_DEFAULT,&MilDigitizer); // Stop live grab when window is disable MsysControl(MilSystem,M_STOP_LIVE_GRAB_WHEN_DISABLED,M_ENABLE); // Inquire digitizer informations MdigInquire(MilDigitizer,M_SIZE_X,&DigSizeX); MdigInquire(MilDigitizer,M_SIZE_Y,&DigSizeY); MdigInquire(MilDigitizer,M_SIZE_BAND,&Band); MbufAlloc2d(MilSystem, DigSizeX, DigSizeY,8L+M_UNSIGNED, M_IMAGE+M_GRAB, &MilImage); MdispAlloc(MilSystem, M_DEF_DISPLAY_NUM, M_DEF_DISPLAY_FORMAT, M_WINDOWED, &MilDisplay); if (DigSizeX > M_DEF_IMAGE_SIZE_X_MAX) DigSizeX = M_DEF_IMAGE_SIZE_X_MAX; if (DigSizeY > M_DEF_IMAGE_SIZE_Y_MAX) DigSizeY = M_DEF_IMAGE_SIZE_Y_MAX; } // Digitizer is not available else { SizeX = M_DEF_IMAGE_SIZE_X_MIN; SizeY = M_DEF_IMAGE_SIZE_Y_MIN; Band = M_DEF_IMAGE_NUMBANDS_MIN; } // Initialize the state of the grab GrabIsStarted = FALSE;

Page 23: Using OpenCV With MFC

- - - 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_GRAB" and the Caption to "Grab". Close the Properties dialog box and double click on the new button to add a function called "OnGrab" 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 hWnd = AfxGetMainWnd()->m_hWnd; MdispSelectWindow(MilDisplay, MilImage, hWnd); if (GrabIsStarted == FALSE) { // Start a continuous grab in this view MdigGrabContinuous(MilDigitizer, MilImage); // Update the variable GrabIsStarted GrabIsStarted = TRUE; pButton = GetDlgItem(IDC_GRAB); pButton->SetWindowText("Stop"); } else { // Stop a continuous grab in this view MdigHalt(MilDigitizer); // Update the variable GrabIsStarted GrabIsStarted = FALSE; pButton = GetDlgItem(IDC_GRAB); pButton->SetWindowText("Grab"); // Now get the Grabbed pixels MbufInquire(MilImage, M_HOST_ADDRESS, &TheImage->imageData); RedrawWindow(NULL, NULL, RDW_INVALIDATE ); //Force update of dialog; }

Page 24: Using OpenCV With MFC

- - - End cut'n paste - - -

In the function CMyApplicationDlg::OnPaint() change the code in the else part to: - - - Start cut'n paste - - - if (!GrabIsStarted) DisplayMyData(); //Only redraw iplimage if not grabbing CDialog::OnPaint(); - - - End cut'n paste - - -

Add a function "SetIplData(IplImage *ipl)" returning void, to the class MyIplClass. and add the code: - - - Start cut'n paste - - - memcpy(m_Ipl->imageData, ipl->imageData, m_Ipl->imageSize); - - - End cut'n paste - - -

Change the code in CMyApplicationDlg::OnProcess() to: - - - Start cut'n paste - - - MyIplClass *Img= new MyIplClass; Img->SetIplData(TheImage); //Copy the content of TheImage to the class for processing Img->ProcessIpl(); Img->GetIplData( TheImage ); delete Img; RedrawWindow(NULL, NULL, RDW_INVALIDATE ); //Force update of dialog; - - - End cut'n paste - - -

Thats it! hit F5 to build and run your application! Press the Grab button to start grabbing, then on Stop and on Process to use OpenCV on the grabbed image.

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

Using OpenCV with MFC - Grabbing

using a USB Camera

Page 25: Using OpenCV With MFC

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

Page 26: Using OpenCV With MFC

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

Page 27: Using OpenCV With MFC

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

Page 28: Using OpenCV With MFC

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++ ) {

Page 29: Using OpenCV With MFC

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

Page 30: Using OpenCV With MFC

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

Page 31: Using OpenCV With MFC

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.