我在随机的时候得到这些错误,当从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对这类错误没有多大帮助。
#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;
}发布于 2020-09-25 12:22:44
OpenCV和RTSP流有点棘手。当流的帧读取不够快时,通常会发生这种情况。在这种情况下(某个地方),接收RTSP帧的缓冲区填充速度将比清空速度快;当缓冲区已满时,它将被刷新,并将从最近的帧重新启动填充。这将破坏流解码直到下一个关键帧。
我的建议是,即使10毫秒很小,也要删除sleep。由于这还不够(: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;
}发布于 2020-12-01 15:38:17
将视频压缩改为H.264解决了这个问题。
https://stackoverflow.com/questions/64048013
复制相似问题