Как минимизировать отставание от живого потока, используя OpenCV / EmguCV WPF - PullRequest
0 голосов
/ 15 января 2020

Я использую EmguCV для прямой трансляции с веб-камеры высокого разрешения. (Full HD) Проблема в том, что в видео есть значительное отставание. Я сравнил его с приложением Windows для камеры, и мое приложение намного задерживается.

Вот фрагмент кода, который я использую, чтобы получить прямую трансляцию и показать ее на холсте. Мне интересно, если я упускаю что-то важное, чтобы минимизировать отставание. Если кто-то имеет опыт, пожалуйста, помогите мне.

void init_camera()
{
    m_capture= new VideoCapture(0);
    m_capture.ImageGrabbed += ProcessFrame;
}

void ProcessFrame()
{
    if (m_capture_in_progress)
        return;
    m_capture_in_progress = true;
    if (m_capture != null && m_capture.Ptr != IntPtr.Zero)
    {
        m_capture.Retrieve(m_frame, 0);
        if (m_frame != null && m_frame.Bitmap != null)
        {
            if (IsRecording && m_video_writer != null && m_video_writer.IsOpened)
            {
                try
                {
                    m_video_writer.Write(m_frame);
                }
                catch (Exception ex)
                {
                    log(ex.Message + "\n" + ex.StackTrace);
                }
            }

            this.Dispatcher.Invoke(() =>
            {
                using (var stream = new MemoryStream())
                {
                    m_frame.Bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
                    using (var outstream = new MemoryStream(stream.ToArray()))
                    {

                        BitmapImage bitmap = new BitmapImage();
                        bitmap.BeginInit();
                        bitmap.StreamSource = new MemoryStream(stream.ToArray());
                        bitmap.CacheOption = BitmapCacheOption.OnLoad;
                        bitmap.EndInit();

                        ui_canvas.Background = new ImageBrush(bitmap);
                    }
                };
            });
        }
    }
    m_capture_in_progress = false;
}


Ответы [ 2 ]

0 голосов
/ 28 января 2020

Используйте элемент управления Image, но установите его свойство Source в WriteableBitmap вместо BitmapImage. Затем заблокируйте растровое изображение, скопируйте пиксельные данные из вашего EmguCV Mat в буферный буфер WriteableBitmap, вызовите метод AddDirtyRect и, наконец, разблокируйте растровое изображение. Последний вызов разблокировки в сочетании с AddDirtyRect вызовет перерисовку изображения пользовательского интерфейса.

Преимущества:

  • Он не генерирует новый объект BitmapImage каждый раз, когда вы хотите нарисовать новый кадр.
  • Вы копируете данные пикселей только один раз

Ваши данные копируются, кодируются и декодируются часто:

 // Copies and encodes pixel data to jpeg stream
 m_frame.Bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);

 // Copies jpeg stream
 using (var outstream = new MemoryStream(stream.ToArray()))
 {

     BitmapImage bitmap = new BitmapImage();
     bitmap.BeginInit();

     //Copies jpeg stream again
     bitmap.StreamSource = new MemoryStream(stream.ToArray());

     bitmap.CacheOption = BitmapCacheOption.OnLoad;

     // Triggers jpeg stream decoding
     bitmap.EndInit();
     ui_canvas.Background = new ImageBrush(bitmap);
  }
0 голосов
/ 15 января 2020

OP ссылается на какие-то лаги, когда рисует поток захвата камеры из EmguCv в элемент управления canvas wpf. OP также заявляет, что задержка исчезает при потоковой передаче с помощью стороннего программного обеспечения.

Это вызвано низкой производительностью кода OP.

После просмотра примера размещенного кода я бы предложил следующие улучшения:

  1. Увеличение частоты кадров в секунду из параметров EmguCV

Возможно, ваше устройство поддерживает более высокие скорости кадров в секунду, попробуйте увеличить это значение.

Рисование растрового изображения над другим элементом управления, например image

Насколько я знаю, рисование растрового изображения над canvas медленнее, чем при рисовании над image контроль. Хорошим решением было бы перекрыть оба элемента управления, чтобы вы могли закрасить рамки поверх image и нарисовать фигуры поверх canvas, поскольку они хорошо перекрываются.

Очистка метода рендеринга

Сохраняйте простоту и старайтесь избегать такого количества управляющих структур, когда находитесь внутри критического программного блока. Особенно в программных блоках, которые выполняются, когда внешние устройства запускают событие.

Исправление возможной блокировки программы

Насколько я вижу, вы блокируете событие ProcessFrame с помощью переменной bool с именем m_capture_in_progress, которая установлена ​​в true пока вы рисуете рамку, и она освобождается после завершения рисования. Это может привести к тому, что следующие входящие кадры не будут окрашены, поскольку метод все еще заблокирован предыдущим кадром. Это может привести к снижению производительности, так как многие кадры теряются и не окрашиваются.

...