Search code examples
c#wpfemgucv

Emgu.cv binding failure in WPF


I'm trying to capture video from camera and display in c# WPF form. But image dont show up when i start the program. Also debugger gives me no exception it's just running. I m debugging and i see the CapturedImage property is taking the data as supposed to be. It might be they work in the different threads. But i cant figure out. So, HELP ME,

I'm binding a ImageSource type property. As you can see,

public class VideoCapturing : INotifyPropertyChanged
{
    private ImageSource capturedImage;
    public ImageSource CapturedImage
    {
        get { return capturedImage;  }
        set { capturedImage = value; OnPropertyChanged("CapturedImage"); }
    }

Also capturing code is here,

public void run()
    {
        if (cap.capture == null)
        {
            capture = new Emgu.CV.VideoCapture(0);
            CurrentFrame = new Mat();
             
        }
        capture.ImageGrabbed += VideoCapture_ImageGrabbed;
        capture.Start();
       
    }
private void VideoCapture_ImageGrabbed(object sender, EventArgs e) // runs in worker thread
    {
       capture.Retrieve(CurrentFrame);
       CapturedImage = ImageSourceFromBitmap(CurrentFrame.ToImage<Emgu.CV.Structure.Bgr, byte>().ToBitmap()); 
    } 
} // VideoCapturing class ends.

here is the xaml part for binding,

<Grid>
    <Image x:Name="img" Source="{Binding CapturedImage}"></Image> 
</Grid> 

This is the mainwindow.xaml.cs,

public MainWindow()
    {
        InitializeComponent(); 
        VideoCapturing VideoCapture = new VideoCapturing();
        this.DataContext = VideoCapture ;
        VideoCapture.run();
    }

Solution

  • There is a typo when you call OnPropertyChanged(). "CaptureImage" but it should be "CapturedImage".

    public ImageSource CapturedImage
    {
        get { return capturedImage;  }
        set { capturedImage = value; OnPropertyChanged("CapturedImage"); }
    }
    

    In MainWindow you should call VideoCapture.run() instead of capture.run().

    Because of VideoCapture_ImageGrabbed runs in worker thread you have set CapturedImage on UI thread by calling Dispatcher.BeginInvoke.

    private void VideoCapture_ImageGrabbed(object sender, EventArgs e)
    {
        capture.Retrieve(CurrentFrame);
        Application.Current.Dispatcher.BeginInvoke(new Action(() =>
        {
            CapturedImage = ImageSourceFromBitmap(CurrentFrame.ToImage<Emgu.CV.Structure.Bgr, byte>().ToBitmap()); 
        }));
    }