文章转自:http://www.cnblogs.com/iacocca/archive/2011/08/18/2144741.html
很多使用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了!原生的就是好用,速度很令人满意。