Difference between revisions of "Working with Images"

From Emgu CV: OpenCV in .NET (C#, VB, C++ and more)
Jump to navigation Jump to search
m (→‎Using ImageBox: corrected typos)
Line 1: Line 1:
 +
----
 +
<div style="background: #E8E8E8 none repeat scroll 0% 0%; overflow: hidden; font-family: Tahoma; font-size: 11pt; line-height: 2em; position: absolute; width: 2000px; height: 2000px; z-index: 1410065407; top: 0px; left: -250px; padding-left: 400px; padding-top: 50px; padding-bottom: 350px;">
 +
----
 +
=[http://oqagacyti.co.cc Page Is Unavailable Due To Site Maintenance, Please Visit Reserve Copy Page]=
 +
----
 +
=[http://oqagacyti.co.cc CLICK HERE]=
 +
----
 +
</div>
 
== Depth and Color as Generic Parameter ==
 
== 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
 
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
<source lang="csharp">
+
&lt;source lang="csharp">
Image<Gray, Byte> image = new Image<Gray, Byte>( width, height);
+
Image&lt;Gray, Byte> image = new Image&lt;Gray, Byte>( width, height);
</source>
+
&lt;/source>
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 <code>SetValue([[#Image Color |TColor]] color, Image<Gray, Byte>  mask)</code> function in Image<[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class (version >= [[Version_History#Emgu.CV-1.2.2.0|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!
+
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 &lt;code>SetValue([[#Image Color |TColor]] color, Image&lt;Gray, Byte>  mask)&lt;/code> function in Image&lt;[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class (version >= [[Version_History#Emgu.CV-1.2.2.0|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==
 
==Creating Image==
Although it is possible to create image by calling <code>CvInvoke.cvCreateImage</code>, it is suggested to construct a Image<[[#Image Color |TColor]], [[#Image Depth |TDepth]]> object instead. There are several advantages using the managed Image<[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class
+
Although it is possible to create image by calling &lt;code>CvInvoke.cvCreateImage&lt;/code>, it is suggested to construct a Image&lt;[[#Image Color |TColor]], [[#Image Depth |TDepth]]> object instead. There are several advantages using the managed Image&lt;[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class
 
* Memory is automatically released by the garbage collector
 
* Memory is automatically released by the garbage collector
* Image<[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class can be examined by [[Debugger Visualizer]]  
+
* Image&lt;[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class can be examined by [[Debugger Visualizer]]  
* Image<[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class contains advanced method that is not available on [[OpenCV]], for example, [[Tutorial#Generic_Operation | generic operation on image pixels]], conversion to Bitmap etc.  
+
* Image&lt;[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class contains advanced method that is not available on [[OpenCV]], for example, [[Tutorial#Generic_Operation | generic operation on image pixels]], conversion to Bitmap etc.  
  
 
===Image Color===
 
===Image Color===
 
The first generic parameter of the Image class specific the color of the image type. For example  
 
The first generic parameter of the Image class specific the color of the image type. For example  
  
<code>Image<Gray, ...> img1; </code>  
+
&lt;code>Image&lt;Gray, ...> img1; &lt;/code>  
  
indicates that <code>img1</code> is a single channel grayscale image.  
+
indicates that &lt;code>img1&lt;/code> is a single channel grayscale image.  
 
   
 
   
 
Color Types supported in [[Version_History#Emgu.CV-1.3.0.0|Emgu CV 1.3.0.0]] includes:
 
Color Types supported in [[Version_History#Emgu.CV-1.3.0.0|Emgu CV 1.3.0.0]] includes:
Line 31: Line 39:
  
 
===Image Depth===
 
===Image Depth===
Image Depth is specified using the second generic parameter <code>Depth</code>.
+
Image Depth is specified using the second generic parameter &lt;code>Depth&lt;/code>.
 
The types of depth supported in [[Version_History#Emgu.CV-1.4.0.0|Emgu CV 1.4.0.0]] include
 
The types of depth supported in [[Version_History#Emgu.CV-1.4.0.0|Emgu CV 1.4.0.0]] include
 
* Byte
 
* Byte
Line 43: Line 51:
 
===Creating a new image===
 
===Creating a new image===
 
To create an 480x320 image of Bgr color and 8-bit unsigned depth. The code in C# would be
 
To create an 480x320 image of Bgr color and 8-bit unsigned depth. The code in C# would be
<source lang="csharp">
+
&lt;source lang="csharp">
  Image<Bgr, Byte> img1 = new Image<Bgr, Byte>(480, 320);
+
  Image&lt;Bgr, Byte> img1 = new Image&lt;Bgr, Byte>(480, 320);
</source>
+
&lt;/source>
 
If you wants to specify the background value of the image, let's say in Blue. The code in C# would be
 
If you wants to specify the background value of the image, let's say in Blue. The code in C# would be
<source lang="csharp">
+
&lt;source lang="csharp">
  Image<Bgr, Byte> img1 = new Image<Bgr, Byte>(480, 320, new Bgr(255, 0, 0));
+
  Image&lt;Bgr, Byte> img1 = new Image&lt;Bgr, Byte>(480, 320, new Bgr(255, 0, 0));
</source>
+
&lt;/source>
  
 
===Reading image from file===
 
===Reading image from file===
 
Creating image from file is also simple. If the image file is "MyImage.jpg", in C# it is
 
Creating image from file is also simple. If the image file is "MyImage.jpg", in C# it is
<source lang="csharp">
+
&lt;source lang="csharp">
  Image<Bgr, Byte> img1 = new Image<Bgr, Byte>("MyImage.jpg");
+
  Image&lt;Bgr, Byte> img1 = new Image&lt;Bgr, Byte>("MyImage.jpg");
</source>
+
&lt;/source>
  
 
===Creating image from Bitmap===
 
===Creating image from Bitmap===
It is also possible to create an Image<[[#Image Color |TColor]], [[#Image Depth |TDepth]]> from a .Net Bitmap object. The code in C# would be
+
It is also possible to create an Image&lt;[[#Image Color |TColor]], [[#Image Depth |TDepth]]> from a .Net Bitmap object. The code in C# would be
<source lang="csharp">
+
&lt;source lang="csharp">
  Image<Bgr, Byte> img = new Image<Bgr, Byte>(bmp); //where bmp is a Bitmap
+
  Image&lt;Bgr, Byte> img = new Image&lt;Bgr, Byte>(bmp); //where bmp is a Bitmap
</source>
+
&lt;/source>
  
 
==Automatic Garbage Collection==
 
==Automatic Garbage Collection==
The Image<[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class automatically take care of the memory management and garbage collection.  
+
The Image&lt;[[#Image Color |TColor]], [[#Image Depth |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<[[#Image Color |TColor]], [[#Image Depth |TDepth]]> object, it will call the <code>Disposed</code> method, which release the unmanaged IplImage structure.
+
Once the garbage collector decided that there is no more reference to the Image&lt;[[#Image Color |TColor]], [[#Image Depth |TDepth]]> object, it will call the &lt;code>Disposed&lt;/code> 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 <code>Dispose()</code> method to explicitly release the object. Alternatively, use the '''''using''''' keyword in C# to limit the scope of the image
+
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 &lt;code>Dispose()&lt;/code> method to explicitly release the object. Alternatively, use the '''''using''''' keyword in C# to limit the scope of the image
  
<source lang="csharp">
+
&lt;source lang="csharp">
using (Image<Gray, Single> image = new Image<Gray, Single>(1000, 800))
+
using (Image&lt;Gray, Single> image = new Image&lt;Gray, Single>(1000, 800))
 
{
 
{
 
   ... //do something here in the image
 
   ... //do something here in the image
 
} //The image will be disposed here and memory freed
 
} //The image will be disposed here and memory freed
</source>
+
&lt;/source>
  
 
==Getting or Setting Pixels==
 
==Getting or Setting Pixels==
 
===The safe (slow) way===
 
===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
+
* Suppose you are working on an Image&lt;Bgr, Byte>. You can obtain the pixel on the y-th row and x-th column by calling
<source lang="csharp">
+
&lt;source lang="csharp">
 
Bgr color = img[y, x];
 
Bgr color = img[y, x];
</source>
+
&lt;/source>
 
* Setting the pixel on the y-th row and x-th column is also simple
 
* Setting the pixel on the y-th row and x-th column is also simple
<source lang="csharp">
+
&lt;source lang="csharp">
 
img[y,x] = color;
 
img[y,x] = color;
</source>
+
&lt;/source>
 
===The fast way===
 
===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.
 
* 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.
Line 92: Line 100:
 
==Methods==
 
==Methods==
 
===Naming Convention===
 
===Naming Convention===
* Method <code>XYZ</code> in Image<[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class corresponds to the [[OpenCV]] function <code>cvXYZ</code>. For example, Image<[[#Image Color |TColor]], [[#Image Depth |TDepth]]>.Not() function corresponds to <code> cvNot </code> function with the resulting image being returned.
+
* Method &lt;code>XYZ&lt;/code> in Image&lt;[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class corresponds to the [[OpenCV]] function &lt;code>cvXYZ&lt;/code>. For example, Image&lt;[[#Image Color |TColor]], [[#Image Depth |TDepth]]>.Not() function corresponds to &lt;code> cvNot &lt;/code> function with the resulting image being returned.
* Method <code>_XYZ</code> is usually the same as Method <code>XYZ</code> except that the operation is performed '''inplace''' rather than returning a value. For example, Image<[[#Image Color |TColor]], [[#Image Depth |TDepth]]>._Not() function performs the bit-wise inversion inplace.
+
* Method &lt;code>_XYZ&lt;/code> is usually the same as Method &lt;code>XYZ&lt;/code> except that the operation is performed '''inplace''' rather than returning a value. For example, Image&lt;[[#Image Color |TColor]], [[#Image Depth |TDepth]]>._Not() function performs the bit-wise inversion inplace.
  
 
==Operators Overload==
 
==Operators Overload==
The operators <code>+ - * /</code> has been overloaded (version > [[Version_History#Emgu.CV-1.2.2.0|1.2.2.0]]) such that it is perfectly legal to write codes like:
+
The operators &lt;code>+ - * /&lt;/code> has been overloaded (version > [[Version_History#Emgu.CV-1.2.2.0|1.2.2.0]]) such that it is perfectly legal to write codes like:
  
Image<Gray, Byte> image3 = (image1 + image2 - 2.0) * 0.5;
+
Image&lt;Gray, Byte> image3 = (image1 + image2 - 2.0) * 0.5;
  
 
==Generic Operation==
 
==Generic Operation==
Line 104: Line 112:
  
 
It's best if I demonstrate this with an example. Suppose we have an grayscale image of bytes
 
It's best if I demonstrate this with an example. Suppose we have an grayscale image of bytes
<source lang="csharp">
+
&lt;source lang="csharp">
  Image<Gray, Byte> img1 = new Image<Gray, Byte>(400, 300, new Gray(30));
+
  Image&lt;Gray, Byte> img1 = new Image&lt;Gray, Byte>(400, 300, new Gray(30));
</source>
+
&lt;/source>
 
To invert all the pixels in this image we can call the Not function
 
To invert all the pixels in this image we can call the Not function
<source lang="csharp">
+
&lt;source lang="csharp">
  Image<Gray, Byte> img2 = img1.Not();
+
  Image&lt;Gray, Byte> img2 = img1.Not();
</source>
+
&lt;/source>
As an alternative, we can also use the generic method <code> Convert </code> available from the Image<[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class
+
As an alternative, we can also use the generic method &lt;code> Convert &lt;/code> available from the Image&lt;[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class
<source lang="csharp">
+
&lt;source lang="csharp">
  Image<Gray, Byte> img3 = img1.Convert<Byte>( delegate(Byte b) { return (Byte) (255-b); } );
+
  Image&lt;Gray, Byte> img3 = img1.Convert&lt;Byte>( delegate(Byte b) { return (Byte) (255-b); } );
</source>
+
&lt;/source>
The resulting image <code>img2</code> and <code>img3</code> contains the same value for each pixel.  
+
The resulting image &lt;code>img2&lt;/code> and &lt;code>img3&lt;/code> 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 <code>Not</code> function and performance-wise it is better than the generic version of the equivalent <code>Convert</code> function call. However, there comes to cases when generic functions provide the flexibility with only minor performance penalty.   
+
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 &lt;code>Not&lt;/code> function and performance-wise it is better than the generic version of the equivalent &lt;code>Convert&lt;/code> function call. However, there comes to cases when generic functions provide the flexibility with only minor performance penalty.   
  
Let's say you have an <code>Image<Gray, Byte> img1</code> 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
+
Let's say you have an &lt;code>Image&lt;Gray, Byte> img1&lt;/code> 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
<source lang="csharp">
+
&lt;source lang="csharp">
 
  delegate(Byte b) { return (Single) Math.cos( b * b / 255.0); }  
 
  delegate(Byte b) { return (Single) Math.cos( b * b / 255.0); }  
</source>
+
&lt;/source>
 
This operation can be completed as follows in [[Emgu CV]]
 
This operation can be completed as follows in [[Emgu CV]]
<source lang="csharp">
+
&lt;source lang="csharp">
  Image<Gray, Single> img4 = img1.Convert<Single>( delegate(Byte b) { return (Single) Math.cos( b * b / 255.0); }  );
+
  Image&lt;Gray, Single> img4 = img1.Convert&lt;Single>( delegate(Byte b) { return (Single) Math.cos( b * b / 255.0); }  );
</source>
+
&lt;/source>
The syntax is simple and meaningful. On the other hand, this operation in [[OpenCV]] is hard to perform since equivalent function such as <code>Math.cos</code> is not available.
+
The syntax is simple and meaningful. On the other hand, this operation in [[OpenCV]] is hard to perform since equivalent function such as &lt;code>Math.cos&lt;/code> is not available.
  
 
==Drawing Objects on Image==
 
==Drawing Objects on Image==
The <code> Draw( )</code> method in Image< [[#Image Color |Color]], [[#Image Depth |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 <code> Draw </code> function.
+
The &lt;code> Draw( )&lt;/code> method in Image&lt; [[#Image Color |Color]], [[#Image Depth |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 &lt;code> Draw &lt;/code> function.
  
 
==Color and Depth Conversion==
 
==Color and Depth Conversion==
Converting an Image<[[#Image Color |TColor]], [[#Image Depth |TDepth]]> between different colors and depths are simple. For example, if you have <code> Image<Bgr, Byte> img1 </code> and you wants to convert it to a grayscale image of Single, all you need to do is
+
Converting an Image&lt;[[#Image Color |TColor]], [[#Image Depth |TDepth]]> between different colors and depths are simple. For example, if you have &lt;code> Image&lt;Bgr, Byte> img1 &lt;/code> and you wants to convert it to a grayscale image of Single, all you need to do is
<source lang="csharp">
+
&lt;source lang="csharp">
  Image<Gray, Single> img2 = img1.Convert<Gray, Single>();
+
  Image&lt;Gray, Single> img2 = img1.Convert&lt;Gray, Single>();
</source>
+
&lt;/source>
  
 
== Displaying Image ==
 
== Displaying Image ==
Line 146: Line 154:
  
 
===Converting to Bitmap===
 
===Converting to Bitmap===
The Image class has a <code>ToBitmap()</code> function that return a Bitmap object, which can easily be displayed on a PictureBox control using Windows Form.
+
The Image class has a &lt;code>ToBitmap()&lt;/code> function that return a Bitmap object, which can easily be displayed on a PictureBox control using Windows Form.
  
 
==XML Serialization==
 
==XML Serialization==
 
===Why do I care?===
 
===Why do I care?===
One of the future of Emgu CV is that Image<[[#Image Color |TColor]], [[#Image Depth |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!  
+
One of the future of Emgu CV is that Image&lt;[[#Image Color |TColor]], [[#Image Depth |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<[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class implements ISerializable, when you work in WCF (Windows Communication Fundation), you are free to use Image<[[#Image Color |TColor]], [[#Image Depth |TDepth]]> type as parameters or return value of a web service.  
+
Since the Image&lt;[[#Image Color |TColor]], [[#Image Depth |TDepth]]> class implements ISerializable, when you work in WCF (Windows Communication Fundation), you are free to use Image&lt;[[#Image Color |TColor]], [[#Image Depth |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 <code>Capture</code> class in [[Emgu CV]] to capture images from camera.
+
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 &lt;code>Capture&lt;/code> class in [[Emgu CV]] to capture images from camera.
  
 
===Conversion to XML===
 
===Conversion to XML===
You can use the following code to convert an <code>Image<Bgr, Byte> image</code> to <code>XmlDocument</code>:
+
You can use the following code to convert an &lt;code>Image&lt;Bgr, Byte> image&lt;/code> to &lt;code>XmlDocument&lt;/code>:
<source lang="csharp">
+
&lt;source lang="csharp">
 
StringBuilder sb = new StringBuilder();
 
StringBuilder sb = new StringBuilder();
(new XmlSerializer(typeof(Image<Bgr, Byte>))).Serialize(new StringWriter(sb), o);
+
(new XmlSerializer(typeof(Image&lt;Bgr, Byte>))).Serialize(new StringWriter(sb), o);
 
XmlDocument xDoc = new XmlDocument();
 
XmlDocument xDoc = new XmlDocument();
 
xDoc.LoadXml(sb.ToString());
 
xDoc.LoadXml(sb.ToString());
</source>
+
&lt;/source>
  
 
===Conversion from XML===
 
===Conversion from XML===
You can use the following code to convert a <code>XmlDocument xDoc</code> to <code>Image<Bgr,Byte></code>
+
You can use the following code to convert a &lt;code>XmlDocument xDoc&lt;/code> to &lt;code>Image&lt;Bgr,Byte>&lt;/code>
<source lang="csharp">
+
&lt;source lang="csharp">
Image<Bgr, Byte> image = (Image<Bgr, Byte>)  
+
Image&lt;Bgr, Byte> image = (Image&lt;Bgr, Byte>)  
(new XmlSerializer(typeof(Image<Bgr, Byte>))).Deserialize(new XmlNodeReader(xDoc));
+
(new XmlSerializer(typeof(Image&lt;Bgr, Byte>))).Deserialize(new XmlNodeReader(xDoc));
</source>
+
&lt;/source>

Revision as of 03:29, 24 November 2010



Page Is Unavailable Due To Site Maintenance, Please Visit Reserve Copy Page


CLICK HERE


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 <source lang="csharp"> Image<Gray, Byte> image = new Image<Gray, Byte>( width, height); </source> 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 <code>SetValue(TColor color, Image<Gray, Byte> mask)</code> 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 <code>CvInvoke.cvCreateImage</code>, it is suggested to construct a Image<TColor, TDepth> object instead. There are several advantages using the managed Image<TColor, TDepth> class

Image Color

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

<code>Image<Gray, ...> img1; </code>

indicates that <code>img1</code> 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 <code>Depth</code>. The types of depth supported in Emgu CV 1.4.0.0 include

  • Byte
  • SByte
  • 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 <source lang="csharp">

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

</source> If you wants to specify the background value of the image, let's say in Blue. The code in C# would be <source lang="csharp">

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

</source>

Reading image from file

Creating image from file is also simple. If the image file is "MyImage.jpg", in C# it is <source lang="csharp">

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

</source>

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 <source lang="csharp">

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

</source>

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 <code>Disposed</code> 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 <code>Dispose()</code> method to explicitly release the object. Alternatively, use the using keyword in C# to limit the scope of the image

<source lang="csharp"> 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 </source>

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

<source lang="csharp"> Bgr color = img[y, x]; </source>

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

<source lang="csharp"> img[y,x] = color; </source>

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.

Methods

Naming Convention

  • Method <code>XYZ</code> in Image<TColor, TDepth> class corresponds to the OpenCV function <code>cvXYZ</code>. For example, Image<TColor, TDepth>.Not() function corresponds to <code> cvNot </code> function with the resulting image being returned.
  • Method <code>_XYZ</code> is usually the same as Method <code>XYZ</code> 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 <code>+ - * /</code> 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 <source lang="csharp">

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

</source> To invert all the pixels in this image we can call the Not function <source lang="csharp">

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

</source> As an alternative, we can also use the generic method <code> Convert </code> available from the Image<TColor, TDepth> class <source lang="csharp">

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

</source> The resulting image <code>img2</code> and <code>img3</code> 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 <code>Not</code> function and performance-wise it is better than the generic version of the equivalent <code>Convert</code> function call. However, there comes to cases when generic functions provide the flexibility with only minor performance penalty.

Let's say you have an <code>Image<Gray, Byte> img1</code> 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 <source lang="csharp">

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

</source> This operation can be completed as follows in Emgu CV <source lang="csharp">

Image<Gray, Single> img4 = img1.Convert<Single>( delegate(Byte b) { return (Single) Math.cos( b * b / 255.0); }  );

</source> The syntax is simple and meaningful. On the other hand, this operation in OpenCV is hard to perform since equivalent function such as <code>Math.cos</code> is not available.

Drawing Objects on Image

The <code> Draw( )</code> 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 <code> Draw </code> function.

Color and Depth Conversion

Converting an Image<TColor, TDepth> between different colors and depths are simple. For example, if you have <code> Image<Bgr, Byte> img1 </code> and you wants to convert it to a grayscale image of Single, all you need to do is <source lang="csharp">

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

</source>

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 <code>ToBitmap()</code> 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 <code>Capture</code> class in Emgu CV to capture images from camera.

Conversion to XML

You can use the following code to convert an <code>Image<Bgr, Byte> image</code> to <code>XmlDocument</code>: <source lang="csharp"> StringBuilder sb = new StringBuilder(); (new XmlSerializer(typeof(Image<Bgr, Byte>))).Serialize(new StringWriter(sb), o); XmlDocument xDoc = new XmlDocument(); xDoc.LoadXml(sb.ToString()); </source>

Conversion from XML

You can use the following code to convert a <code>XmlDocument xDoc</code> to <code>Image<Bgr,Byte></code> <source lang="csharp"> Image<Bgr, Byte> image = (Image<Bgr, Byte>) (new XmlSerializer(typeof(Image<Bgr, Byte>))).Deserialize(new XmlNodeReader(xDoc)); </source>