在WPF中使用Emgu加载Image<,>图像的两种方法

很多使用c#平台做图像处理的朋友都是因为要使用WPF而不得不放弃OpenCV而选择使用了Emgu。Emgu这个工具吧,由于才接触,对于OpenCV的封装好坏我不好评论,但有一点可以肯定的是,网上可以搜索的资料太少了,很多东西都需要自己研究api文档,看源代码。遇到了问题也基本上只能靠自己解决。真是魂淡啊……喷……

(↑↑↑↑以上纯属吐槽↑↑↑↑)

由于手上项目的原因,需要捕获摄像头,对摄像头得图像进行实时处理,并在窗口里显示出来。窗口是基于WPF的。WPF中使用过得能载图像控件就是一个Image。通过Emgu的capture函数,我们获得的图像是Image(Of TColor, TDepth)。很遗憾,Image控件是不能加载Image(Of TColor, TDepth)对象的。。

仔细研究了一下api文档,Image(Of TColor, TDepth)类有一公共属性,是获得该对象的Bitmap。而Image控件是可以加载BitmapImage的。这两个之间是互相转换的。附上转换函数(转载自 http://blog.sina.com.cn/s/blog_6e6941e10100n2yn.html, 感谢分享!):

public class GetBitmpIamge
{
public static BitmapImage BitmapToBitmapImage(Bitmap bitmap)
{
Bitmap bitmapSource
= new Bitmap(bitmap.Width, bitmap.Height);
bitmapSource.MakeTransparent();
int i, j;
for (i = 0; i < bitmap.Width; i++)
for (j = 0; j < bitmap.Height; j++)
{

Color pixelColor
= bitmap.GetPixel(i, j);
Color newColor
= Color.FromArgb(pixelColor.R, pixelColor.G, pixelColor.B);
if (newColor == Color.FromArgb(255, 0, 0, 0))
{
newColor
= Color.FromArgb(255, 255, 255, 255);
}
bitmapSource.SetPixel(i, j, newColor);
}
MemoryStream ms
= new MemoryStream();
bitmapSource.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
BitmapImage bitmapImage
= new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource
= new MemoryStream(ms.ToArray());
bitmapImage.EndInit();
return bitmapImage;
}
}

这样的确可以解决问题,图像可以很简单加载上。但使用以后你会发现这个转换的速度是完全不能满足实时的,非常的慢,更不用说还要处理了。当然,如果对于速度要求不是那么高的话,这个方法是完全可行的,而且是我现在发现最省事的方法。

既然不能实时,那就只能另外想办法了。其实Emgu中有提供一个ImageBox的控件,封装在Emgu.CV.UI,它可以直接加载Image<,>图像。但问题是这个控件只支持Windows Form,不支持WPF。所以我们需要在WPF平台上加载Windows Form,然后再加载ImageBox的控件。

大家可以先参考如何在WPF中加载Windows Form控件(http://www.cnblogs.com/iacocca/archive/2011/08/18/2144640.html)。这篇文章中控件是加载的button,而我们需要加载的是ImageBox。这里我们需要修改两个地方:

xmlns:WinFormControls="clr-namespace:Emgu.CV.UI;assembly=Emgu.CV.UI"
<WindowsFormsHost x:Name="cam_winform" Margin="1,0,-1,0">
<WinFormControls:ImageBox x:Name="cam_ibox" FunctionalMode="Minimum"/>

</WindowsFormsHost>

第二段中的FunctionalMode属性是设置ImageBox需不需要扩展功能的,比如拖动放大缩小,右键等功能。如果需要的话,就把这句去掉就好了。如果只想显示图像,想自定义一些鼠标响应的话我建议保留这句。

这样的话就将ImageBox嵌入到WPF中了。然后直接用ImageBox.image加载图像就ok了!原生的就是好用,速度很令人满意。

posted @ 2011-08-18 16:09  Iacocca Yan  阅读(3809)  评论(2编辑  收藏  举报