目录
介绍
假设知识
基本要求
首选方法
不太喜欢的方法
x64架构和EMGU.CV.Invoke异常
基本程序
更多的图像处理
一点关于转换图像
访问图像数据
DllNotFound异常及故障排除 0x8007007E
System.TypeInitializationException:
X64架构(更新)参见历史注释[2]
- 下载基本程序源 - 4.48 MB
- 下载更多图像处理源 - 4.49 MB
X86架构
- 下载基本程序 x86 源 - 5.04 MB
- 下载更多图像处理 x86 源 - 2.96 MB
介绍
以下文章旨在向EMGUcv新手展示如何逐步建立项目。此信息可在此处免费获得,但本文旨在使该过程更加用户友好。EMGU是OpenCV的C#包装器,它与其他包装器不同,因为它纯粹用C#编写并且不使用不安全的代码。EMGU向C#开发人员开放主要针对实时计算机视觉的编程函数OpenCV(开源计算机视觉库)库。OpenCV最初由Intel开发,现在由Willow Garage提供支持。
x86和x64架构的当前版本可在其Sourceforge网站上下载。
因为EMGU是 C++代码的包装器。使用了两种类型的动态链接库(DLL)。有EMGU语法的EMGU总是在名称中引用,而opencv则有所不同。设置第一个项目是许多新手的共同绊脚石,而且您并不孤单。
如果您已经下载了源代码,您需要阅读“基本程序”。如果您从EMGU提取文件夹中复制了一个示例,请查看EMGU.CV.Invoke异常和故障排除部分。
假设知识假设用户具有C#的基本经验并且可以生成新的C#项目。假设每个用户都下载了他们平台的最新更新,并从EMGU提取文件夹\EMGU.Examples\Hello World运行HelloWorld示例。
基本要求与任何C#库一样,有一些基本的DLL需要在您的项目中引用。启动一个新的C# Windows窗体应用程序并将其命名为您喜欢的名称。提到的所有DLL都在EMGU提取文件夹\bin中——您需要记住这一点。首先,您需要引用3个EMGU DLL。
- Emgu.CV.dll
- Emgu.CV.UI.dll
- Emgu.Util.dll
这可以通过右键单击您的项目名称或解决方案资源管理器中的References文件夹来完成。转到添加参考。
或者使用菜单项Project > Add Reference。当Add Reference窗口打开时,选择上面列出的DLL,然后单击OK。
现在,您将看到它们列在解决方案资源管理器窗口的References文件夹中。这三个DLL是前面提到的EMGU特定的C#库。仅这些将不允许您使用任何图像处理功能,因此请阅读本文的其余部分。
现在您需要以您将使用代码的任何形式的形式引用这些。您将使用的参考将取决于您在图像处理方面所做的工作。查看示例,这些将具有您需要的示例。为了让您开始,请将以下内容添加到后面的Form1.cs代码的顶部。
using Emgu.CV;
using Emgu.Util;
using Emgu.CV.Structure;
现在,对于更复杂的C++库,要加载、显示、访问图像数据并执行许多更简单的功能,您只需要两个文件。请注意,“220”是版本号——这将根据更新(opencv_core***.dll、opencv_imgproc***.dll)而改变。
- opencv_core220.dll
- opencv_imgproc220.dll
现在因为这些是封装的C++文件,所以您不能像使用EMGU文件那样引用它们。您需要将这些文件添加到您的项目中。这可以通过两种方式完成——在解决方案资源管理器中右键单击您的项目名称(这不是以“解决方案'您的项目名称'......”开头的那个,而是这个下面的那个)。使用标准打开文件对话框转到添加>现有项目。选择上面的两个文件,以防您忘记它们位于EMGU提取文件夹\bin中。
提示:如果看不到.dll,请确保将右下角的文件过滤器更改为Executable Files。
您现在可以在解决方案资源管理器窗口中查看您的文件。您将需要更改它们的属性,因此通过按住Ctrl键并左键单击它们来选择它们(或者,您可以单独执行此操作)。现在查看属性窗口,您将看到六个字段,其中两个将填充内容。您对复制到输出目录感兴趣。将其从“不复制”更改为“始终复制”。
如果您使用的是x64编译,请转到x64部分并确保将项目设置为编译为x64架构,而不是准备好开始图像处理。这是首选方法的原因是,现在,如果您从Debug更改为Release,这些文件将始终可供您的程序使用,并且不会发生错误。跳转到阅读和显示图像部分基本程序开始。
不太喜欢的方法虽然没有提供,但这通常是最简单的,如果您有一个复杂的项目架构,这可以防止解决方案资源管理器看起来非常混乱。只需在Windows资源管理器中导航到EMGU提取文件夹\bin,然后将相关的DLL文件、opencv_core220.dll 和opencv_imgproc220.dll复制到您的项目bin\Debug文件夹或bin\Release文件夹。这将随着x64版本而改变,因为它将是bin\x64\Debug文件夹或替代Release文件夹。
虽然这里的好处不是很清楚,但想象一下,如果您需要所有opencv DLL文件,那么您将在解决方案资源管理器中拥有额外的34个文件,但是这种情况很少见。
x64架构和EMGU.CV.Invoke异常如果您正在运行x64系统或为它们设计,则必须下载单独的DLL。构建项目的步骤是相同的,但是您需要更改一个额外的构建参数。在解决方案资源管理器中右键单击您的项目文件,然后选择底部的“属性”。从该窗口右侧的功能区栏中选择“构建”选项卡。平台目标将有一个选项:使用下拉菜单,将其从x86更改为x64。
提示:如果您使用的是Visual Studio的Express版本,您可能看不到x64选项。在这种情况下,请转到菜单选项Tools > Options。在此窗口中,使用左侧的箭头展开和折叠选项。选择“项目和解决方案”并选中显示高级构建配置复选框。
如果没有正确完成,这将允许编译运行。一旦您访问任何EMGU代码,就会通过带有'InnerException' “尝试加载格式不正确的程序......”的异常来引发异常'EMGU.CV.Invoke'。
基本程序为帮助您入门,我们提供了一个加载图像并将其显示在图片框中的简单程序,以及一些更高级的程序,它将展示如何访问图像数据和在图像类型之间进行转换。
目前只有x64版本可用,很快就会提供x86。
如果您已经下载了示例代码,您将首先收到3个未找到引用的警告。展开解决方案资源管理器中的References文件夹,删除带有黄色警告图标的3并为它们添加新的引用,其步骤可在基本要求部分中找到。
主窗体中添加了一个按钮项和一个picturebox项。它们的默认名称没有更改。当我们单击该按钮时,我们希望打开一个文件对话框选择和图像并将其显示在picturebox中。
双击按钮并添加以下代码:
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog Openfile = new OpenFileDialog();
if (Openfile.ShowDialog() == DialogResult.OK)
{
Image My_Image = new Image(Openfile.FileName);
pictureBox1.Image = My_Image.ToBitmap();
}
}
代码很简单,一个叫做' Openfile'的OpenFileDialog 用来选择和图像文件。然后将该图像读入名为“My_Image”的颜色对象Image中。通过分配给picturebox的Image属性来显示图像。这需要Bitmap通过调用'My_Image'的.ToBitmap()函数来实现。
一旦在设置项目时采取了正确的过程,这将非常简单。该项目的替代品Picturebox可通过EMGU.CV.UI库获得,并在示例中使用。如果您希望使用它,请访问http://www.emgu.com/wiki/index.php/Add_ImageBox_Control了解如何将此控件添加到Visual Studio。
更多的图像处理稍微高级一点的源代码项目将具有与提供的基本程序中描述的相同的警告。引用将需要替换。在这个程序中,有一个演示将Image从colour到转换greyscale,并访问单个像素的Data。虽然抑制图像光谱数据的方法不是最有效的,但它是访问图像Data属性的一个很好的例子。
一点关于转换图像EMGU中的图像转换可能很复杂。在示例程序中,将Bgr彩色图像转换为Gray灰度图像。
Image gray_image = My_Image.Convert();
但是,您最终会希望使用不同深度(Tdepth)的图像而不是Byte。这种方法的问题是每次调用只能转换一次深度或颜色。假设我们希望从Image转换为Image,您必须使用以下语法。
Image gray_image = My_Image.Convert();
Image gray_image = My_Image.Convert();
//or alternatively in one line
Image gray_image = My_Image.Convert().Convert();
//alternatively
Image gray_image = My_Image.Convert().Convert();
有几种方法可以访问图像数据并为其分配值。有两种方法可用,使用图像数据属性的直接访问更远程访问。两者都在这里演示。请注意,在访问Data属性时尊重图像光谱深度很重要。灰度图像的深度为1,因此将被称为[x,y,0],而彩色图像的深度为3,[x,y,0], [x,y,1] & [x, y,2]分别代表(Bgr)蓝色、绿色和红色光谱。
假设我们希望为位置[0,0]处的像素分配一个值。使用更简单的远程方法,我们可以使用:
//Colour Image
My_Image[0, 0] = new Bgr(Color.Red);
//Gray Image
gray_image[0, 0] = new Gray(200);
或者我们使用Data属性:
//Colour 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);
所以写入一个像素是相当简单的,但是读取一个像素值呢?
//Colour Image
Bgr my_Bgr = My_Image[0, 0];
//Gray Image
Gray my_Gray = gray_image[0, 0];
现在在许多情况下,您不想使用“Bgr”或“Gray”,因此转换它们很重要。
//BGR to Color
Color my_colour = Color.FromArgb((int)value.Red, (int)value.Blue, (int)value.Green);
//Gray to int
int my_intensity = (int) my_Gray.Intensity;
您会注意到每个值都被转换为整数以允许数据丢失,这是因为强度自然存储为double。但是在这种情况下,更简单的方法是访问Image Data属性。如果您希望使用图像数据,则不需要不断地在Gray和整数之间进行转换等。您可以直接访问图像Data并使用它。
//Colour
Color my_colour = Color.FromArgb(My_Image.Data[0, 0, 0],
My_Image.Data[0, 0, 1], My_Image.Data[0, 0, 2]);
//Gray Image
int my_intensity = gray_image.Data[0, 0, 0];
在循环中处理图像Data时,使用起来要简单得多。要检查如何实现循环,请下载Little More Image Processing源代码。
DllNotFound异常及故障排除 0x8007007E现在在某个时候,您将收到错误消息“无法加载 DLL......(来自HRESULT: 0x8007007E的异常)”。您需要阅读下面红色圈出的Message部分。
如果异常是EMGU.CV.Invoke异常,则您的构建可能没有针对正确的平台。有关详细信息,请参阅有关x64架构的部分。
现在,如果您已经进入高级图像处理方法,或者只是将示例复制到EMGU提取文件夹之外的其他位置,您可能会看到以下错误之一:
Unable to load DLL 'opencv_highgui220': The specified module could not be found.
(Exception from HRESULT: 0x8007007E)
通常是在您尝试从网络摄像头获取图像时引起的。解决这个问题非常简单。如基本要求部分所述,您需要将opencv_highgui220.dll复制到输出目录,或者将文件作为现有文件添加到项目中,然后将其属性“复制到输出目录”更改为“永远复制”。如果需要,请查看本节以供参考。
Unable to load DLL 'cvextern': The specified module could not be found.
(Exception from HRESULT: 0x8007007E)
这个错误有更多的实质性解决方案。cvextern.dll错误不能通过简单的添加这个文件来修复,事实上,这个文件需要下面列出的所有文件才能正确执行。如基本要求部分所述,您需要将文件复制到输出目录,或者将文件作为现有文件添加到项目中,然后将它们的每个属性“复制到输出目录”更改为“总是复制”。如果需要,请查看本节以供参考。
请注意,“220”是版本号——这将根据更新而改变。
- cudart64_32_16.dll
- cufft64_32_16.dll
- cvextern.dll
- npp64_32_16.dll
- opencv_calib3d220.dll
- opencv_contrib220.dll
- opencv_core220.dll
- opencv_features2d220.dll
- opencv_flann220.dll
- opencv_gpu220.dll
- opencv_highgui220.dll
- opencv_imgproc220.dll
- opencv_legacy220.dll
- opencv_ml220.dll
- opencv_objdetect220.dll
- opencv_video220.dll
任何其他无法加载DLL '...' 错误都可以通过尝试相同的过程并将相关列出的DLL加载到您的项目中来修复。如果您仍然遇到困难,请随时向社区寻求帮助。
System.TypeInitializationException:OpenCV不支持从 Image到Image的转换
其中*是相关的图像深度或数据类型。
此错误在2.3.*及更高版本中引发,是由于程序无法访问opencv_imgproc***.dll或opencv_core***.dll即使它们存在于输出“bin”目录中。
有两种解决方案,将它们添加到项目中并将它们的属性设置为始终复制,因为它们是两个关键文件。或者通过将Bin文件夹中的当前副本替换为新副本也可以解决问题。
如果这两种方法都失败了,那么构建可能存在问题,因此请从SourceForge下载新副本并重试。
https://www.codeproject.com/Articles/257502/Creating-Your-First-EMGU-Image-Processing-Project