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
- Introduction - Intel's openCV libs and the wrapper
- Features of the wrapper
- Environment and IDE
- Installation
- Common using of wrapper DLLs
- Sample binaries
- Sample sources / Visual Studio Projects
- Recompile the wrapper library
- Let's start - A short tutorial
- Overloading instead of default arguments
- Error Handling
- Marshalling - P/Invoke
- Internal wrapper function calls
- Table with conversions which has been used
- The cvtools - class
- Low level access for pixels and sequences
- Actual state of implementation and known problems
- Examples
- The "BigSample" application
- Optical flow sample
- Squares sample
- History
- Contact and frequently Updated
- In own matter :-)
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.
- 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.
- Visual Studio 2005 Standard Edition
- Version 8.050727.762 (SP.050727-7600)
- Microsoft .NET Framework 1.1. / 2.0 / 3.0
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.
- Download "cvlib_bin.zip" from the above links and
openCV
libs (DLLs) for example from here.
- Extract both zips in a folder of your choice.
- 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.
- 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)
- 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.
- Copy the RELEASE versions of the wrapper DLL and all RELEASE
openCV
DLLs to the sample folders that contain the EXE file.
- 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.
- 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.
- Go to the project folders of Visual Studio and create bin\Debug, and bin\Release directories.
- 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.
- 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".
- 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.
- 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.
- Download "cvlib_src.zip" from the above links and extract to a directory of your choice.
- Double click "openCV.csproj" file to open Visual Studio project.
- Change what you want in the code.
- Compile the library in debug or release mode.
- Don't forget to report your extensions or fixes to the community :-)
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)
{
img = cvlib.CvLoadImage(openFileDialog.FileName, cvlib.CV_LOAD_IMAGE_COLOR);
cvlib.CvNamedWindow("MyWindow", cvlib.CV_WINDOW_AUTOSIZE);
cvlib.CvShowImage( "MyWindow", ref img );
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)
{
img = cvlib.CvLoadImage(openFileDialog.FileName, cvlib.CV_LOAD_IMAGE_COLOR);
gray = cvlib.CvCreateImage(new CvSize(img.width, img.height),
(int)cvlib.IPL_DEPTH_8U, 1);
cvlib.CvCvtColor(ref img, ref gray, cvlib.CV_BGR2GRAY);
cvlib.CvCanny(ref gray, ref gray, 100, 100, 3);
cvlib.CvNamedWindow("MyWindow", cvlib.CV_WINDOW_AUTOSIZE);
cvlib.CvShowImage( "MyWindow", ref gray );
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.
private void OnChange(int value)
{
labelValue.Text = value.ToString();
}
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:
int value = 0;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
...
cvlib.CvNamedWindow("MyWindow", cvlib.CV_WINDOW_AUTOSIZE);
cvlib.CvCreateTrackbar
("TrackbarName", "MyWindow", ref value, 100, onChange);
cvlib.CvSetMouseCallback("MyWindow", onMouse, IntPtr.Zero);
...
}
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 string
s, 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.
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.
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
{
cvlib.OnErrorCallback onError;
public Form1()
{
InitializeComponent();
onError = new cvlib.OnErrorCallbackDelegate(OnError);
cvlib.CvSetErrMode(cvlib.CV_ErrModeParent);
cvlib.CvRedirectError(onError);
}
private void buttonFile_Click(object sender, EventArgs e)
{
...
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
...
cvlib.CvCanny(ref gray, ref gray, 100, 100, 3);
if (cvlib.CvGetErrStatus() != 0)
{
cvlib.CvReleaseImage(ref img);
cvlib.CvSetErrStatus(0);
return;
}
}
...
}
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);
return 0;
}
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. String
s 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:
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);
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 struct s that contains only primitive datatypes for reading like CvPoint |
Struct* |
ref struct , IntPtr |
For struct s that contains pointers like IplImage (ref) and arrays of struct s (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".
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)
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:
CvMat m = cvlib.CvCreateMat(3, 3, cvlib.CV_64FC1);
cvlib.CvSetReal2D(ref m, 0, 0, 12.4);
cvlib.CvSetReal2D(ref m, 0, 1, 2.4);
...
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.
double[] a = { 1.1, 2.2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
CvMat ma = cvlib.CvCreateMat(3, 4, cvlib.CV_64FC1);
GCHandle h;
cvlib.CvInitMatHeader(ref ma, 3, 4, cvlib.CV_64FC1,
cvtools.Convert1DArrToPtr(a, out h), cvlib.CV_AUTO_STEP);
cvtools.ReleaseHandel(h);
Now we want to iterate through a sequence. The next sample source shows how to achieve this goal.
CvSeq contours = new CvSeq();
GCHandle h;
IntPtr p = cvtools.ConvertStructureToPtr(contours, out h);
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));
while (p != IntPtr.Zero)
{
CvSeq result = cvlib.CvApproxPoly
(p, Marshal.SizeOf(typeof(CvContour)), ref storage,
cvlib.CV_POLY_APPROX_DP, 10, 0);
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
{
...
int baseAddress = image.imageData.ToInt32();
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.
...
int baseAddress = image.imageData.ToInt32();
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));
}
}
...
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);
cvlib.CvReleaseMemStorage(ref storage);
}
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);
cvlib.CvClearMemStorage(ref storage);
cvlib.CvReleaseMemStorage(ref storage);
}
cvlib.CvReleaseMemStorage(ref parentStorage);
- 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
- 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
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.
- v 1.0.0, August, 2008: Library first published
- v 1.0.3, February, 2009: Library updated, additional samples, CodeProject article updated
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).