You are on page 1of 31

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.

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.

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

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.

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

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!

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

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

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;

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

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:

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

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

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

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

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

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.

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.

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

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

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

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.

You might also like