出處:http://blog.csdn.net/friedvan/article/details/6195777 (opencv2.3.1仍然有這問題)
以前在opencv2.0裏面用到cvSetCaptureProperty函數的時候總是發生定位不準確的問題,明明是讓其跳到100幀,結果卻總不是100幀,定位一段連續的視頻,總是出現跳躍的現象。同樣的代碼在opencv1.0裏面完全沒錯。可是這是爲什麼?這個問題一直困擾了我半年,終於在今天知道原因了。
經過差不多一晚上的探究,得出粗略的結論。原因在於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庫,就可以了。
P.S:測試的代碼
#include "opencv/highgui.h"
#include <iostream>
using namespace std;
int main( int argc, char** argv )
{
cvNamedWindow( "Example2", CV_WINDOW_AUTOSIZE );
CvCapture* capture = cvCreateFileCapture( "d://11.avi" );
IplImage* frame;
int pos=0;
int pos1=0;
while(1)
{
cvSetCaptureProperty(capture,CV_CAP_PROP_POS_FRAMES,pos);
cout<<pos;
frame = cvQueryFrame(capture);
pos1=cvGetCaptureProperty(capture,CV_CAP_PROP_POS_FRAMES);
cout<<"/t"<<pos1<<endl;
if( !frame ) break;
cvShowImage( "Example2", frame );
char c = cvWaitKey(33);
if( c == 27 ) break;
pos++;
}
cvReleaseCapture( &capture );
cvDestroyWindow( "Example2" );
}
參考:http://wsqhs.spaces.live.com/blog/cns!94F639580F58209C!697.entry