Click here to Skip to main content
15,911,035 members
Articles / Programming Languages / C#
Tip/Trick

A .NET approach to EmguCV

Rate me:
Please Sign up or sign in to vote.
4.25/5 (3 votes)
21 Oct 2015CPOL4 min read 31.3K   88   9  
Complete guide for beginner to setup EmguCV project and run first program in Visual Studio
This is an old version of the currently published tip/trick.

Introduction

The following article is desgined for beginners with a little understanding of C# and no understanding of EmguCV. First, what is EmguCV? EmguCV is a collection of libraries written in C#, C++, VB and other languages. Is it similar to famous APIs like Matlab or OpenCV? Naah!

Background

In simple words, EmguCV is just a wrapper which calls OpenCV methods from supported languages like C#,VB etc. Unlike other wrappers, it doesn't use unsafe code and is written purely in C# which makes EmguCV a way different, better and efficient than others.

Requirements

  1. C#
  2. Visual Studio (2013 used in this article)
  3. EmguCV libraries Installer (Link, FileSize = 214MB approx, you can use the latest if you want)

Using the code

After installing emguCV libraries via Installer, goto your My Computer->Properties->Advanced System Settings->Advanced->Environment Variables. In System Variable Groupbox, select Path and click Edit. In the textbox, add a semi-colon(;) at the end of text and add the path of the emguCV libraries(X\emgucv\bin\x86) where X = "Directory where your EmguCV libraries are installed". Click OK to confirm.

Image 1

Create a new project under File->New->Project and select WPF Application from project wizard.

You need three files to began working on Emgu CV located under "X\emgucv\bin\" where X = "Directory where your EmguCV libraries are installed" 

  • Emgu.CV.dll
  • Emgu.CV.UI.dll
  • Emgu.Util.dll

After Project creation, right-click on References in Solution Explorer and click on Add Reference. In Add Reference window, browse and select the above three listed dlls under specificied directory(see above) and click OK to add them to your project references. If everything goes well, your solution explorer should look like this.

Image 2

Add following references to your MainWindows.xaml.cs file to include Emgu CV references.

C#
using Emgu.CV;
using Emgu.Util;
using Emgu.CV.Structure;

and add the following code to display an image.

Note: Add System.Drawing.dll (if not included) as reference provided in Add Reference->Assemblies->Check System.Drawing. and click OK.

Drag and drop an image to your solution explorer(project) and then right-click to select properties. Set the Build Action to Content Type to Content and Copy to Output Directory  Copy If Newer  to copy image while building project to use it at runtime. Huh! Environemt settings done references added, ready to code, locked and loaded.

Let run your neurons (Coding...)

Alright! Let's Code

In MainWindow.xaml

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="270*"/>
            <RowDefinition Height="60"/>
        </Grid.RowDefinitions>
        <Image x:Name="cv_image" Grid.Row="0" />
        <StackPanel HorizontalAlignment="Center" Orientation="Horizontal" Grid.Row="1" Margin="10">
            <Button Content="Browse" Width="70" Height="30" Click="Button_Click"></Button>
        </StackPanel>
    </Grid>

In MainWindow.xaml.cs

C#
public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog();
            openFileDialog.Filter = "All Image Files (*.png,*.jpg,*.bmp)|*.png;*.jpg;*.bmp";
            var result = openFileDialog.ShowDialog();
            if(result.Value == true)
            {
                var image = new Image<Bgr, Byte>(openFileDialog.FileName);
                cv_image.Source = BitmapSourceConvert.ToBitmapSource(image);
            }
        }
    }
    //Using unsafe c# code to convert System.Drawing.Bitmap to WPF Media.Imaging
    public static class BitmapSourceConvert
    {
        [DllImport("gdi32")]
        private static extern int DeleteObject(IntPtr o);

        public static BitmapSource ToBitmapSource(IImage image)
        {
            using (System.Drawing.Bitmap source = image.Bitmap)
            {
                IntPtr ptr = source.GetHbitmap();

                BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                    ptr,
                    IntPtr.Zero,
                    Int32Rect.Empty,
                    System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());

                DeleteObject(ptr);
                return bs;
            }
        }
    }

Code is pretty simple. In XAML file, there is a Root grid with rows. Image with name 'cv_image' is in the first row and a stackpanel in the second row which has a 'Browse' button to open file with an 'Click' event handler which call Button_Click event in code behind. In Button_Click method, there is a OpenFileDialog with filter equal to Images extension. After selecting image from dialog, Image<Bgr, Byte>( "Image File Name" ) method will load the image in specified (RGB) format. 

Handling emgu.cv.cvinvoke Exception

If you haven't face emgu.cv.cvinvoke exception on build, then skip this step.

Current Versions of Emgu CV support both x86 and x64 architectures you have to specify the architecture in order to build the program successfully on x64. To switch between x86 and x64, you have to set the arhictecture manually.

Right-Click on your Project->Properties and then select Build from left sidebar. In the Platform Taget Combo Box select x86 to switch to x86 architecture or x64 for 64-bit. (For x64, you might need x64 emguCV libraries, which you can copy from the installer extracted libraries.

Image 3

Build and run your project. Hope it will do the trick.

Result:

Image 4

Conversion to Color Spaces

An image consist of picture elements called pixels. Human eye can detect 3 colors i.e Red, Green, Blue. So, the colored image is made up of three channels i.e RGB or BGR(in reverse). There are other color spaces like HSV, Lab, YCbCr, YUV, all of them are made up of three channels but channels differ in each type of color space. Grayscale image consist of only one channel i.e Grayshade having values of each pixel ranging from 0-255 of gray color.

Update your xaml code with following code.

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="270*"/>
            <RowDefinition Height="60"/>
        </Grid.RowDefinitions>
        <Image x:Name="cv_image" Grid.Row="0" />
        <StackPanel HorizontalAlignment="Center" Orientation="Horizontal" Grid.Row="1" Margin="15">
            <Button Content="Browse" Width="70" Click="Button_Click"></Button>
            <Border Width="20" />
            <TextBlock VerticalAlignment="Center">Convert to: </TextBlock>
            <Border Width="5" />
            <ComboBox x:Name="comboBox_colorspace" SelectedIndex="0" Width="80" SelectionChanged="ComboBox_SelectionChanged" HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
                <ComboBoxItem Content="RGB" />
                <ComboBoxItem Content="YCbCr" />
                <ComboBoxItem Content="Lab" />
                <ComboBoxItem Content="Grayscale" />
            </ComboBox>
        </StackPanel>
    </Grid>

In MainWindow.xaml.cs

C#
        Image<Bgr, Byte> image = null;
        //On browse button click
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog();
            openFileDialog.Filter = "All Image Files (*.png,*.jpg,*.bmp)|*.png;*.jpg;*.bmp";
            //open file dialog
            var result = openFileDialog.ShowDialog();
            if (result.Value == true)
            {
                //load image - selected file path
                image = new Image<Bgr, Byte>(openFileDialog.FileName);
                cv_image.Source = BitmapSourceConvert.ToBitmapSource(image);
                //set comboBox to default color space RGB
                comboBox_colorspace.SelectedIndex = 0;
            }
        }
        //if combox box selection changed - event handler
        private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var comboBox = (ComboBox)sender;
            if (comboBox == null || image == null)
                return;
            ConvertTo(((ComboBoxItem)comboBox.SelectedItem).Content.ToString());
        }
        //Convert to selected colorspace
        private void ConvertTo(string colorspace)
        {
            switch(colorspace)
            {
                case "RGB":
                    cv_image.Source = BitmapSourceConvert.ToBitmapSource(image.Convert<Bgr, Byte>());
                    break;
                case "Grayscale":
                    cv_image.Source = BitmapSourceConvert.ToBitmapSource(image.Convert<Gray, Byte>());
                    break;
                case "YCbCr":
                    cv_image.Source = BitmapSourceConvert.ToBitmapSource(image.Convert<Ycc, Byte>());
                    break;
                case "Lab":
                    cv_image.Source = BitmapSourceConvert.ToBitmapSource(image.Convert<Lab, Byte>());
                    break;
                default:
                    break;
            }
        }

On selection changed event of combo Box, image.Convert<[Color Space Name], [Type]>() method will convert the image into other selected color space.

*[Color Space Name] = Ycc, Hsv, Lab, Gray, Bgr and Type = Byte, int, double*

Result: (To grayscale Conversion)

Image 5

A little more coding...

Changing the color of patch in image.

As described above, RGB, YUV,HSV, Lab are 3-dimensional(3 Channels) colorspaces, whereas grayscale is 2-dimensional color space(1 Channel). If we want to change color of (let's say) first 5 rows of image, then replace color values of first 5 rows of 3 components of image.

//convert first pixel color of first channel to black
image.Data[0,0,0] = 0;

To assign green color to first pixel with 3 channels (Colored Image)

//get green color
Color G = Color.Green;

image.Data[0,0,0] = G.B;
image.Data[0,0,1] = G.G;
image.Data[0,0,2] = G.R;
private void ConvertToBlack(int rows)
        {
            for(int row=0;row<rows;row++)
            {
                //Iterate through channels of image-if Gray then 1, if colored then 3
                for (int channel = 0; channel < image.NumberOfChannels;channel++ )
                    for (int col = 0; col < image.Cols; col++)
                    {
                        image.Data[row, col, channel] = 0; //0 = black color value
                    }
            }
            cv_image.Source = BitmapSourceConvert.ToBitmapSource(image);
        }

The above code will convert given number of rows to black by iterating through columns and rows of three channels(for colored) or one channel(for grayscale) of image, assigning black value to each pixel.

Result of coloring 100 rows:

Image 6

Source code is provided. Hope you get the idea of setting up and using EmguCV basic functions in WPF. Incase of any query, feel free to comment. :)

Free advice: Work smarter not harder ;)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Student
Pakistan Pakistan
I prefer Smart work over hard work. With over 6+ months experience in django and android app development I have made a very good progress in web, desktop and mobile development. Eager to work in an environment where I can enhance my skills and do something innovative. I have solid understanding of programming languages and have ability to quickly learn new technologies.

Comments and Discussions

Discussions on this specific version of this article. Add your comments on how to improve this article here. These comments will not be visible on the final published version of this article.