220 likes | 238 Views
EEC-492/592 Kinect Application Development. Lecture 17 Wenbing Zhao wenbing@ieee.org. Outline. Emgu CV Software installation Configure a new project with Emgu CV Working with Emgu CV images. Software Needed. OpenCV does not support C#: cannot use it directly
E N D
EEC-492/592Kinect Application Development Lecture 17 Wenbing Zhao wenbing@ieee.org
Outline Emgu CV Software installation Configure a new project with Emgu CV Working with Emgu CV images
Software Needed • OpenCV does not support C#: cannot use it directly • We will be using Emgu CV: a cross platform .Net wrapper for OpenCV • http://www.emgu.com/wiki/index.php/Main_Page • Due to unknown reason, later version of EmguCV does not work on x64 Windows platform • Latest version that worked for me is: http://sourceforge.net/projects/emgucv/files/emgucv/2.2.1/libemgucv-windows-x64-2.2.1.1150.zip/download
Configuration with EmguCV • It is tricky to use EmguCV in Visual Studio 2010 • You must add the following EmguCV dll files as references • Emgu.CV.dll • Emgu.CV.UI.dll • Emgu.Util.dll • Furthermore, you must copy at least the following OpenCV dlls to your project’s bin/Debug or bin/Release directory • opencv_core220.dll • opencv_imgproc220.dll
Configuration with EmguCV • Alternatively, you can add opencv dlls as files into your project. For each dll, right click and select properties. Then choose “copy always”. The dll will be copied to the output directory for you. • More one critical step. Right click your project name in the “Solution Explorer” pane, and select properties. Then, choose the “Build” tab and change the platform target to “x64”
Working with EmguCV Images • EmguCV Image Class • Creating Image • Getting/setting pixels • Drawing objects on image EEC492/693/793 - iPhone Application Development
Generic Parameters for EmguCV Images • Supported TDepth types: • Byte • SByte • Single (float) • Double • UInt16 • Int16 • Int32 (int) • Image<TColor, TDepth> • Depth: number of bits used to represent the color of a single pixel • Color: type of color representation. Emgu CV supports Supported TColor types: 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<Gray, Byte> image = new Image<Gray, Byte>( width, height);
Creating EmguCV Images • Creating a new image • No background • With blue background • Creating an image from an existing file • Creating an image from bitmap Image<Bgr, Byte> img1 = new Image<Bgr, Byte>(480, 320); Image<Bgr, Byte> img1 = new Image<Bgr, Byte>(480, 320, new Bgr(255, 0, 0)); Image<Bgr, Byte> img1 = new Image<Bgr, Byte>("MyImage.jpg"); Image<Bgr, Byte> img = new Image<Bgr, Byte>(bmp); EEC492/693/793 - iPhone Application Development
Accessing Image Data (Pixels) • Direct access to Image //Color Image My_Image[0, 0] = new Bgr(Color.Red); //Gray Image gray_image[0, 0] = new Gray(200); //Color Image Bgr my_Bgr = My_Image[0, 0]; //Gray Image Gray my_Gray = gray_image[0, 0];
Accessing Image Data (Pixels) • Access via Image.Data property • Must respect the image depth when accessing the Data property • A grayscale image has a depth of one (i.e., 1 bit) • [x,y,0] • RGB color image has a depth of 3 (i.e., 23 bits or one Byte) • [x,y,0], [x,y,1], [x,y,2] represent the blue, green, and red spectrums //Color Image 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);
Accessing Image Data: Examples • Using column per row access: http://stackoverflow.com/questions/5101986/iterate-over-pixels-of-an-image-with-emgu-cv private void settingPixelsSlow(Image<Bgr, Byte> img) { Stopwatch evaluator = new Stopwatch(); int repetitions = 100; Bgr color = new Bgr(100, 40, 243); evaluator.Start(); for (int run = 0; run < repetitions; run++) { for (int j = 0; j < img.Cols; j++) { for (int i = 0; i < img.Rows; i++){ img[i, j] = color; } } } evaluator.Stop(); Console.WriteLine("Average execution time for {0} iteration \n using column per row access: {1}ms\n", repetitions, evaluator.ElapsedMilliseconds / repetitions); }
Accessing Image Data: Examples private void settingPixelsFaster(Image<Bgr, Byte> img) { Stopwatch evaluator = new Stopwatch(); int repetitions = 100; evaluator.Start(); for (int run = 0; run < repetitions; run++) { for (int j = 0; j < img.Cols; j++) { for (int i = 0; i < img.Rows; i++) { img.Data[i, j,0] = 100; img.Data[i, j, 1] = 40; img.Data[i, j, 2] = 243; } } } evaluator.Stop(); Console.WriteLine("Average execution time for {0} iteration \n using Data property: {1}ms\n", repetitions, evaluator.ElapsedMilliseconds / repetitions); } • Using Data property
Accessing Image Data: Examples private void settingPixelsFastest(Image<Bgr, Byte> img) { Stopwatch evaluator = new Stopwatch(); int repetitions = 100; byte[, ,] data = img.Data; evaluator.Start(); for (int run = 0; run < repetitions; run++) { for (int j = 0; j < img.Cols; j++) { for (int i = 0; i < img.Rows; i++) { data[i, j, 0] = 100; data[i, j, 1] = 40; data[i, j, 2] = 243; } } } evaluator.Stop(); Console.WriteLine("Average execution time for {0} iteration \n using Data property smartly: {1}ms\n", repetitions, evaluator.ElapsedMilliseconds / repetitions); } • Using Data property outside the loop:
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 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
First EmguCV WPF App • Basic image type is: Image<Rgb,byte> • It is a wrapper for IplImage class in OpenCV • Image<> offers many constructors • public Image(Bitmap bmp); • public Image(string fileName); • public Image(int width, int height); • public Image(int width, int height, TColor value); • public Image(int width, int height, int stride, IntPtr scan0); • In the app, we will create a new Image object, draw “Hello world”, and display via WPF image control
First EmguCV WPF App • Create a new WPF project • Add emgu cv dlls and opencv dlls • Add System.Drawing reference • Change platform target to x64 • Add one image control in MainWindow • Draw “Hello world” using EmguCV Image<> • Convert the image to BitmapSource using the provided helper function • Set the BitmapSource as the WPF image control source
First EmguCV WPF App • Add the following namespaces: • using Emgu.CV; • using Emgu.CV.CvEnum; • using Emgu.CV.Structure; // for Image to BitmapSource conversion • using System.IO; • using System.Runtime.InteropServices; • using System.Drawing; • using System.Drawing.Imaging; // for Stopwatch • using System.Diagnostics;
First EmguCV WPF App public MainWindow() { InitializeComponent(); //Create an image of 400x200 of Blue color Image<Bgr, Byte> img = new Image<Bgr, byte>(400, 200, new Bgr(255, 0, 0)); MCvFont f = new MCvFont(FONT.CV_FONT_HERSHEY_COMPLEX, 1.0, 1.0); //Create the font //Draw "Hello, world." on the image using the specific font img.Draw("Hello, world", ref f, new System.Drawing.Point(10, 80), new Bgr(0, 255, 0)); BitmapSource imgsource=ToBitmapSource(img); image1.Source = imgsource; }
First EmguCV WPF App // taken from: http://blogs.claritycon.com/blog/2012/11/blob-tracking-kinect-opencv-wpf/ [DllImport("gdi32")] private static extern int DeleteObject(IntPtr o); public BitmapSource ToBitmapSource(IImage image) { using (System.Drawing.Bitmap source = image.Bitmap) { IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap( ptr, IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()); DeleteObject(ptr); //release the HBitmap return bs; }}
Have a little more fun • EmguCV Image also provides a number of drawing methods • Draw a Circle of the specific color and thickness • // thickness: If thickness is less than 1, the circle is filled up • void Draw(CircleF circle, TColor color, int thickness); • // others • void Draw(Ellipse ellipse, TColor color, int thickness); • void Draw(IConvexPolygonF polygon, TColor color, int thickness); • void Draw(LineSegment2D line, TColor color, int thickness); • void Draw(Rectangle rect, TColor color, int thickness);
Accessing Pixels in Image • Try out the three ways of accessing pixels in the image • Draw more customized patterns in the image