0

すべてのソース コードが MainWindow.xaml.cs コード ビハインドにある場合に、WPF イメージ ボックスに Emgu イメージを表示するための基本的なコードに精通しています。

ただし、後で再利用できるように、「ProcessFrame」イベント/クエリフレーム スニペットを含む Emgu 関連のコードを静的メソッドの別のクラスに配置しようとしています。これを行っているのは、後の段階で同じカメラから画像を取得できるようにしたい一方で、それらの画像を別の画像ボックスに表示する柔軟性も必要だからです。このステップに問題があります。

画像ボックスを静的メソッドのプロパティに動的にバインドできれば (また、そのバインドをプログラムで有効/無効にできれば)、問題は解決すると思います。ただし、私が取ろうとしているアプローチには他の問題があるかもしれません。コード/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 スニペット (はい - デザイン パターンを試すには野心的すぎるかもしれません):

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.

ありがとう!

4

2 に答える 2

2

ここで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 が多すぎることを発見しましImageBoxWindowsFormsHost

悲しいことに、あなたが求めている MVVM バインディングの種類は、あなたが想定している構造とはまったく異なるものになる可能性があります。

于 2013-10-12T15:33:59.197 に答える
2

私の提案は、WPF Image Box ではなく、Emgu の ImageBox (Emgu.CV.UI.ImageBox) を使用することです。これはより完全なコントロールであり、フレームワークで使用するように設計されています。

唯一の問題は、コントロールのタイプが Windows フォームでのみ機能することですが、いつでも Emgu のイメージ ボックスを使用して WinForms ユーザー コントロールを作成し、WindowsFormsHost 内の WPF で使用できます。

于 2013-04-30T10:20:43.770 に答える