【问题标题】:WPF, Displaying Emgu Image, using BindingWPF,显示 Emgu 图像,使用绑定
【发布时间】:2013-10-12 23:33:59
【问题描述】:

当所有源代码都在 MainWindow.xaml.cs 代码隐藏中时,我熟悉在 WPF 图像框中显示 Emgu 图像的基本代码。

但是,我试图将与 Emgu 相关的代码(包括“ProcessFrame”事件/Queryframe sn-p)放入单独的静态方法类中,以便以后可以重用它们。我这样做是因为虽然我希望能够在稍后阶段从同一个相机抓取图像,但我也希望能够灵活地在不同的图像框中显示这些图像。我在这一步遇到问题。

如果我可以将图像框动态绑定到静态方法中的属性(并以编程方式启用/禁用该绑定),我认为这将解决我的问题。但是,我尝试采用的方法可能存在其他问题。非常感谢任何代码/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 代码片段(工作):

//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 design-patterns binding emgucv


    【解决方案1】:

    我的建议是不要使用 WPF Image Box,而是使用 Emgu 的 ImageBox (Emgu.CV.UI.ImageBox)。它是一个更完整的控件,旨在与框架一起使用。

    唯一的问题是这种类型的控件仅适用于 Windows 窗体,但您始终可以使用 Emgu 的图像框创建一个 WinForms 用户控件,并在 WindowsFormsHost 内的 WPF 中使用它。

    【讨论】:

      【解决方案2】:

      稍微扩展一下celsoap7's answer,下面是生成的 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>
      

      我 (and others) 发现将图像编组到 UI 线程会占用太多 CPU,因此您最好使用 celsoap7 suggests 并将 EmguCV ImageBox 放入 WPF WindowsFormsHost 中。

      遗憾的是,这可能会使您询问的那种 MVVM 绑定与您设想的结构完全不同。

      【讨论】:

        猜你喜欢
        • 2021-04-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-21
        • 1970-01-01
        • 2015-09-25
        相关资源
        最近更新 更多