OpenCV FFMPEG RTSP相机提供的错误

4

当从rtsp相机获取帧并保存时,我会在不确定的时间遇到这些错误。这些错误通常发生在保存100-200张图像后的不同时间,错误本身并不总是完全相同。这些错误导致保存到时间错误的图像出现失真,可能变成完全灰色或包含扭曲的像素。

#Frame_142 - [hevc @ 0c3bf800] The cu_qp_delta 29 is outside the valid range [-26, 25].

#Frame_406 - [hevc @ 0b6bdb80] Could not find ref with POC 41

我尝试使用python和c++实现代码,但结果相同。也尝试将其保存为.png而不是.jpg。当使用imshow显示相机时,rtsp源正常工作,问题似乎只会在尝试保存帧时发生。据我所了解,这些错误与ffmpeg有关,但谷歌对这些错误类型没有太多帮助。

#include <iostream>
#include <opencv2\opencv.hpp>
#include <chrono>
#include <thread>

using namespace std;
using namespace cv;

int main() {

    VideoCapture cap("rtsp://admin:admin@192.168.88.97/media/video1");
    if (!cap.isOpened())
        return -1;

    for (int i = 0; i < 500; i++)
    {
        Mat frame;
        cap >> frame;
        imwrite("C:\\Users\\Documents\\Dev\\c++\\OpenCVExample\\frames\\frame" + std::to_string(i) + ".png", frame);
        cout << i << "\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(10));

    }

    return 0;
}

在写作 if(frame.data) 之前,尝试检查帧是否有效。这可能不仅是问题,还有一个遗漏点。请查看此处 - Yunus Temurlenk
2个回答

2

OpenCV和RTSP流有些棘手。这通常发生在无法快速读取流的帧时。在这种情况下,接收RTSP帧的缓冲区将比它可以被清空得更快地填满;当缓冲区已满时,它将被刷新并从最近的帧重新开始填充。这将导致流解码出现损坏,直到下一个关键帧

我的建议是删除sleep,即使10ms非常短。由于这不足以解决问题 (:P),唯一的解决方案是实现一个线程,不断从 cv::VideoCapture 读取帧,并且在主线程忙于保存之前的帧时,抛弃那些被抓取的帧。

一个简单的实现方法可能是:

#include <opencv2/opencv.hpp>
#include <thread>

class VideoSourceHandler
{
public:
  // Video file or IP camera
  VideoSourceHandler( const std::string & source ) :
    mCapture( source ),
    mRun( false )
  {
  }

  // USB camera
  VideoSourceHandler( int webcamID ) :
    mCapture( webcamID ),
    mRun( false )
  {
  }

  // start and stopCapture can be squashed into C'tor and D'tor if you want RTTI
  void startCapture()
  {
    mRun = true;
    mLoopThread = std::thread( &VideoSourceHandler::threadLoop, this );
  }

  void stopCapture()
  {
    mRun = false;
    mLoopThread.join();
  }

  cv::Mat getFrame()
  {
    std::this_thread::yield(); // Be nice
    const std::lock_guard<std::mutex> lock( mMutex );
    return mCurrentFrame;
  }

private:
  void threadLoop()
  {
    while( mRun )
    {
      // Sleep if you want to "control" FPS
      {
        const std::lock_guard<std::mutex> lock( mMutex );
        mCapture >> mCurrentFrame;
      }
      std::this_thread::yield(); // Be nice
    }
  }

  cv::VideoCapture mCapture;
  std::thread      mLoopThread;
  std::mutex       mMutex;
  bool             mRun;
  cv::Mat          mCurrentFrame;
};

int main()
{
  VideoSourceHandler vsh( 0 );
  vsh.startCapture();
  while( true )
  {
    cv::Mat frame = vsh.getFrame();
    if( frame.empty() )
      continue;

    cv::imshow( "Test", frame );
    char key = cv::waitKey( 1 );
    if( key == 'q' || key == 27 )
      break;

  }
  vsh.stopCapture();
  return 0;
}

1
这个答案让我改变了来自相机的帧率,从而解决了问题。将帧率从25fps降至10fps后,错误停止出现了。谢谢! - trn2020

0

将视频压缩格式更改为H.264,问题得到了解决。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接