无法使用 EMGU CV 连续从 RTSP 流中抓取图像

Unable to use EMGU CV to grab images from RTSP stream continuously

我正在尝试使用 C# Windows Forms 应用程序从网络摄像机的 RTSP 流中获取图像。我正在使用 EMGU CV 连续捕获流,但 RTSP Steam 在几秒钟后停止,然后 imageGrabbedEvent 永远不会触发。

我的目的很简单:从相机中获取每一帧并进行分析。

我正在使用 IP 地址为 192.168.1.64 的 HIKVision IP 摄像机 (DS-2CD2683G1-IZ) 在端口 554 上流式传输 RTSP(这是许多 Hikvision IP 摄像机的默认 IP 地址和端口号)

DateTime LastTimeImageGrabReinitialised = new DateTime();


public void InitializeCameraEMGUStream()
        {
            //added a datetime to the URL as recommended by another answer but it didnt help.
            VideoCapture myVideoCapture = new VideoCapture("rtsp://admin:mysecretpassword@192.168.1.64:554/ch1/main/av_stream?"+DateTime.Now.ToString());
            myVideoCapture.ImageGrabbed += imageGrabbedEvent;
            myVideoCapture.Start();

            LastTimeImageGrabReinitialised = DateTime.Now;

        }

private void imageGrabbedEvent(object sender, EventArgs e)
        {
            lastTimeImageGrabbed = DateTime.Now;
            try
            {
                Mat m = new Mat();
                myVideoCapture.Retrieve(m);
                LatestAcquiredImage = m.ToImage<Bgr, byte>().Bitmap;
                pictureBox.Image = m.ToImage<Bgr, byte>().Bitmap;
                imgEntrada = m.ToImage<Bgr, byte>();
            }
            catch (Exception Ex)
            {



            }

            //I tried adding some logic to reinitialize the stream after a few hundred milliseconds, 
            //but it seems the reinitialization takes a while to obtain a clear image and many frames cannot be read.
            if((DateTime.Now- LastTimeImageGrabReinitialised).TotalMilliseconds>200)
            {

                myVideoCapture.Start();
                LastTimeImageGrabReinitialised = DateTime.Now;
            }

        }


我浏览了几个在线可用的答案,但找不到让流保持活跃的确定方法。如果能在这方面提供任何帮助,我将不胜感激。

仅供参考:我已经尝试过的:

  1. 我尝试每隔一段时间重新初始化 VideoCapture,但速度很慢,许多初始帧都是 noisy/unclear 图像。

  2. 我已经尝试使用 VLC.Dotnet 到 运行 RTSP 流,流工作得很好但是抓取图像并将其转换为图像非常慢,主要是因为 VLCControl.TakeSnapshot() 将文件保存在磁盘上。充其量,这会消耗超过 500 毫秒,并且在此期间会丢失许多帧。

  3. 我还尝试使用 RTSPClientSharp,在使用它时,imageGrabbed 事件会定期触发,但我无法显示解码图像。

  4. 我尝试使用 HTTP 从相机获取图像,但是,每张图像需要超过 600 毫秒才能到达,同时相机不会接受任何其他连接请求,因此再次出现许多帧迷路了。

我在 RTSP 流中遇到了类似的问题,我通过使用 QueryFrame 和超时而不是 ImageGrabbed 事件解决了它,所以这可能值得用你的相机试试。这是抓取帧的主要处理循环,我没有观察到任何意外丢帧我只看到 QueryFrame 超时,原因是相机断电:

try
{
    if (!cameraOpened)
    {
        LogMessage("Opening camera stream...");
        var openTask = Task.Run(() => capture = new Capture("rtsp://admin:redacted@10.0.0.22:554"));
        if (await Task.WhenAny(openTask, Task.Delay(20000)) != openTask)
        {
            LogMessage("Unable to open camera stream");
        }
        else
        {
            LogMessage("Camera stream opened");
            cameraOpened = true;
        }
    }
    if (cameraOpened)
    {
        var captureTask = Task.Run(() => inputFrame = capture.QueryFrame());
        if (await Task.WhenAny(captureTask, Task.Delay(5000)) != captureTask)
        {
            LogMessage("Camera connection lost");
            cameraOpened = false;
        } 
        else
        {
            if (inputFrame != null && !inputFrame.IsEmpty)
            {
                frameQueue.Enqueue(inputFrame);
            }
        }
    }
} catch (Exception ex)
{
    LogMessage(ex.Message);
    Thread.Sleep(5000);
}

frameQueue 声明如下,处理发生在一个单独的线程中,这也可能有所帮助。我很久以前写了代码,而不是我现在使用 ConcurrentQueue class.

Queue myQ = new Queue();
Queue frameQueue = Queue.Synchronized(myQ);

我终于找到了解决办法。

虽然 Emgu 的 RTSP 流采集器不稳定,但 RTSPClientSharp 是一个非常稳定的实现,用于从 RTSP 流中采集单个帧并将它们转换为位图,您可以将其用于 .NET 中的任何图像处理。 GitWorks 中提供的示例开箱即用。

https://github.com/BogdanovKirill/RtspClientSharp

从GitHub下载项目后,您可以尝试使用以下流进行抓取(如果仍然在线,请使用VLC检查以确保流仍然可用)

rtsp://rtsp.stream/pattern