EmguCV: BitmapSource не обновляется в графическом интерфейсе после события PropertyChanged: - PullRequest
0 голосов
/ 17 сентября 2018

Я хочу просто захватить и отобразить изображение с камеры на моем виде, обновляемое каждую секунду. Однако контейнер изображения, связанный с моим Bitmapsource CurrentFrame, остается пустым во время выполнения. Это мой код до сих пор (в основном взят из ответа другой ветки с похожей темой :

public class CameraViewModel : ViewModelBase
{
    public CameraViewModel()
    {
        StartVideo();
    }

    private DispatcherTimer Timer { get; set; }

    private VideoCapture Capture { get; set; }

    private BitmapSource currentFrame;
    public BitmapSource CurrentFrame
    {
        get { return currentFrame; }
        set
        {
            if (currentFrame != value)
            {
                currentFrame = value;
                SetProperty(ref currentFrame, value);
            }
        }
    }

    private void StartVideo()
    {
        //CurrentFrame = new BitmapImage(new Uri("C:\\Users\\Johannes\\Pictures\\Camera Roll\\asdf.bmp")) as BitmapSource;
        Capture = new VideoCapture();
        Timer = new DispatcherTimer();
        //framerate of 10fps
        Timer.Interval = TimeSpan.FromMilliseconds(1000);
        Timer.Tick += new EventHandler(async (object s, EventArgs a) =>
        {
            //draw the image obtained from camera
            using (Image<Bgr, byte> frame = Capture.QueryFrame().ToImage<Bgr, byte>())
            {
                if (frame != null)
                {
                    CurrentFrame = ToBitmapSource(frame);
                }
            }
        });
        Timer.Start();
    }

    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, BitmapSizeOptions.FromEmptyOptions());
            DeleteObject(ptr); //release the HBitmap
            return bs;
        }
    }

    /// <summary>
    /// Delete a GDI object
    /// </summary>
    [DllImport("gdi32")]
    private static extern int DeleteObject(IntPtr o);

}

Несколько вещей для лучшего понимания:

  1. Класс ViewModelBase работает и обрабатывает События INotifyPropertyChange.
  2. Привязка данных работает! Я проверил это, назначив bmp-файл CurrentFrame в StartVideo() Метод - и изображение отображается в графическом интерфейсе во время выполнения.
  3. Метод SetProperty() срабатывает каждые 1000 мсек, как и ожидалось.
  4. Когда я назначил файл для CurrentFrame, чтобы проверить привязку данных, я увидел, что это, кажется, типа BitmapImage - может быть, там проблема лежит ?? Однако из информации, которую я мог собрать, BitmapSource должен работать и показываться в представлениях WPF ...
  5. Захваченный кадр с камеры не пустой. Я пытался написать это непосредственно в файл изображения, и он показывает правильное содержимое как ожидается.

Edit: Для полноты здесь также ответственная часть представления:

<UserControl.Resources>
    <ResourceDictionary>
        <local:CameraViewModel x:Key="vm" />
    </ResourceDictionary>
</UserControl.Resources>

<Grid DataContext="{StaticResource vm}">
    <Image Source="{Binding CurrentFrame}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Grid>

Edit2: Ссылка на репозиторий Github для просмотра кода

1 Ответ

0 голосов
/ 17 сентября 2018

Вы не должны устанавливать

currentFrame = value;

перед звонком

SetProperty(ref currentFrame, value);

потому что чек

if (Object.Equals(storage, value)) return;

всегда будет верным.

Реализуйте свойство следующим образом:

public BitmapSource CurrentFrame
{
    get { return currentFrame; }
    set { SetProperty(ref currentFrame, value); }
}
...