Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Easy to use Wrapper (DLL) for Intel's OpenCV Library with Examples

0.00/5 (No votes)
3 Mar 2009 5  
The article describes an easy to use a wrapper for Intel's OpenCV lib with examples.

cvlib versions: A.B.C

  • A = major version; will not be changed until a completely new version. For example build with SWIG.
  • B = minor version; will change when a new sublib like ML or cvaux is added
  • C = Build; will change with each new released distribution (any changes)

Latest is 1.0.3.
Look here for frequently updates: Downloads

Content

  1. Introduction - Intel's openCV libs and the wrapper
  2. Features of the wrapper
  3. Environment and IDE
  4. Installation
    1. Common using of wrapper DLLs
    2. Sample binaries
    3. Sample sources / Visual Studio Projects
    4. Recompile the wrapper library
  5. Let's start - A short tutorial
  6. Overloading instead of default arguments
  7. Error Handling
  8. Marshalling - P/Invoke
    1. Internal wrapper function calls
    2. Table with conversions which has been used
    3. The cvtools - class
  9. Low level access for pixels and sequences
  10. Actual state of implementation and known problems
  11. Examples
    1. The "BigSample" application
    2. Optical flow sample
    3. Squares sample
  12. History
  13. Contact and frequently Updated
  14. In own matter :-) 

I. Introduction - Intel's openCV Libs and the Wrapper

opencv.jpg

The OpenCV Library (or Open Computer Vision Library) is a open source computer vision library developed by Intel and first released for the open source domain in 2002. It contains many algorithms and examples for image processing and for machine vision. Some actual links to resources and information are:

Provided in the form of a dynamic link library (DLL), the presented wrapper enables you to call the library function from within the modern .NET language C#. Porting my software wasn't the hardest obstacle, but I wasn't familiar with interop mechanism which was need to adopt Intel's library. After searching the net, I found two possible solutions. On one side was SharperCV and on the other EmGuCv. Both projects are quite extensive and cover a rich set on functionality and I have to acknowledge that I got many hints from it and also used some small pieces of code. The underlying reason why I decided to write my own library was to learn more about Platform invoke (P/invoke) and to create a library which is usable, where one can write method calls in a "c-style" manner. Ideally it should take as little effort as possible for a user to learn something about the wrapper and it should be sufficient to only read the original OpenCV documentation and of course some of my documentation.

The OpenCV Library has an extensive amount of highly developed algorithms (more than 400 functions, hundreds of macros, myriads of constants, etc.) so it seemed nearly impossible for a single person to encapsulate all of this. Additionally, there is a lot of overloading and default values. The idea was to write a simple HTML parser that on the one hand was able to extract all function prototypes and descriptions from the OpenCV HTML documentation, and on the other able to generate the necessary code by using predefined rules. With this, I could save a lot of time but because I did not have the time to write a perfect converter and the resulting code was not perfect, much additional handwork was necessary.
Actually I learnt to use the swig - converter that would enable me easily wrap classes like ml (machine learning) too.

II. Features of the Wrapper

  • The wrapper is provided in the form of a dynamic link library (DLL)
  • All exported methods (e.g. cvCanny,...), the most important macros, constructors, constant definitions and callbacks are visible through on class. (e.g.: cvlib.Functionname(...), cvlib.CV_LOAD_IMAGE_COLOR).
  • All structure definitions are usable in a familiar way (e.g. IplImage img, CvMat mat).
  • A few special function arguments are passed by IntPtr, and for casting additional support is available (a second tools library, see cvtools)
  • The conversion to and from drawing types like Bitmap is integrated in the Library and casting operator/function to and from Bitmap are available.
  • For error handling, the provided mechanisms of the OpenCV Library can be used. There is no support for exceptions (still not).
  • Callbacks are handled by predefined delegates. Use trackbars in a child window, mouse callbacks and error handlers in a familiar way.
  • The user has to take care of freeing the unmanaged memory. This is simply done by call to the appropriate OpenCV functions, e.g. cvlib.CvReleaseImage(...).
  • A huge set of samples are available and because of the big resonance, a lot of bugs could be fixed till now. Many thanks here to the community.
  • Due to requests I now added support for iterations (for example iteration through CvSeq or trees) and low level access without using unsafe code.

III. Environment and IDE

  • Visual Studio 2005 Standard Edition
  • Version 8.050727.762 (SP.050727-7600)
  • Microsoft .NET Framework 1.1. / 2.0 / 3.0

IV. Installation

I decided to divide this section into several parts depending on what you want to do. Therefore some lines have been simply copied. In every case, it is necessary to download the original Intel OpenCV DLLs from the official website at sourceforge or you use the provided link.

1. Common Using of the Wrapper DLLs

  1. Download "cvlib_bin.zip" from the above links and openCV libs (DLLs) for example from here.
  2. Extract both zips in a folder of your choice.
  3. Select either debug DLLs or release versions from the folders and copy it to your project Debug or Release folder. It is important not to mix debug and release versions. This can possibly crash your application.
  4. Add a reference to the wrapper DLL in your Visual Studio project reference tab (how to: look at section 3.6 below: Usage of sample sources / Visual Studio Projects)

2. Sample Binaries

  1. Download "cvlib_bin.zip", "samples_bin.zip" from the above links and openCV libs (DLLs) for example from here, if not already done. Extract zips in a folder of your choice. For the wrapper DLLs, you will get Debug and Release folder for each sample one more zip. Select the sample you want and extract.
  2. Copy the RELEASE versions of the wrapper DLL and all RELEASE openCV DLLs to the sample folders that contain the EXE file.
  3. Run the sample. If you want to try out the Camera Calibration (within the 'bigexample application') there are some images in the folder beside the EXE folder. You can use this for teaching and one for undistorting demonstration.

3. Sample Sources / Visual Studio Projects

  1. Download "cvlib_bin.zip", "samples_src.zip" from the above links and openCV libs (DLLs) for example from here, if not already done. Extract the zip files in a folder of your choice. For the wrapper DLLs, you will get Debug and Release folder for each sample source one more zip. Select the sample you want and extract. Each sample source zip contains a complete Visual Studio solution.
  2. Go to the project folders of Visual Studio and create bin\Debug, and bin\Release directories.
  3. Copy the DLLs from "cvlib_bin" to the debug and release folder you have just created. Also copy the XML files, if you want to read the methods tool tip messages generated by the VS intellisense feature.
  4. Go to your studio environment for a project and look at the left side for references, click with the right mouse button and choose "Add Reference".
  5. From the menu, select the "Browse" tab page, go to the bin/debug folder of your project (depending on whether you are in the debug or release modus) and add only the cvlib.dll.

    cvlib2.jpg

  6. For your own projects, you also need to add a using-reference ("using OpenCV ") at the top of your *.cs where you want to use the library.

4. Recompile the Wrapper Library

  1. Download "cvlib_src.zip" from the above links and extract to a directory of your choice.
  2. Double click "openCV.csproj" file to open Visual Studio project.
  3. Change what you want in the code.
  4. Compile the library in debug or release mode.
  5. Don't forget to report your extensions or fixes to the community :-)

V. Let's Start - A Short Tutorial

For this tutorial, you can use the "SmallExample" - Visual Studio project which is provided within the downloads if you don't want to code the small GUI. The example illustrates how to implement a simply canny edge detector with its image output in a picture box control and an OpenCV image window. It will then later be extended with error handling, a track bar and it will be shown as to how to retrieve mouse coordinates from the extern OpenCV window.

Your first step is to create a Windows Form application and add all DLLs and a reference to the wrapper as described above in the install section. Add two buttons and a picture box control to your form. The one button is simply to exit the application the other is intended to load an image file in your application. Add an "openFileDialog" Control from the Toolbox. Create the event handler for the buttons (by double clicking on the control). In the "Open File" button eventhandler, add the following code:

private void buttonFile_Click(object sender, EventArgs e)
{
IplImage img
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
// Load image from file
img = cvlib.CvLoadImage(openFileDialog.FileName, cvlib.CV_LOAD_IMAGE_COLOR);
// Create external window
cvlib.CvNamedWindow("MyWindow", cvlib.CV_WINDOW_AUTOSIZE);
// Show the image in external Window
cvlib.CvShowImage( "MyWindow", ref img );
// Show the image additional in the Picture Box Control
this.pictureBox1.Image = (Bitmap)img;
}
}

It is assumed that the Visual Studio Code Generator adds the name "openFileDialog1" for the file dialog. As you can see, it's quite simple to use the library calls. Type the prefix "cvlib." and after the dot, one can select the required operation from the list that appears (In Visual Studio with intellisense on). Most of openCV operations start with the prefix "cv". In difference to the original library calls in the wrapper, all operators start with an uppercase letter. In the file event handler we load an image from file, create an external window and show the image in this window. Quite often we pass an argument by reference keyword. This is because openCV lib expects a pointer to that datatype and wants to perform read and/or write operations to that object. Maybe you noticed that I didn't take care, at the moment, to release the unmanaged memory (the IplImage, and disposing the bitmap image). You are responsible for doing this any time an image has to be released (or any other unmanaged memory) by using the desired calls (see below). Because we hold our image in a class variable, we will release the memory in the forms Close event (not shown here).
In the next step, we will add the edge detector. But to achieve this, we first have to create a grey level image and apply a color conversion and we will keep in mind that we now have a second image that has to be released.

private void buttonFile_Click(object sender, EventArgs e)
{
IplImage img, gray;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
// Load image from file
img = cvlib.CvLoadImage(openFileDialog.FileName, cvlib.CV_LOAD_IMAGE_COLOR);
// create grey channel image
gray = cvlib.CvCreateImage(new CvSize(img.width, img.height), 
				(int)cvlib.IPL_DEPTH_8U, 1);
// color conversion
cvlib.CvCvtColor(ref img, ref gray, cvlib.CV_BGR2GRAY);
// apply the operator
cvlib.CvCanny(ref gray, ref gray, 100, 100, 3);
// Create external window
cvlib.CvNamedWindow("MyWindow", cvlib.CV_WINDOW_AUTOSIZE);
// Show the edge image in external Window
cvlib.CvShowImage( "MyWindow", ref gray );
// Show the input image in the Picture Box Control
this.pictureBox1.Image = (Bitmap)img;
}
}

Now you are ready to run the application to see the results. Did it work? I hope.

We are now going to add a track bar control to the external window and receive mouse events. We will display the mouse coordinates in a label. So please add a label control for the text output anywhere on your form window.

Because the C# language uses so called delegates for receiving events, we must follow these conventions. In the presented cvlib.dll predefined delegates are already implemented, so one has only to instantiate it. We do this by adding two members and allocate it in the forms constructor.

public partial class Form1 : Form
{
...
private cvlib.OnTrackbarChangeCallback onChange;
private cvlib.OnMouseCallback onMouse;
...
public Form1()
{
InitializeComponent();
...
onChange = new cvlib.OnTrackbarChangeCallback(OnChange);
onMouse = new cvlib.OnMouseCallback(OnMouse);
...
}
...
}

Now we can add eventhandler for the callbacks. The names for the handlers (method names) are not restricted. Feel free to select a name of your choice. In the example, I used "OnChange" and "OnMouse". "OnChange" will be called if a trackbar event occurs, "OnMouse" when the mouse has been moved.

More important than the names of the eventhandlers are their parameter lists. Either you watch the line that will pop up when you typed in the opening brace (in Visual Studio with intellisense on) or you get it from the OpenCV documentation.

// this Method is called when Trackbar value changed
private void OnChange(int value)
{
// Set the labels text with trackbar value
labelValue.Text = value.ToString();
}

// This Method is called when the mouse is moved around the child window
private void OnMouse(int evnt, int x, int y, int flags, IntPtr param)
{
labelValue.Text =
"Event: " + evnt.ToString() +

"\nx=" + x.ToString() +
"\ny=" + y.ToString() +
"\nFlags: " + flags.ToString();
}

The "x,y" variables, for example, will be updated every time the mouse has been moved.
Extend your File Dialog Method now with the following lines:

// Position of the trackbar
int value = 0;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
...
// Create external window
cvlib.CvNamedWindow("MyWindow", cvlib.CV_WINDOW_AUTOSIZE);
// Create the trackbar
cvlib.CvCreateTrackbar
	("TrackbarName", "MyWindow", ref value, 100, onChange); //  -- add
// Set the mouse callback eventhandler
cvlib.CvSetMouseCallback("MyWindow", onMouse, IntPtr.Zero);    // < -- add
...
}

The identifier for the callback routines are passed as parameters without the ref keyword. TrackbarName is the leading string of the ruler and specifies its function. Because OpenCV identifies the relationships between windows by strings, the window name "MyWindow" is an additional parameter. Within the example code, I put the processing stuff in a separate method called Process() and moved the creation of the external window in the forms constructor.

VI. Overloading Instead of Default Arguments

One of the features of the openVC lib is the possibility of overloading and default arguments. This leads to a problem in C# because default arguments are not supported and due to the possible numbers of combinations of structure types and default values. So I decided to only support a few combinations and added partial overloading for default values. Maybe I will build a better support for the ubiquitous CvArr type if I will get a good idea to do this.

The following example shows how to allocate data for the CvMat component.

VII. Error Handling

The OpenCV Library offers two major, different methods to get information if an error occurs. The first way is to ask for the Error status, or you get informed about errors within a callback. Furthermore, there is a way to distinguish whether you want to continue program execution or suspend the application.

It is important to know, that, when the program is internally terminated some unwanted behaviour can occur and of course this can also happen if you continue because some values are undefined. OpenCV does not support exceptions. So if you put a try-catch block and a error happens in a function call, a message box pops up by default and depending on which button you choose (cancel, try again, ignore) the application exits or crashes in most cases and the try-catch block is ignored.

The first decision you have to make is regarding the error mode. You have three options (some text copied from the OpenCV-documentation):

  • Leaf
    The program is terminated after error handler is called. This is the default value. It is useful for debugging, as the error is signalled immediately after it occurs. However, for production systems other two methods may be preferable as they provide more control.
    You can define your own error handler or use the predefined handler (see below)
  • Parent
    The program is not terminated, but the error handler is called. The stack is unwinded (it is done w/o using C++ exception mechanism). User may check error code after calling CxCore function with cvlib.CvGetErrStatus() and react.
  • Silent
    Similar to Parent mode, but no error handler is called.

If you use Silent mode, you may check after calling a function with cvlib.CvGetErrStatus() and react. For defining you own error handler (this is suggested) you have to redirect the error by using the cvlib.RedirectError(...) method where you pass your own error handler as an argument. The usage is similar to a mouse or trackbar callback (with a delegate).

The following code snippet illustrates the variants (using the example from above).

public partial class Form1 : Form
{
// define the error delegate member
cvlib.OnErrorCallback onError;
// Constructor
public Form1()
{
InitializeComponent();
// create a instance and pass your error handler method name
onError = new cvlib.OnErrorCallbackDelegate(OnError);
// advise the CvLib to work in Parent mode (call error handler but don't exit)
cvlib.CvSetErrMode(cvlib.CV_ErrModeParent);
// redirect the error to use your error handler against the predefined handler
// (Message Box)
cvlib.CvRedirectError(onError);
}
private void buttonFile_Click(object sender, EventArgs e)
{
...
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
...
// apply the operator
cvlib.CvCanny(ref gray, ref gray, 100, 100, 3);
// check for error (variant 1)
if (cvlib.CvGetErrStatus() != 0)
{
// do some clean up
cvlib.CvReleaseImage(ref img);
// !! important set error status back
cvlib.CvSetErrStatus(0);
// return for example or throw exception
return;
}
}
...
}
// your error handler
private int OnError(int status, string func_name,
string err_msg, string file_name, int line)
{
MessageBox.Show(
"Status: " + cvlib.CvErrorStr(status) +
"\nIn Function: " + func_name +
"\nMessage: " + err_msg +
"\nIn File: " + file_name +
"\nOn Line: " + line.ToString(), "CV-Error", 
	MessageBoxButtons.OK, MessageBoxIcon.Error);
// a return value   0 means application is suspended, avoid this!!
return 0;
}

VIII. Marshalling - P/Invoke

1. Internal Wrapper Function Calls

Most of wrapper internal DLL-calls follow simple rules. If the called function returns a structure pointer, it is converted to the desired structure definition by using the Marshal.PointerToStructure conversion. The returned pointer is saved as an additional parameter in the structure definitions and used for releasing the allocated memory when the corresponding release call is processed (like cvlib.CvReleaseImage(...)). All primitive data types including one dimensional arrays are passed directly or by reference. Strings are converted by using the desired convention (LPStr). Structures (like the IPL image structure) passed by reference to avoid read / write access violations. Void* pointers are passed by IntPtr. To converts these arguments, use the functions available in the cvtool class. To access the unmanaged functions, the DllImportAttribute class has been used. Because this class can handle only static library functions, classes like the ml class are still not supported at moment. The next lines shows a short extract from the highgui.cs for illustration:

/// <summary>
/// The function cvShowImage shows the image
/// in the specified window. If the window was created
/// with CV_WINDOW_AUTOSIZE flag then the image is shown
/// with its original size, otherwise the image is scaled
/// to fit the window.
/// </summary>
/// <param name="name">The name of the window.</param>
/// <param name="image">The image to be shown.</param>
public static void CvShowImage( string name, ref IplImage image)
{
  cvShowImage(name, ref image);
}
[DllImport(HIGHGUI_LIBRARY)]

private static extern void cvShowImage([MarshalAs(UnmanagedType.LPStr)] 
					String name, ref IplImage image);

2. Table with Conversions that has been used

The table shows the used analogies for declaration of OpneCV API types in C#. It is regarded only to the arguments in method calls for the OpenCV library and has not been tested for common Windows API calls. What is explained is HOW the arguments are passed and gives hints when the cvtool-class can be used for adapting.

API-Type Passed in C# as (input and/or output argument) Explanation/Hints
int, uint, uint64, float, double int, uint, UInt64, float, double uint64 = cvRNG is the seed for the Random Number Generator
int* ref int, int[] ref for reading/writing single value, int[] for reading/writing one dimensional arrays
float* ref float, float[] ref for reading/writing single value, float[] for reading/writing one dimensional arrays
Struct struct For structs that contains only primitive datatypes for reading like CvPoint
Struct* ref struct, IntPtr For structs that contains pointers like IplImage (ref) and arrays of structs (cvtools should be used for conversion).
Struct** ref IntPtr Most in case that data will be deallocated.
char* [MarshalAs(UnmanagedType.LPStr)] String CharSet = CharSet.Ansi. In cases that the function reads a string.
char* ref StringBuilder CharSet = CharSet.Ansi. In cases that the function allocates a string and returns it.
void* IntPtr Use cvtools.Convert1DArrayToPtr() or the desired function
void** ref IntPtr Use cvtools.Convert2DArrayToPtr(). or pass structure by using the ref keyword

There are additional return value conversions. Mostly the Marshal.PointerToStructure conversion has been used or the return values are passed unchanged to the caller. Microsoft describes the analogies in the .NET Framework documentation under the Keywords "Programing with .NET Framework", "Communication with unmanaged code", "Interop-Marshalling", Marshalling data with Platform invoke" and "Datatypes for Platform invoke".

3. The cvtool Class

By using the methods of the cvtool class, it is very simple to handle the c-pointer types. For most of the methods, the changes in values within the unmanaged memory will be visible in the managed environment. The follow listing shows the available conversion routines.

  • Convert2DArrToPtr(byte[][] arr, out GCHandle[] handles)
  • Convert2DArrToPtr(int[][] arr, out GCHandle[] handles)
  • Convert2DArrToPtr(float[][] arr, out GCHandle[] handles)
  • Convert2DArrToPtr(double[][] arr, out GCHandle[] handles)
  • Convert1DArrToPtr(byte[] arr, out GCHandle handle)
  • Convert1DArrToPtr(int[] arr, out GCHandle handle)
  • Convert1DArrToPtr(float[] arr, out GCHandle handle)
  • Convert1DArrToPtr(double[] arr, out GCHandle handle)
  • Convert1DArrToPtr(CvPoint2D32f[] arr, out GCHandle handle)
  • ConvertStructureToPtr(object structure, out GCHandle handle)
  • ConvertPtrToStructure(IntPtr p, Type typeOfStructure)
  • ConvertPtrToArray(IntPtr data, byte[] arr)
  • ConvertPtrToArray(IntPtr data, float[] arr)
  • ConvertPtrToArray(IntPtr data, double[] arr)
  • ConvertPtrToArray(IntPtr data, int[] arr)
  • ReleaseHandels(GCHandle[] h)
  • ReleaseHandel(GCHandle h)

IX. Low Level Access for Pixels and Sequences

Low level operations are illustrated in the next sample. It will be shown how to access and manipulate either Image/Matrix data by using macros or by directly accessing the raw data by either using safe or unsafe code. For unsafe operations it is necessary to turn on this option in Visual Studio. You can do this by clicking the check on the "allow unsafe code" checkbox in the build tab of your project options. For accessing raw data, the OpenCV Library offers some macros. This are:

  • CvPtr*D
  • CvSet*D
  • CvGet*D
  • CvGetReal*D
  • CvSetReal*D

Here are the first examples of how to read/write data by using one of the macros:

// Create a matrix
CvMat m = cvlib.CvCreateMat(3, 3, cvlib.CV_64FC1);
// set data
cvlib.CvSetReal2D(ref m, 0, 0, 12.4);
cvlib.CvSetReal2D(ref m, 0, 1, 2.4);
...
// read data at index  0, 0
double res = cvlib.CvGetReal2D(ref m, 0, 0);

The second example shows how to allocate data for the CvMat Component. Notice that members of the cvtools class output a Handle to connected memory. Release the handle not earlier than you don't need the memory anymore. After releasing the handle, the memory is available for the garbage collector.

// a array with doubles
double[] a = { 1.1, 2.2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };

// create a matrix with 3 rows and 4 columns
CvMat ma = cvlib.CvCreateMat(3, 4, cvlib.CV_64FC1);

// as long as the handle (h) is not disposed,
// the garbage collector will not touch the double array
GCHandle h;

// fill our matrix with data
cvlib.CvInitMatHeader(ref ma, 3, 4, cvlib.CV_64FC1, 
	cvtools.Convert1DArrToPtr(a, out h), cvlib.CV_AUTO_STEP);

//...
// do anything with the matrix
//...

// dispose
cvtools.ReleaseHandel(h);

Now we want to iterate through a sequence. The next sample source shows how to achieve this goal.

// Create a Sequence , say that will be a set of contours
CvSeq contours = new CvSeq();

// Get a pointer to the sequence
GCHandle h;
IntPtr p = cvtools.ConvertStructureToPtr(contours, out h);

// Do anything with that pointer for example find contours
cvlib.CvFindContours(ref gray, ref storage, ref p, 
	Marshal.SizeOf(typeof(CvContour)),
cvlib.CV_RETR_LIST, cvlib.CV_CHAIN_APPROX_SIMPLE, new CvPoint(0, 0));

// iterate
while (p != IntPtr.Zero)
{
  // Do anything with the partial contour for example approximate polygonal  
  CvSeq result = cvlib.CvApproxPoly
		(p, Marshal.SizeOf(typeof(CvContour)), ref storage,
    cvlib.CV_POLY_APPROX_DP, 10, 0);

  // Get the next contour element
  contours = (CvSeq)cvtools.ConvertPtrToStructure(p, typeof(CvSeq));
  p = contours.h_next;
}

cvtools.ReleaseHandel(h);

Finally we will show how to colorize an image area by using unsafe access. Suppose we have a colour image (IplImage image) and want to fill a rectangular area with top left at P(10, 10) and width and height = (100, 100). The image data base address is given by the imageData IntPtr class. We will get the actual address for writing data by offsetting this base address. This is similar to: image[y * imageWidthStep + x]. imageWidthStep may be shorter than actual image width because of boxing or an ROI.

unsafe
{
...
// get base address
int baseAddress = image.imageData.ToInt32();
// iterate
for (int x = 10; x   100; x++)
{
for (int y = 10; y   100; y++)
{
byte* dst =  (((byte*)(baseAddress + image.widthStep * y))[x * 3]);
dst[0] = 0; dst[1] = 0; dst[2] = 255;
}
}
...
}

At least a similar example like the above but without unsafe access and reading a float. Notice the "4 * x" that means the float datatype is internally represented by 4 bytes of data.

...
// get base address
int baseAddress = image.imageData.ToInt32();

// iterate
for (int x = 10; x   100; x++)
{
  for (int y = 10; y   100; y++)
  {
    float result = (float)Marshal.PtrToStructure(new IntPtr(baseAddress +
			baseAddress .widthStep * y + 4 * x), typeof(float));

  }
}
...

X Actual State of Implementation and Known Problems

  • cxcore is most complete
  • cv is most complete
  • highgui is most complete
  • Machine learning and cvaux is open

There is a problem deallocation CvMemStorage reported by Carsten C:

for (int i = 0; i   100000; i++)
{
  CvMemStorage storage = cvlib.CvCreateMemStorage(0);
  CvSeq sequence = cvlib.CvCreateSeq(0, Marshal.SizeOf(typeof (CvSeq)), 
			Marshal.SizeOf(typeof (CvPoint)), ref storage);
  // Do some funny things with the sequence
  cvlib.CvReleaseMemStorage(ref storage); //  == does actually not release sequence
}

Here is the solution (Thanks Carsten):

CvMemStorage parentStorage = cvlib.CvCreateMemStorage(0);
for (int i = 0; i   100000; i++)
{
    CvMemStorage storage = cvlib.CvCreateChildMemStorage(ref parentStorage);
    CvSeq sequence = cvlib.CvCreateSeq(0, Marshal.SizeOf(typeof(CvSeq)), 
			Marshal.SizeOf(typeof(CvPoint)), ref storage);
    // Do some funny things with the sequence
    cvlib.CvClearMemStorage(ref storage);    //  == needed
    cvlib.CvReleaseMemStorage(ref storage);  //  == seems not to be needed
}
cvlib.CvReleaseMemStorage(ref parentStorage);

XI. Examples

1. The "BigSample" Application

cvlib.jpg

Features

  • Load and save images of different image formats supported by the OpenCV Library.
  • Choose from a set of image processing operators which are directly adapted from the samples distributed with latest OpenCV package.
  • Display live video from webcam or file by using HighGUI functions. Simple real time processing of your own code.
  • See how to implement a non modl dynamic configurable dialog

Included Image Processing Samples

  • Canny Edge detector
  • Dilate filter
  • Erosion filter
  • Harris corner detector
  • Sobel filter
  • Laplace filter
  • Watershed Transformation
  • Pyramid Segmentation
  • Calibration (Teach)
  • Calibration (Correct)
  • HAAR Classifier (Faces)
  • Contour finder
  • Hough Lines
  • Hough Circles
  • Convert2Gray
  • Line Approximation
  • Ellipse Approximation
  • Several Histograms
  • Equalize Histogram
  • Hue-Sat Histogram
  • Good Features to Track
  • Singular Value Transformation
  • Matrix Multiplication
  • Perspective Transform
  • Random number Generator demo
  • All Moments and Hu Moments
  • Flood Fill
  • Template Matching

How It Works

The presented application is intended for reference or to be a good starting place to build your own Application. Inside the mainForm.cs file, all properties and methods are arranged by regions. Within Visual Studio IDE, you should first collapse all definitions to get a good overview. Most importantly, definitions are:

  • Process Run
  • Process Menu
  • Video Start / Stop / Timer

Under "Process Run" you will find the eventhandler that is executed when the "Run" button was pushed. The if-constructs check for the actual selected entry in the 'operations' combo-box and branches to the corresponding image processing method.

The 'operations' combo-box SelectedIndexChanged-Method has been placed within the "Process Menu" region. Every time the index is changed, this method creates a dynamic dialogbox with corresponding controls adequate to the selected image processing task.

For every image processing operation, I wrote a separated class placed in different files. So it is simple to find the corresponding code for reuse. Each of the functions takes only one parameter, the actual, loaded image in IPL format. Depending on the selected mode, the resulting image of an operation will be displayed in a new tab or the actual tab page.

XII History

  • v 1.0.0, August, 2008: Library first published
  • v 1.0.3, February, 2009: Library updated, additional samples, CodeProject article updated

XIII Contact and Frequently Updated

XIV In Own Matter

If you need help or advice or assistance in a project on any area of image processing, don't hesitate to contact me... (please use email above).

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here