EmguCV 的 .NET 方法
EmguCV 初学者在 Visual Studio 中设置项目并运行第一个程序的完整指南
引言
本技巧面向对 C# 有些了解但对 EmguCV 一无所知的初学者。首先,EmguCV 是什么?EmguCV 是用 C#、C++、VB 和其他语言编写的一组库。它是否类似于 Matlab 或 OpenCV 等著名 API?不!
背景
简单来说,EmguCV 只是一个包装器,它从 C#、VB 等支持的语言调用 OpenCV 方法。与其他包装器不同,它不使用不安全的代码,并且完全用 C# 编写,这使得 EmguCV 比其他包装器更好、更高效。
要求
- C#
- Visual Studio(本技巧中使用 2013 版)
- 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
处理 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 的基本功能。如有任何疑问,请随时评论。 :)
免费建议:聪明地工作,而不是拼命工作;)