首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenCV FFMPEG RTSP相机馈电误差

OpenCV FFMPEG RTSP相机馈电误差
EN

Stack Overflow用户
提问于 2020-09-24 13:55:02
回答 2查看 4.9K关注 0票数 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有关,但是google对这类错误没有多大帮助。

代码语言:javascript
复制
#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;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-09-25 12:22:44

OpenCV和RTSP流有点棘手。当流的帧读取不够快时,通常会发生这种情况。在这种情况下(某个地方),接收RTSP帧的缓冲区填充速度将比清空速度快;当缓冲区已满时,它将被刷新,并将从最近的帧重新启动填充。这将破坏流解码直到下一个关键帧

我的建议是,即使10毫秒很小,也要删除sleep。由于这还不够(:P),唯一的解决方案是实现线程不断从cv::VideoCapture读取帧,并丢弃在主线程忙于保存前一个帧时捕获的帧。

一个简单的实现可以是:

代码语言:javascript
复制
#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;
}
票数 2
EN

Stack Overflow用户

发布于 2020-12-01 15:38:17

将视频压缩改为H.264解决了这个问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64048013

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档