繁体   English   中英

如何使用 OpenCV/EmguCV WPF 最大限度地减少实时流的延迟

[英]How to minimize the lag from the live stream using OpenCV/EmguCV WPF

我正在使用 EmguCV 从高分辨率网络摄像头获取实时流。 (全高清)问题在于视频中存在明显滞后。 我与 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;
}


OP 在从 EmguCv 将相机捕获流绘制到canvas wpf 控件中时指的是某种滞后。 OP 还指出,使用第三方软件流式传输时,滞后会消失。

这是由 OP 代码的低性能引起的。

观看发布的代码示例后,我建议进行以下改进:

  1. 从 EmguCV 参数提高 FPS 率

也许您的设备支持更高的 fps 速率,请尝试增加此值。

  1. 在另一个控件(如image绘制位图

据我所知,在canvas绘制位图比在image控件上绘制要慢。 一个很好的解决方案是重叠两个控件,这样您就可以在image绘制框架并在canvas绘制您的形状,因为它们重叠得很好。

  1. 清理渲染方法

当您处于关键程序块中时,请保持简单并尽量避免使用过多的控制结构。 特别是在外部设备触发事件时执行的程序块中。

  1. 修复可能的程序锁定

据我所知,您正在使用名为m_capture_in_progress的 bool 变量锁定ProcessFrame事件,该变量在您绘制框架时设置为 true,并在您完成绘图后释放。 这可能会导致下一个传入帧未绘制,因为该方法仍被前一帧阻止。 这可能会导致性能低下的问题,因为许多帧丢失且未绘制。

使用 Image 控件,但将其 Source 属性设置为WriteableBitmap而不是 BitmapImage。 然后锁定位图,将 EmguCV Mat 中的像素数据复制到 WriteableBitmap 的后台缓冲区,调用 AddDirtyRect 方法,最后解锁位图。 最后的解锁调用与 AddDirtyRect 结合将触发 UI 图像的重绘。

优点:

  • 每次要绘制新帧时,它不会生成新的 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);
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM