我熟悉在WPF图像框中显示Emgu图像的基本代码,所有源代码都在MainWindow.xaml.cs代码后面。
然而,我正试图将我的emgu相关代码,包括"ProcessFrame"事件/Queryframe片段,放入一个单独的静态方法类中,以便以后可以重用它们。我这样做是因为虽然我希望能够在以后的阶段从同一台相机抓取图像,但我也希望能够灵活地在不同的图像框中显示这些图像。这一步我有困难。
如果我可以动态地将图像框绑定到静态方法中的属性(并以编程方式启用/禁用该绑定),我认为这将解决我的问题。然而,我尝试采用的方法可能存在一些其他问题。任何代码/xaml的修改,非常感谢。
下面的代码可以工作,但是不令人满意,因为它迫使我将ProcessFrame方法捆绑到MainWindow代码中: XAML(工作):<Window x:Class="EmguWPF_Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Image Height="215" HorizontalAlignment="Left" Margin="62,66,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="224" />
</Grid>
</Window>
MainWindow代码片段(working):
//using statements etc
public partial class MainWindow : Window
{
private Image<Bgr, Byte> image;
private Capture capture = null;
private void button1_Click(object sender, RoutedEventArgs e)
{
InitializeCameras();
timer = new DispatcherTimer();
timer.Tick+=new EventHandler(ProcessFrame);
timer.Interval = new TimeSpan(0, 0, 0, 0, 10);
timer.Start();
}
private void InitializeCameras()
{
if (capture == null)
{
try
{
capture = new Capture(0);
}
catch // etc
}
}
private void ProcessFrame(object sender, EventArgs arg)
{
image = capture.QueryFrame();
image1.Source = BitmapSourceConvert.ToBitmapSource(image);
}
}
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(); //obtain the Hbitmap
BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
ptr,
IntPtr.Zero,
Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
DeleteObject(ptr); //release the HBitmap
return bs;
}
}
}
下面的代码是我所做的,但需要帮助:
XAML(和以前一样)
<Window x:Class="EmguWPF_Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Image Height="215" HorizontalAlignment="Left" Margin="62,66,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="224" />
</Grid>
</Window>
ViewModel Snippet(是的——可能对设计模式的试验太过雄心勃勃):
public ViewModel()
{
CaptureMethods.InitializeCameras();
timer = new DispatcherTimer();
timer.Tick += new EventHandler(CaptureMethods.ProcessFrame);
timer.Interval = new TimeSpan(0, 0, 0, 0, 10);
timer.Start();
}
CaptureMethods类,而不是像我希望的那样作为一个单独的类工作。您会注意到,我现在是在这个类中定义捕获字段,而不是在ViewModel类中:
class CaptureMethods
{
private static Capture capture = null;
public static void InitializeCameras()
{
if (capture == null)
{
try
{
capture = new Capture(0);
}
catch // etc
}
}
public static void ProcessFrame(object sender, EventArgs arg)
{
image = capture.QueryFrame();
image1.Source = BitmapSourceConvert.ToBitmapSource(image); // this is my problem line
}
}
// BitmapSourceConvert class not repeated here to avoid duplication.
谢谢!
我的建议是不要使用WPF图像盒,而是使用Emgu的ImageBox (Emgu. cv . ui .ImageBox)。它是一个更完整的控件,它被设计为与框架一起使用。
唯一的问题是这种类型的控件只适用于Windows窗体,但你总是可以用Emgu的图像框创建一个WinForms用户控件,并在WPF的WindowsFormsHost中使用它。
详细介绍一下celsoap7的答案,下面是生成的XAML的样子:
<Window x:Class="WPFEmguCV.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:emui="clr-namespace:Emgu.CV.UI;assembly=Emgu.CV.UI"
Title="MainWindow" Height="521" Width="1274">
<Grid>
<WindowsFormsHost>
<emui:ImageBox x:Name="CapturedImageBox" Width="409" Height="353" />
</WindowsFormsHost>
</Grid>
</Window>
我(和其他人)发现,将图像封送到UI线程需要太多的CPU,所以你最好像celsoap7建议的那样,把EmguCV ImageBox
放在WPF WindowsFormsHost
中。
遗憾的是,这可能会使您所询问的MVVM绑定类型与您设想的结构完全不同。