歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

OpenCV中cvSetCaptureProperty定位不准的原因及解決

以前在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:測試的代碼

  1. #include "opencv/highgui.h"  
  2. #include <iostream>   
  3. using namespace std;  
  4. int main( int argc, char** argv )  
  5. {   
  6.     cvNamedWindow( "Example2", CV_WINDOW_AUTOSIZE );  
  7.     CvCapture* capture = cvCreateFileCapture( "d://11.avi" );  
  8.     IplImage* frame;  
  9.     int pos=0;  
  10.     int pos1=0;  
  11.     while(1)  
  12.     {  
  13.         cvSetCaptureProperty(capture,CV_CAP_PROP_POS_FRAMES,pos);  
  14.         cout<<pos;  
  15.         frame = cvQueryFrame(capture);  
  16.         pos1=cvGetCaptureProperty(capture,CV_CAP_PROP_POS_FRAMES);  
  17.         cout<<"/t"<<pos1<<endl;  
  18.         if( !frame ) break;  
  19.         cvShowImage( "Example2", frame );  
  20.         char c = cvWaitKey(33);  
  21.         if( c == 27 ) break;  
  22.         pos++;  
  23.     }  
  24.     cvReleaseCapture( &capture );  
  25.     cvDestroyWindow( "Example2" );  
  26. }  
Copyright © Linux教程網 All Rights Reserved