欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenCV2.x使用cvSetCaptureProperty定位后读取的帧重复 博客分类: opencv opencv视频分析 

程序员文章站 2024-03-20 16:53:16
...

前几天提取了一些视频中的人脸头像,交给同事去做识别分析,后来返回来说,其中的头像出现周期性的重复。
由于在视频中进行人脸检测开始是设定隔几幀检测一次,所以循环中使用了 cvSetCaptureProperty() 进行了跳帧,尔后通过cvQueryFrame()获取相应的帧转换成图像,于是怀疑是这里的问题。取消跳帧的规则后,程序检测正常。而修改定位的参数,比如直接改成定位到下一帧,却丝毫不起作用。
帧的重复非常有规律,我这边的测试数据是每隔5帧重复一次。于是就怀疑是否是定位出现了问题。google了一下,果然: opencv中cvSetCaptureProperty定位不准的原因及解决

 

 

friedvan的专栏 写道
经过差不多一晚上的探究,得出粗略的结论。原因在于opencv2.0以后,采用ffmpeg采集视频,而在opencv1.0采用vfw采集视频(具体的概念暂时还不清楚,有时间继续补上)。而opencv在定位时候,调用的ffmpeg的av_seek_frame()函数,此函数原型为:
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags);
其中,最后一个参数有
AVSEEK_FLAG_BACKWARD = 1; ///< seek backward
AVSEEK_FLAG_BYTE = 2; ///< seeking based on position in bytes
AVSEEK_FLAG_ANY = 4; ///< seek to any frame, even non key-frames
ffmpeg默认的是选取关键帧(这个概念需要具体定义)。opencv里面这个函数的参数flag是0,
int ret = av_seek_frame(ic, video_stream, timestamp, 0);
也就是按照默认的读取关键帧。因此,视频跳跃就出现了。
解决这个问题需要将0改为 AVSEEK_FLAG_ANY ,即:
int ret = av_seek_frame(ic, video_stream, timestamp, AVSEEK_FLAG_ANY );
之后重新编译opencv库,就可以了。

 但看了friedvan上面文章的回复,发现有人反映说是重新编译后读取视频出现花屏。因为一时也腾不出手来重新编译了测试,只好先通过另外的方式解决:即在读取的循环中加入判断,如果是需要处理的帧进行处理的逻辑,否则continue

 

VideoCapture cap;
cap.open("test.avi");
namedWindow("video",1);
int frameNum=0;
int readRatio=3;//读取的周期
for(;;){
 if(frameNum%readRatio!=0) continue;
 Mat frame;
 cap<<frame;
 
 //Do something

 frameNum++;
}
 

 

 

 

 

 

相关标签: opencv 视频分析