65.9K
CodeProject 正在变化。 阅读更多。
Home

EmguCV 的 .NET 方法

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.25/5 (3投票s)

2015 年 2 月 25 日

CPOL

4分钟阅读

viewsIcon

32920

downloadIcon

307

EmguCV 初学者在 Visual Studio 中设置项目并运行第一个程序的完整指南

引言

本技巧面向对 C# 有些了解但对 EmguCV 一无所知的初学者。首先,EmguCV 是什么?EmguCV 是用 C#、C++、VB 和其他语言编写的一组库。它是否类似于 Matlab 或 OpenCV 等著名 API?不!

背景

简单来说,EmguCV 只是一个包装器,它从 C#、VB 等支持的语言调用 OpenCV 方法。与其他包装器不同,它不使用不安全的代码,并且完全用 C# 编写,这使得 EmguCV 比其他包装器更好、更高效。

要求

  1. C#
  2. Visual Studio(本技巧中使用 2013 版)
  3. EmguCV 库安装程序(链接,文件大小约 214MB,您可以使用最新版本)

Using the Code

通过安装程序安装 emguCV 库后,请转到**我的电脑 -> 属性 -> 高级系统设置 -> 高级 -> 环境变量**。在“系统变量”分组框中,选择“Path”并单击“编辑”。在文本框中,在文本末尾添加一个分号(**;**),然后添加 emguCV 库的路径(*X\emgucv\bin\x86*),其中 X =“您 EmguCV 库的安装目录”。单击“确定”进行确认。

在 **文件 -> 新建 -> 项目** 下创建一个新项目,然后从项目向导中选择 **WPF 应用程序**。

您需要三个文件才能开始使用 Emgu CV,它们位于 **“X\emgucv\bin\”** 目录下,其中 X =“您 EmguCV 库的安装目录”。

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

项目创建后,右键单击“**解决方案资源管理器**”中的“**引用**”,然后单击“**添加引用**”。在“添加引用”窗口中,浏览并选择上面列出的三个 DLL 文件(位于指定目录,请参阅上方),然后单击“确定”将它们添加到您的项目引用中。如果一切顺利,您的解决方案资源管理器应该如下所示

将以下引用添加到您的 *MainWindows.xaml.cs* 文件中,以包含 Emgu CV 引用。

using Emgu.CV;
using Emgu.Util;
using Emgu.CV.Structure;

并添加以下代码以显示图像。

**注意**:将 *System.Drawing.dll*(如果未包含)作为引用添加,方法是在“添加引用 -> 程序集 -> 勾选 `System.Drawing`”中找到它,然后单击“确定”。

将图像拖放到解决方案资源管理器(项目)中,然后右键单击以选择属性。将“生成操作”设置为“**内容**”,将“复制到输出目录”设置为“**仅较新文件复制**”,以便在构建项目时复制图像以在运行时使用。到目前为止,已添加环境变量和引用。

让我们运行您的思维(编码……)

好了!开始编码。

在 *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>

在 *MainWindow.xaml.cs* 中

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;
            }
        }
    }

代码很简单。在 XAML 文件中,有一个带有行的根网格。名为“`cv_image`”的图像位于第一行,第二个堆栈面板包含一个“`Browse`”按钮,用于打开文件,该按钮具有一个“`Click`”事件处理程序,该处理程序调用后台代码中的 `Button_Click` 事件。在 `Button_Click` 方法中,有一个 `OpenFileDialog`,其过滤器设置为图像扩展名。从对话框中选择图像后,`Image("Image File Name")` 方法将以指定的(**RGB**)格式加载图像。

处理 emgu.cv.cvinvoke 异常

如果您在构建时没有遇到 `emgu.cv.cvinvoke` 异常,则跳过此步骤。

Emgu CV 的当前版本支持 x86 和 x64 架构,您必须指定架构才能在 x64 上成功构建程序。要在 x86 和 x64 之间切换,您需要手动设置架构。

右键单击您的 **项目 -> 属性**,然后从左侧边栏选择“**生成**”。在“**平台目标**”组合框中,选择 x86 切换到 x86 架构,或 x64 切换到 64 位。(对于 x64,您可能需要 x64 emguCV 库,您可以从安装程序提取的库中复制。)

构建并运行您的项目。希望它能奏效。

结果

颜色空间转换

图像由称为像素的图像元素组成。人眼可以识别 3 种颜色,即 `Red`、`Green`、`Blue`。因此,彩色图像由三个通道组成,即 RGB 或 BGR(反序)。还有其他颜色空间,如 HSV、Lab、YCbCr、YUV,它们都由三个通道组成,但在每种颜色空间类型中,通道都不同。`Grayscale` 图像只包含一个通道,即 `Grayshade`,其中每个像素的值范围从 0-255 的灰色。

使用以下代码更新您的 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="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>

在 *MainWindow.xaml.cs* 中

        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;
            }
        }

在 `combobox` 的选择更改事件中,`image.Convert<[Color Space Name], [Type]>()` 方法会将图像转换为选定的其他颜色空间。

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

结果:(转换为灰度)

再来点编码……

更改图像中的斑块颜色

如上所述,RGB、YUV、HSV、Lab 是 3 维(3 通道)颜色空间,而 `grayscale` 是 2 维颜色空间(1 通道)。如果我们要更改图像的前 5 行(例如)的颜色,则需要替换图像 3 个通道的前 5 行的颜色值。

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

为具有 3 个通道(彩色图像)的第一个像素分配绿色

//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);
        }

上面的代码将通过遍历图像的三个通道(彩色)或一个通道(灰度)的列和行,将指定数量的行转换为黑色,并将黑色值分配给每个像素。

给 100 行着色后的结果

提供了源代码。希望您了解如何在 WPF 中设置和使用 EmguCV 的基本功能。如有任何疑问,请随时评论。 :)

免费建议:聪明地工作,而不是拼命工作;)

© . All rights reserved.