my reference manual emucv.pdf

23
1 Suriya Phiokham 2013 06, 20 Reference : hp://www.emgu.com/wiki/index.php/ Working with Images Depth and Color as Generic Parameter An Image is defined by its generic parameters: color and depth. To create a 8bit unsigned Grayscale image, in Emgu CV it is done by calling Image<Gray, Byte> image = new Image<Gray, Byte>( width, height); Not only this syntax make you aware the color and the depth of the image, it also restrict the way you use functions and capture errors in compile time. For example, the SetValue(TColor color, Image<Gray, Byte> mask) function in Image<TColor, TDepth> class (version >= 1.2.2.0) will only accept colors of the same type, and mask has to be an 8-bit unsigned grayscale image. Any attempts to use a 16-bit floating point or non-grayscale image as a mask will results a compile time error! Creating Image Although it is possible to create image by calling CvInvoke.cvCreateImage, it is suggested to construct a Image<TColor, TDepth> object instead. There are several advantages using the managed Image<TColor, TDepth> class Memory is automatically released by the garbage collector Image<TColor, TDepth> class can be examined by Debugger Visualizer Image<TColor, TDepth> class contains advanced method that is not available on OpenCV, for example, generic operation on image pixels, conversion to Bitmap etc. Image Color The first generic parameter of the Image class specific the color of the image type. For example Image<Gray, ...> img1; indicates that img1 is a single channel grayscale image. Color Types supported in Emgu CV 1.3.0.0 includes: Gray Bgr (Blue Green Red) Bgra (Blue Green Red Alpha) Hsv (Hue Saturation Value) Hls (Hue Lightness Saturation) Lab (CIE L*a*b*) Luv (CIE L*u*v*) Xyz (CIE XYZ.Rec 709 with D65 white point) Ycc (YCrCb JPEG) Image Depth Image Depth is specified using the second generic parameter Depth. The types of depth supported in Emgu CV 1.4.0.0 include Byte SByte

Upload: phiokham-suriya

Post on 01-Dec-2015

987 views

Category:

Documents


19 download

DESCRIPTION

Example how to using Emgu Cv Library for Image processing (Fundamental)

TRANSCRIPT

Page 1: My Reference Manual EmuCv.pdf

1

Suriya Phiokham 2013 06, 20 Reference : http://www.emgu.com/wiki/index.php/

Working with Images

Depth and Color as Generic Parameter

An Image is defined by its generic parameters: color and depth. To create a 8bit unsigned Grayscale image, in Emgu CV it is done by calling

Image<Gray, Byte> image = new Image<Gray, Byte>( width, height);

Not only this syntax make you aware the color and the depth of the image, it also restrict the way you use functions

and capture errors in compile time. For example, the SetValue(TColor color, Image<Gray, Byte>

mask) function in Image<TColor, TDepth> class (version >= 1.2.2.0) will only accept colors of the same type, and

mask has to be an 8-bit unsigned grayscale image. Any attempts to use a 16-bit floating point or non-grayscale image as a mask will results a compile time error!

Creating Image

Although it is possible to create image by calling CvInvoke.cvCreateImage, it is suggested to construct a

Image<TColor, TDepth> object instead. There are several advantages using the managed Image<TColor, TDepth> class

Memory is automatically released by the garbage collector

Image<TColor, TDepth> class can be examined by Debugger Visualizer

Image<TColor, TDepth> class contains advanced method that is not available on OpenCV, for example, generic operation on image pixels, conversion to Bitmap etc.

Image Color

The first generic parameter of the Image class specific the color of the image type. For example

Image<Gray, ...> img1;

indicates that img1 is a single channel grayscale image.

Color Types supported in Emgu CV 1.3.0.0 includes:

Gray

Bgr (Blue Green Red)

Bgra (Blue Green Red Alpha)

Hsv (Hue Saturation Value)

Hls (Hue Lightness Saturation)

Lab (CIE L*a*b*)

Luv (CIE L*u*v*)

Xyz (CIE XYZ.Rec 709 with D65 white point)

Ycc (YCrCb JPEG)

Image Depth

Image Depth is specified using the second generic parameter Depth. The types of depth supported in Emgu CV

1.4.0.0 include

Byte

SByte

Page 2: My Reference Manual EmuCv.pdf

2 Single (float)

Double

UInt16

Int16

Int32 (int)

Creating a new image

To create an 480x320 image of Bgr color and 8-bit unsigned depth. The code in C# would be

Image<Bgr, Byte> img1 = new Image<Bgr, Byte>(480, 320);

If you wants to specify the background value of the image, let's say in Blue. The code in C# would be

Image<Bgr, Byte> img1 = new Image<Bgr, Byte>(480, 320, new Bgr(255, 0, 0));

Reading image from file

Creating image from file is also simple. If the image file is "MyImage.jpg", in C# it is

Image<Bgr, Byte> img1 = new Image<Bgr, Byte>("MyImage.jpg");

Creating image from Bitmap

It is also possible to create an Image<TColor, TDepth> from a .Net Bitmap object. The code in C# would be

Image<Bgr, Byte> img = new Image<Bgr, Byte>(bmp); //where bmp is a Bitmap

Automatic Garbage Collection

The Image<TColor, TDepth> class automatically take care of the memory management and garbage collection.

Once the garbage collector decided that there is no more reference to the Image<TColor, TDepth> object, it will

call the Disposed method, which release the unmanaged IplImage structure.

The time of when garbage collector decides to dispose the image is not guaranteed. When working with large

image, it is recommend to call the Dispose() method to explicitly release the object. Alternatively, use

the using keyword in C# to limit the scope of the image

using (Image<Gray, Single> image = new Image<Gray, Single>(1000, 800))

{

... //do something here in the image

} //The image will be disposed here and memory freed

Getting or Setting Pixels

The safe (slow) way

Suppose you are working on an Image<Bgr, Byte>. You can obtain the pixel on the y-th row and x-th column by calling

Bgr color = img[y, x];

Setting the pixel on the y-th row and x-th column is also simple

img[y,x] = color;

The fast way

The Image pixels values are stored in the Data property, a 3D array. Use this property if you need to iterate through the pixel values of the image.

For example, in an grayscale image (Image<Gray, Byte>), instead of doing this:

Gray byCurrent = imageGray[x, y];

Page 3: My Reference Manual EmuCv.pdf

3 You would do this:

Byte byCurrent = imageGray.Data[x, y, 0];

Methods

Naming Convention

Method XYZ in Image<TColor, TDepth> class corresponds to the OpenCV function cvXYZ. For example,

Image<TColor, TDepth>.Not() function corresponds to cvNot function with the resulting image being

returned.

Method _XYZ is usually the same as Method XYZ except that the operation is performed inplace rather than

returning a value. For example, Image<TColor, TDepth>._Not() function performs the bit-wise inversion inplace.

Operators Overload

The operators + - * / has been overloaded (version > 1.2.2.0) such that it is perfectly legal to write codes like:

Image<Gray, Byte> image3 = (image1 + image2 - 2.0) * 0.5;

Generic Operation

One of the advantage of using Emgu CV is the ability to perform generic operations.

It's best if I demonstrate this with an example. Suppose we have an grayscale image of bytes

Image<Gray, Byte> img1 = new Image<Gray, Byte>(400, 300, new Gray(30));

To invert all the pixels in this image we can call the Not function

Image<Gray, Byte> img2 = img1.Not();

As an alternative, we can also use the generic method Convert available from the Image<TColor, TDepth> class

Image<Gray, Byte> img3 = img1.Convert<Byte>( delegate(Byte b) { return (Byte) (255-

b); } );

The resulting image img2 and img3 contains the same value for each pixel.

At first glance it wouldn't seems to be a big gain when using generic operations. In fact, since OpenCV already has

an implementation of the Not function and performance-wise it is better than the generic version of the

equivalent Convert function call. However, there comes to cases when generic functions provide the flexibility

with only minor performance penalty.

Let's say you have an Image<Gray, Byte> img1 with pixels set. You wants to create a single channel floating

point image of the same size, where each pixel of the new image, correspond to the old image, described with the following delegate

delegate(Byte b) { return (Single) Math.cos( b * b / 255.0); }

This operation can be completed as follows in Emgu CV

Image<Gray, Single> img4 = img1.Convert<Single>( delegate(Byte b) { return (Single)

Math.cos( b * b / 255.0); } );

The syntax is simple and meaningful. On the other hand, this operation in OpenCV is hard to perform since

equivalent function such as Math.cos is not available.

Drawing Objects on Image

The Draw( ) method in Image< Color, Depth> can be used to draw different types of objects, including fonts,

lines, circles, rectangles, boxes, ellipses as well as contours. Use the documentation and intellisense as a

guideline to discover the many functionality of the Draw function.

Color and Depth Conversion

Page 4: My Reference Manual EmuCv.pdf

4 Converting an Image<TColor, TDepth> between different colors and depths are simple. For example, if you

have Image<Bgr, Byte> img1 and you wants to convert it to a grayscale image of Single, all you need to do is

Image<Gray, Single> img2 = img1.Convert<Gray, Single>();

Displaying Image

Using ImageBox

Emgu CV recommends the use of ImageBox control for display purpose, for the following reasons

ImageBox is a high performance control for displaying image. Whenever possible, it displays a Bitmap that shares memory with the Image object, therefore no memory copy is needed (very fast).

The user will be able to examine the image pixel values, video frame rates, color types when the image is being displayed.

It is convenient to perform simple image operations with just a few mouse clicks.

Converting to Bitmap

The Image class has a ToBitmap() function that return a Bitmap object, which can easily be displayed on a

PictureBox control using Windows Form.

XML Serialization

Why do I care?

One of the future of Emgu CV is that Image<TColor, TDepth> can be XML serializated. You might ask why we need to serialization an Image. The answer is simple, we wants to use it in a web service!

Since the Image<TColor, TDepth> class implements ISerializable, when you work in WCF (Windows Communication Fundation), you are free to use Image<TColor, TDepth> type as parameters or return value of a web service.

This will be ideal, for example, if you are building a cluster of computers to recognize different groups of object and have a central computer to coordinate the tasks. I will also be useful if your wants to implement remote monitoring

software that constantly query image from a remote server, which use the Capture class in Emgu CV to capture

images from camera.

Conversion to XML

You can use the following code to convert an Image<Bgr, Byte> image to XmlDocument:

StringBuilder sb = new StringBuilder();

(new XmlSerializer(typeof(Image<Bgr, Byte>))).Serialize(new StringWriter(sb), o);

XmlDocument xDoc = new XmlDocument();

xDoc.LoadXml(sb.ToString());

Conversion from XML

You can use the following code to convert a XmlDocument xDoc to Image<Bgr,Byte>

Image<Bgr, Byte> image = (Image<Bgr, Byte>)

(new XmlSerializer(typeof(Image<Bgr, Byte>))).Deserialize(new XmlNodeReader(xDoc));

Working with Matrices Depth as Generic Parameter

A Matrix is defined by its generic parameters depth. To create a 32bit floating point matrix, in Emgu CV it is done by calling

Page 5: My Reference Manual EmuCv.pdf

5 Matrix<Single> matrix = new Matrix<Single>(width, height);

Matrix Depth

The types of depth supported in Emgu CV 1.4.0.0 include

Byte

SByte

Single (float)

Double

UInt16

Int16

Int32 (int)

XML Serialization

Conversion to XML

You can use the following code to convert an Matrix<double> matrix to XmlDocument:

StringBuilder sb = new StringBuilder();

(new XmlSerializer(typeof(Matrix<double>))).Serialize(new StringWriter(sb), o);

XmlDocument xDoc = new XmlDocument();

xDoc.LoadXml(sb.ToString());

Conversion from XML

You can use the following code to convert a XmlDocument xDoc to Matrix<double>

Matrix<double> matrix = (Matrix<double>)

(new XmlSerializer(typeof(Matrix<double>))).Deserialize(new XmlNodeReader(xDoc));

C# Image Processing Examples

Hello World - Version 1 We will start by the Hello World sample, written in C# using Emgu.CV;

using Emgu.CV.CvEnum;

using Emgu.CV.Structure;

using System.Drawing;

...

//The name of the window

String win1 = "Test Window";

//Create the window using the specific name

CvInvoke.cvNamedWindow(win1);

//Create an image of 400x200 of Blue color

using (Image<Bgr, Byte> img = new Image<Bgr, byte>(400, 200, new Bgr(255, 0, 0)))

{

//Create the font

MCvFont f = new MCvFont(CvEnum.FONT.CV_FONT_HERSHEY_COMPLEX, 1.0, 1.0);

//Draw "Hello, world." on the image using the specific font

img.Draw("Hello, world", ref f, new Point(10, 80), new Bgr(0, 255, 0));

Page 6: My Reference Manual EmuCv.pdf

6

//Show the image

CvInvoke.cvShowImage(win1, img.Ptr);

//Wait for the key pressing event

CvInvoke.cvWaitKey(0);

//Destory the window

CvInvoke.cvDestroyWindow(win1);

}

The above code will create an image of 400x200 with blue background color and the text "Hello, world" in green on the foreground. The image will be displayed a window named "Test Window".

Hello World - Version 2 Showing image using cvNamedWindow is good, but Emgu CV has an event better tool for the same purpose, that is, the ImageViewer class under Emgu.CV.UI namespace. using Emgu.CV;

using Emgu.CV.CvEnum;

using Emgu.CV.Structure;

using Emgu.CV.UI;

using System.Drawing;

...

//Create an image of 400x200 of Blue color

using (Image<Bgr, Byte> img = new Image<Bgr, byte>(400, 200, new Bgr(255, 0, 0)))

{

//Create the font

MCvFont f = new MCvFont(CvEnum.FONT.CV_FONT_HERSHEY_COMPLEX, 1.0, 1.0);

//Draw "Hello, world." on the image using the specific font

img.Draw("Hello, world", ref f, new Point(10, 80), new Bgr(0, 255, 0));

//Show the image using ImageViewer from Emgu.CV.UI

ImageViewer.Show(img, "Test Window");

}

Page 7: My Reference Manual EmuCv.pdf

7

Introduction The following article is designed to show new comers to EMGUcv how to set up a project step by step. This article is designed to make the process a little more user friendly. EMGU is a c# wrapper for OpenCV it differs from other wrappers as it written purely in c# and does not use unsafe code. EMGU opens the OpenCV (Open Source Computer Vision Library) library of programming functions mainly aimed at real time computer vision to C# developers. OpenCV was originally developed by Intel and now supported by Willow Garage. Current versions for both x86 and x64 architectures are available to download at their Sourceforge website. As EMGU is a wrapper for c++ code there are two types of Dynamic-link library’s (DLL’s) that are used. There are the EMGU ones with EMGU syntax always reference in the name and the opencv ones that vary. Setting up a first project is a common stumbling block for many newcomers and you are not alone. If you have downloaded the source code you will need to read “A Basic Program”. If you have copied an example from the EMGU extraction folder then take a look at The EMGU.CV.Invoke Exception and Troubleshooting section.

Assumed Knowledge It is assumed that a user has basic experience in c# and can generate a new c# project. It is assumed that each user has download the most recent update for their platform and has the HelloWorld Example running from the EMGU extraction folder\EMGU.Examples\Hello World.

The Basic Requirements As with any c# library there are some essential DLL’s that need referencing within your project. Start a new c# Windows Form Application and call it what you like. All DLL mentioned are in the EMGU extraction Folder\bin you will need to remember this. To start with you need to reference 3 EMGU DLL’s. Emgu.CV.dll Emgu.CV.UI.dll Emgu.Util.dll This is done by either right clicking on your project name or the References folder within the solution explorer. Go to Add Reference.

Or alternatively using the menu item Project > Add Reference. When the Add Reference window opens select the DLL’s listed above and click OK.

Page 8: My Reference Manual EmuCv.pdf

8

You will now see them listed in the References folder in the solution explorer window. These three DLL’s are the EMGU specific c# libraries mentioned previously. These alone will not allow you to use any of the image processing functions so please read the rest of the article. Now you need to reference these in any class of form that you will be using the code. The references you will use will depend on what you are doing in image processing terms. Look at the examples and these will have the ones your require. To get you started add the following to the top of the Form1.cs code behind.

using Emgu.CV;

using Emgu.Util;

using Emgu.CV.Structure;

The Preferred Method Now for the more complicated c++ libraries, to load, display, access image data and do many of the more simpler functions you only need two files. Note that the "220" is the version number this will change according to updates (opencv_core***.dll, opencv_imgproc***.dll). opencv_core220.dll opencv_imgproc220.dll Now because these are wrapped c++ files you can’t reference them like you did with the EMGU files. You need to add these files to your project. This can be done in two ways, Right click on your project name within solution explorer (This is not the one starting with “Solution ‘Your Project Name’ ...” but the one bellow this). Go to Add > Existing Item using the standard open file dialog. Select the two files above, in case you forgot they are located in the EMGU extraction Folder\bin. Hint: if you can’t see .dll's make sure you change the file filter at the bottom right to Executable Files.

You will now be able to see your files within the solution explorer window. You will need to change there properties so select them both by holding down the Ctl key and left clicking on them (alternatively you can do this individually). Now look at Properties window, you will see 6 fields two of these will be filled with content. You are interested in the Copy to Output Directory. Change this from “Do not Copy” to “Copy always”.

Page 9: My Reference Manual EmuCv.pdf

9

If you are using the x64 compilations go to the x64 section and ensure you set up you project to compile to a x64 architecture other than that you are ready to start image processing. The reason this is the preferred method is that now, if you change from Debug to Release these files will always be available to your program and no errors will occur. Jump to the reading and displaying an image section A Basic Program to start you off.

The Less Preferred Method While not proffered this is often the simplest and if you have a complex project architecture this can prevent the solution explorer from looking very messy. Simply navigate in windows explorer to the EMGU extraction folder\bin copy the relevant dll files opencv_core220.dll and opencv_imgproc220.dll to your project bin\Debug folder or to bin\Release folder. This will change with x64 versions as it will be the bin\x64\Debug folder or alternative Release folder. While the benefits are not so clear here, imagine if you require all the opencv DLL files then you will have an extra 34 files within the solution explorer however, it is rare this will be the case.

x64 Architecture and the EMGU.CV.Invoke Exception If you are running an x64 system or designing for them you will have to download separate DLL’s. The steps on forming a project are identical however you will need to change an additional build parameter. Right click on your project file in the solution explorer and select “Properties” at the bottom. Select the “Build” tab from the ribbon bar on the right of this window. There will be an option for Platform Target: with a drop down menu change this from x86 to x64.

Page 10: My Reference Manual EmuCv.pdf

10

Hint: If you are using the express version of visual studio you may not see the x64 option in such a case go to menu option Tools > Options. In this window using the arrows to the left hand side to expand and collapse options. Select “Projects and Solutions” and select the Show advanced build configurations check box.

This will now allow the compilation to run if this is not done correctly. As soon as you access any EMGU code an

exception will be thrown ‘EMGU.CV.Invoke’ through an exception with the ‘InnerException’ "An attempt was

made to load a program with an incorrect format....”.

A Basic Program To get you started a simple program that loads an image and displays it in a picture box has been provided and a little bit more of an advanced one that will show how to access image data and convert between image types. Only x64 Versions are currently available, x86 will be provided shortly. If you have downloaded the sample code you will start with 3 warnings for the references not being found. Expand the References folder within the solution explorer delete the 3 with yellow warning icons and Add fresh references to them, the steps of which are available The Basic Requirements section.

There has been a button item and a picturebox item added to the main form. There default names have not

been changed. When we click on the button we wish to open a file dialog select and image and have it displayed in

the picturebox.

Double click on the button and add the following code:

private void button1_Click(object sender, EventArgs e)

{

OpenFileDialog Openfile = new OpenFileDialog();

if (Openfile.ShowDialog() == DialogResult.OK)

{

Image<Bgr, Byte> My_Image = new Image<Bgr, byte>(Openfile.FileName);

pictureBox1.Image = My_Image.ToBitmap();

}

Page 11: My Reference Manual EmuCv.pdf

11

}

The code is very simple an OpenFileDialog called 'Openfile' is used to select and image file. This image is then

read into an colour Image object called 'My_Image'. The image is displayed by assigning the Image property of

the picturebox. This requires a Bitmap and by calling the .ToBitmap() function of 'My_Image' this is

achieved. This is incredibly simple to achieve once the correct process has been taken in setting up the project. An alternative to the Picturbox item is made available through the EMGU.CV.UI library and is used in the examples. Please visit http://www.emgu.com/wiki/index.php/Add_ImageBox_Control to learn how to add this control to visual studio should you wish to use it.

A Little More Image Processing The slightly more advanced source code project will have the same warnings as described in A Basic Program has been provided. The references will need replacing. In this program there is a demonstration of converting

an Image from colour to greyscale and accessing the Data of individual pixels. While the methods of

suppressing the image spectrum data is not the most efficient it is a good example on accessing the

image Data property.

A little on Converting Images Image conversion in EMGU can be complex. In the example program a Bgr colour image is converted

the Gray or grayscale.

Image<gray,byte> gray_image = My_Image.Convert<gray,byte>();

However you will eventually want to use a different depth (Tdepth) of image rather than Byte. The problem with

this method is you can only convert a depth or colour once per call. Lets say we wish to convert from Image<bgr,byte> to Image<gray,double> you would have to use the following syntax.

Image<Gray,byte> gray_image = My_Image.Convert<Gray,byte>();

Image<Gray,double> gray_image = My_Image.Convert<Gray,double>();

//or alternatively in one line

Image<Gray,> gray_image = My_Image.Convert<Gray,byte>().Convert<Gray,double>();

//alternatively

Image<Gray,Byte> gray_image =

My_Image.Convert<Bgr,double>().Convert<Gray,double>();

Accesing Image Data There are a few ways of accessing image data and assigning values to it. There are two methods available, direct access using the Image Data property of a more remote access. Both are demonstrated here. Note it is important to respect the image spectrum depth when accessing the Data property. A grayscale image will have a depth of one so will be reference as [x,y,0] however a colour image as a depth of 3, [x,y,0], [x,y,1] & [x,y,2] representing the

Blue, Green & Red spectrums respectively (Bgr).

Lets say we wish to assign a value to a pixel at position [0,0] a value. Using the easier remote method we can use:

//Colour Image

My_Image[0, 0] = new Bgr(Color.Red);

//Gray Image

gray_image[0, 0] = new Gray(200);

Or we use the Data property

//Colour Image

Page 12: My Reference Manual EmuCv.pdf

12

Color R = Color.Red;

My_Image.Data[0,0,2] = R.R; //Write to the Red Spectrum

My_Image.Data[0,0,1] = R.G; //Write to the Green Spectrum

My_Image.Data[0,0,0] = R.B; //Write to the Blue Spectrum

//Gray Image

gray_image[0, 0] = new Gray(200);

So writing to a pixel is fairly simple but what about reading a pixel value.

//Colour Image

Bgr my_Bgr = My_Image[0, 0];

//Gray Image

Gray my_Gray = gray_image[0, 0];

Now in many cases you will not want to work with “Bgr” or “Gray” so converting them is important.

//BGR to Color

Color my_colour = Color.FromArgb((int)value.Red, (int)value.Blue, (int)value.Green);

//Gray to int

int my_intensity = (int) my_Gray.Intensity;

You will notice that each value is cast to an integer to allow data loss this is because the intensities are stored

naturally as doubles. However in this case the easier method is accessing the ImageData property. If you wish to

work with the image data there is not a requirement to constantly convert between Gray and integers etc. You can

access the image Data directly and use that.

//Colour

Color my_colour = Color.FromArgb(My_Image.Data[0, 0, 0],

My_Image.Data[0, 0, 1], My_Image.Data[0, 0, 2]);

//Gray Image

int my_intensity = gray_image.Data[0, 0, 0];

Much simpler and far easier to work with when processing the image Data within a loop. To examine how to

implement a loop please download the Little More Image Processing source code.

The DllNotFound Exception and Troubleshooting 0x8007007E Now at some point you are going to receive and error "Unable to load DLL...... (Exception from HRESULT: 0x8007007E)”. You need to read the Message section circled in red bellow.

Page 13: My Reference Manual EmuCv.pdf

13

If the exception is a EMGU.CV.Invoke Exception, chances are you are not targeting the correct platform for your

build. See the section regarding x64 Architecture for details. Now if you’ve progressed through to an advanced image processing method or simply have copied an example to an alternative location than the EMGU extraction folder you will possibly be seeing one of the following errors.

Unable to load DLL 'opencv_highgui220': The specified module could not be found. (Exception from HRESULT: 0x8007007E) Usually caused when you are trying to get a image from a web camera. The solution to this is extremely simple. As discussed in The Basic Requirements section you will need to either copy theopencv_highgui220.dll to the output directory or the more preferred method of adding the file to your project as an existing file and then changing its property “Copy to Output Directory” to “Copy always”. Look back at this section for reference if required.

Unable to load DLL 'cvextern': The specified module could not be found. (Exception from HRESULT: 0x8007007E) This error has a little more of a substantial solution. The cvextern.dll error can not be fixed by simply adding the this one file in fact this file requires all of the files listed bellow to correctly execute. As discussed in The Basic Requirements section you will need to either copy files to the output directory or the more preferred method of adding the files to your project as an existing file and then changing each of their properties “Copy to Output Directory” to “Copy always”. Look back at this section for reference if required. Note that the "220" is the version number this will change according to updates. cudart64_32_16.dll cufft64_32_16.dll cvextern.dll npp64_32_16.dll opencv_calib3d220.dll opencv_contrib220.dll opencv_core220.dll opencv_features2d220.dll opencv_flann220.dll opencv_gpu220.dll opencv_highgui220.dll opencv_imgproc220.dll opencv_legacy220.dll opencv_ml220.dll opencv_objdetect220.dll opencv_video220.dll Any other Unable to load DLL ‘...’ errors can be fixed by attempting the same process an loading the relevant listed DLLs into your project. If you still get stuck than feel free to ask the community for help.

Page 14: My Reference Manual EmuCv.pdf

14

System.TypeInitializationException: Convertion from Image<Emgu.CV.Structure.Bgr*,System.Byte*> to Image<Emgu.CV.Structure.Structure.Bgr*,System.Byte*> is not supported by OpenCV Where * is the the relavent image depth or data type. This error is thrown up in version 2.3.* onwards and is caused by the programs inability to access opencv_imgproc***.dll or opencv_core***.dll even though they are present in the output "bin" directory. There are two solutions, adding them to the project and set there properties to copy always as they are the two key files. Or by replacing the current ones in the Bin folder with new copies can also solve the problem. If both methods fail then there may be a problem with the build so download a new copy from SourceForge and try again. I hope this article sets you on the right path, Thanks for reading.

Camera Capture in 7 lines of code This example requires Emgu CV 1.5.0.0 Excluding the using statements in the beginning, only 7 lines of code are required to perform a camera capture loop. using Emgu.CV;

using Emgu.CV.UI;

using Emgu.CV.Structure;

using System.Drawing;

using System.Windows.Forms;

...

ImageViewer viewer = new ImageViewer(); //create an image viewer

Capture capture = new Capture(); //create a camera captue

Application.Idle += new EventHandler(delegate(object sender, EventArgs e)

{ //run this until application closed (close button click on image viewer)

viewer.Image = capture.QueryFrame(); //draw the image obtained from camera

});

viewer.ShowDialog(); //show the image viewer

Shape (Triangle, Rectangle, Circle, Line) Detection in CSharp

This project is part of the Emgu.CV.Example solution

Shape Detection In this tutorial, we demonstrate how to perform Hough Line and Circle detection using Emgu CV, as well as using the Contour class to detect Triangles and Rectangles in the image. The "pic3.png" file from the OpenCV sample folder is used here.

pic3.png from opencv

Source Code //Load the image from file

Image<Bgr, Byte> img = new Image<Bgr, byte>(fileNameTextBox.Text).Resize(400, 400,

true);

//Convert the image to grayscale and filter out the noise

Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp();

Page 15: My Reference Manual EmuCv.pdf

15

Gray cannyThreshold = new Gray(180);

Gray cannyThresholdLinking = new Gray(120);

Gray circleAccumulatorThreshold = new Gray(120);

CircleF[] circles = gray.HoughCircles(

cannyThreshold,

circleAccumulatorThreshold,

5.0, //Resolution of the accumulator used to detect centers of the circles

10.0, //min distance

5, //min radius

0 //max radius

)[0]; //Get the circles from the first channel

Image<Gray, Byte> cannyEdges = gray.Canny(cannyThreshold, cannyThresholdLinking);

LineSegment2D[] lines = cannyEdges.HoughLinesBinary(

1, //Distance resolution in pixel-related units

Math.PI / 45.0, //Angle resolution measured in radians.

20, //threshold

30, //min Line width

10 //gap between lines

)[0]; //Get the lines from the first channel

#region Find triangles and rectangles

List<Triangle2DF> triangleList = new List<Triangle2DF>();

List<MCvBox2D> boxList = new List<MCvBox2D>();

using (MemStorage storage = new MemStorage()) //allocate storage for contour

approximation

for (Contour<Point> contours = cannyEdges.FindContours(); contours != null;

contours = contours.HNext)

{

Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05,

storage);

if (contours.Area > 250) //only consider contours with area greater than 250

{

if (currentContour.Total == 3) //The contour has 3 vertices, it is a

triangle

{

Point[] pts = currentContour.ToArray();

triangleList.Add(new Triangle2DF(

pts[0],

pts[1],

pts[2]

));

}

else if (currentContour.Total == 4) //The contour has 4 vertices.

{

#region determine if all the angles in the contour are within the range

of [80, 100] degree

bool isRectangle = true;

Point[] pts = currentContour.ToArray();

LineSegment2D[] edges = PointCollection.PolyLine(pts, true);

for (int i = 0; i < edges.Length; i++)

{

double angle = Math.Abs(

edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i]));

if (angle < 80 || angle > 100)

{

Page 16: My Reference Manual EmuCv.pdf

16 isRectangle = false;

break;

}

}

#endregion

if (isRectangle) boxList.Add(currentContour.GetMinAreaRect());

}

}

}

#endregion

originalImageBox.Image = img;

#region draw triangles and rectangles

Image<Bgr, Byte> triangleRectangleImage = img.CopyBlank();

foreach (Triangle2DF triangle in triangleList)

triangleRectangleImage.Draw(triangle, new Bgr(Color.DarkBlue), 2);

foreach (MCvBox2D box in boxList)

triangleRectangleImage.Draw(box, new Bgr(Color.DarkOrange), 2);

triangleRectangleImageBox.Image = triangleRectangleImage;

#endregion

#region draw circles

Image<Bgr, Byte> circleImage = img.CopyBlank();

foreach (CircleF circle in circles)

circleImage.Draw(circle, new Bgr(Color.Brown), 2);

circleImageBox.Image = circleImage;

#endregion

#region draw lines

Image<Bgr, Byte> lineImage = img.CopyBlank();

foreach (LineSegment2D line in lines)

lineImage.Draw(line, new Bgr(Color.Green), 2);

lineImageBox.Image = lineImage;

#endregion

Result

Creating First Emgu CV Project

Introduction

Page 17: My Reference Manual EmuCv.pdf

17 In the last article we read about Starting with Emgu CV, now here we will start our first Emgu CV project. Emgu CV is

not so difficult; all we have to do is to add certain references and make use of Emgu Controls. Let's get started.

Let's start creating a blank Windows Forms application.

You will get a new project created for you, before starting further enable "show all settings" under tools, this

enables many features like form designer layout, snap to grid and many others.

Now let's start. The first thing we will do is to Add References. Browse for the Emgu bin folder (by default it is

located at C:\Emgu\emgucv-windows-x86 2.3.0.1416\bin ), in the bin folder there must be some dlls add all those

starting with "Emgu.CV" (choose only one among Emgu.CV.DebuggerVisualizers.VS2008.dll

and Emgu.CV.DebuggerVisualizers.VS2010.dll depending on the Visual Studio you are using, in my case it

is Emgu.CV.DebuggerVisualizers.VS2010.dll)

Page 18: My Reference Manual EmuCv.pdf

18

Now we need to add some existing items. Go to "Project" > "Add Existing Items" and now again browse for the bin

directory of Emgu CV and this time choose all the dll files starting with "opencv_", these dll files are required each

time the output is generated via Emgu; that is why we added them to our project directory, we will also change

there the property so that they get copied always to the output folder. So, select all the DLLs added and select

properties and change the "Copy to Output Directory" to "Copy Always".

We already have added the Emgu custom controls to our toolbox, now let's design our form, we will be using two

ImageBox (Emgu Control), one Button and a Textbox, design the form as below.

Page 19: My Reference Manual EmuCv.pdf

19

Coding

Now go to the form1.cs code view, and add the following namespaces:

using Emgu.CV;

using Emgu.CV.CvEnum;

using Emgu.CV.Structure;

using Emgu.CV.UI;

Next create some member variables :

Capture capturecam = null; //instance for capture using webcam

bool CapturingProcess = false; //boolean stating the capturing process status

Image<Bgr, Byte> imgOrg; //image type RGB (or Bgr as we say in Open CV)

Image<Gray, Byte> imgProc; //processed image will be grayscale so a gray image

Now it's time to add a "form load event", we will start capturing via webcam under it.

capturecam = new Capture();

This will associate the default webcam with the capturecam object.

Page 20: My Reference Manual EmuCv.pdf

20

We have added the association to the capture object in the try/catch block to avoid the error if the webcam is

already in use.

We added an event handler to "Application.Idle", so that it performs the task when the application is idle, and the

task is to get the next frame. "ProcessFunction" is called at every idle state of the application.

"QueryFrame" gets the next frame from the webcam, if it is null it means there is some problem and hence we stop

our app there.

The "InRange" function takes two parameters, the minimum and maximum values of the Bgr range.

"SmoothGaussian" applies the Gaussian smoothing with the x,y length = 9, we can pass other parameters for x and

y also.

Now let's come to the coding part of the "playorpause" button:

Page 21: My Reference Manual EmuCv.pdf

21

This is the simplest part, it checks the boolean value of CapturingProcess and changes the button text

correspondingly and stops the streaming from the webcam.

Sample Output

ANN MLP (Neural Network) in CSharp What is an Artificial Neural Network (ANN) According to wikipedia,

An artificial neural network (ANN), usually called "neural network" (NN), is a mathematical model or computational model based on biological neural networks. It consists of an interconnected group of artificial neurons and processes information using a connectionist approach to computation. In most cases an ANN is an adaptive system that changes its structure based on external or internal information that flows through the network during the learning phase.

In more practical terms neural networks are non-linear statistical data modeling tools. They can be used to model complex relationships between inputs and outputs or to find patterns in data. OpenCV implements Multi-Layer Perceptrons Neural Network, hence the name ANN_MLP.

Source Code using System.Drawing;

using Emgu.CV.Structure;

using Emgu.CV.ML;

using Emgu.CV.ML.Structure;

...

Page 22: My Reference Manual EmuCv.pdf

22

int trainSampleCount = 100;

#region Generate the traning data and classes

Matrix<float> trainData = new Matrix<float>(trainSampleCount, 2);

Matrix<float> trainClasses = new Matrix<float>(trainSampleCount, 1);

Image<Bgr, Byte> img = new Image<Bgr, byte>(500, 500);

Matrix<float> sample = new Matrix<float>(1, 2);

Matrix<float> prediction = new Matrix<float>(1, 1);

Matrix<float> trainData1 = trainData.GetRows(0, trainSampleCount >> 1, 1);

trainData1.SetRandNormal(new MCvScalar(200), new MCvScalar(50));

Matrix<float> trainData2 = trainData.GetRows(trainSampleCount >> 1, trainSampleCount,

1);

trainData2.SetRandNormal(new MCvScalar(300), new MCvScalar(50));

Matrix<float> trainClasses1 = trainClasses.GetRows(0, trainSampleCount >> 1, 1);

trainClasses1.SetValue(1);

Matrix<float> trainClasses2 = trainClasses.GetRows(trainSampleCount >> 1,

trainSampleCount, 1);

trainClasses2.SetValue(2);

#endregion

Matrix<int> layerSize = new Matrix<int>(new int[] { 2, 5, 1 });

MCvANN_MLP_TrainParams parameters = new MCvANN_MLP_TrainParams();

parameters.term_crit = new MCvTermCriteria(10, 1.0e-8);

parameters.train_method = Emgu.CV.ML.MlEnum.ANN_MLP_TRAIN_METHOD.BACKPROP;

parameters.bp_dw_scale = 0.1;

parameters.bp_moment_scale = 0.1;

using (ANN_MLP network = new ANN_MLP(layerSize,

Emgu.CV.ML.MlEnum.ANN_MLP_ACTIVATION_FUNCTION.SIGMOID_SYM, 1.0, 1.0))

{

network.Train(trainData, trainClasses, null, null, parameters,

Emgu.CV.ML.MlEnum.ANN_MLP_TRAINING_FLAG.DEFAULT);

for (int i = 0; i < img.Height; i++)

{

for (int j = 0; j < img.Width; j++)

{

sample.Data[0, 0] = j;

sample.Data[0, 1] = i;

network.Predict(sample, prediction);

// estimates the response and get the neighbors' labels

float response = prediction.Data[0,0];

// highlight the pixel depending on the accuracy (or confidence)

img[i, j] = response < 1.5 ? new Bgr(90, 0, 0) : new Bgr(0, 90, 0);

}

}

}

// display the original training samples

for (int i = 0; i < (trainSampleCount >> 1); i++)

{

PointF p1 = new PointF(trainData1[i, 0], trainData1[i, 1]);

img.Draw(new CircleF(p1, 2), new Bgr(255, 100, 100), -1);

PointF p2 = new PointF((int)trainData2[i, 0], (int)trainData2[i, 1]);

img.Draw(new CircleF(p2, 2), new Bgr(100, 255, 100), -1);

}

Emgu.CV.UI.ImageViewer.Show(img);