1. 程式人生 > >opencv學習筆記(2)視訊檔案的讀取與儲存

opencv學習筆記(2)視訊檔案的讀取與儲存

main 函式輸入引數 argc、argv 的意義(參見[1])

在學習筆記(1)中最後寫到:“在Debug完成後,應該把原始影象放到專案資料夾的 debug 資料夾中,使影象與exe程式在同一資料夾內,才能在執行程式時正確讀入並顯示影象。”其實是有誤的,影象不一定要與exe程式在同一資料夾內,在 cvLoadImage( argv[1] ) 中,可以把 argv[1] 改成專案資料夾裡的圖片的具體地址,若圖片與程式同一資料夾,直接寫圖片的檔名即可。 
但是,這種在程式程式碼中寫檔名的方式很不方便,每次更改圖片檔案後都要重新編譯,實際上應該在跑程式時不改argv[1],而是在呼叫時輸入具體的檔名。要解決這個問題,就要理解好main 函式輸入引數 argc、argv 的意義。

     int main(int argc, char** argv) 
     int main(int argc, char* argv[])

argc 是指命令列輸入引數的個數,argv 則儲存了所有的命令列引數。假如我的一個程式是video_test.exe,如果在命令列執行該程式(首先應該在命令列下用 cd 命令進入到 video_test.exe 檔案所在目錄),要處理的檔案有 v1.avi、v2.mpg,執行命令為:

      video_test.exe v1.avi v2.mpg

那麼,argc的值是 3,argv[0]是"video_test.exe",argv[1]是"v1.avi",argv[2]是"v2.mpg"。

視訊檔案的讀取與基本處理

這裡主要是依照《Learning OpenCV》一書的例程修改實現的,其功能是讀取2個視訊檔案,分別在兩個視窗中播放,每個視窗都加入一個進度條,可以自行用滑鼠控制播放進度。程式碼如下:

建立一個Win32 Console專案 

#include <iostream>
#include <cv.h>
//#include <cvaux.h>
#include <cxcore.h>
#include <highgui.h>

// 使用標準名稱空間
using namespace std;

// 初始化進度條的位置
int g_slider_position1 = 0;
int g_slider_position2 = 0;

CvCapture* g_capture1 = NULL;
CvCapture* g_capture2 = NULL;

// 定義回撥函式用於播放進度的控制 
void onTrackbarSlide1( int pos1 )
{
 cvSetCaptureProperty( g_capture1, CV_CAP_PROP_POS_FRAMES, pos1 );
}
void onTrackbarSlide2( int pos2 )
{
 cvSetCaptureProperty( g_capture2, CV_CAP_PROP_POS_FRAMES, pos2 );
}


int main(int argc, char** argv )
{
 // 建立播放視窗
 cvNamedWindow( "Video Test 1", CV_WINDOW_AUTOSIZE );
 cvNamedWindow( "Video Test 2", CV_WINDOW_AUTOSIZE );

 // 捕捉視訊檔案
 g_capture1 = cvCreateFileCapture( "C:\\Users\\Administrator.PC-20131206COUD\\Desktop\\video\\1.mp4");
 g_capture2 = cvCreateFileCapture( "C:\\Users\\Administrator.PC-20131206COUD\\Desktop\\video\\2.mp4" );

 // 讀取、顯示視訊檔案的幀數
 int frames1 = (int) cvGetCaptureProperty( g_capture1, CV_CAP_PROP_FRAME_COUNT );
 cout << "frames1 = " << frames1 << endl;
 // 建立進度條
 if( frames1 != 0 )
  cvCreateTrackbar( 
   "Position", 
   "Video Test 1", 
   &g_slider_position1, 
   frames1, 
   onTrackbarSlide1
  );

 int frames2 = (int) cvGetCaptureProperty( g_capture2, CV_CAP_PROP_FRAME_COUNT );
 cout << "frames2 = " << frames2 << endl;
 if( frames2 != 0 )
  cvCreateTrackbar( 
   "Position", 
   "Video Test 2", 
   &g_slider_position2, 
   frames2, 
   onTrackbarSlide2 
  );

// 讀取視訊檔案資訊
 double fps1 = (int) cvGetCaptureProperty( g_capture1, CV_CAP_PROP_FPS );
 double fps2 = (int) cvGetCaptureProperty( g_capture2, CV_CAP_PROP_FPS );
 CvSize size1 = cvSize( 
  (int)cvGetCaptureProperty(g_capture1, CV_CAP_PROP_FRAME_WIDTH),
  (int)cvGetCaptureProperty(g_capture1, CV_CAP_PROP_FRAME_HEIGHT));
 CvSize size2 = cvSize( 
  (int)cvGetCaptureProperty(g_capture2, CV_CAP_PROP_FRAME_WIDTH),
  (int)cvGetCaptureProperty(g_capture2, CV_CAP_PROP_FRAME_HEIGHT));

// 建立 VideoWriter 
 CvVideoWriter* wrVideo1 = cvCreateVideoWriter("3.mp4", CV_FOURCC('M','J','P','G'), fps1, size1);
 CvVideoWriter* wrVideo2 = cvCreateVideoWriter("4.mp4", CV_FOURCC('M','J','P','G'), fps2, size2);

 int frs = 0;

 // 開始播放並儲存視訊
 IplImage* frame1;
 IplImage* frame2;
 
 while( frs < frames1 && frs < frames2 )
 {

  // 獲取、顯示原始檔的幀畫面
  frame1 = cvQueryFrame( g_capture1 );
  if( !frame1 ) break;
  cvShowImage( "Video Test 1", frame1 );

  frame2 = cvQueryFrame( g_capture2 );
  if( !frame2 ) break;
  cvShowImage( "Video Test 2", frame2 );

  // 儲存:將當前幀寫入到目標視訊檔案

  cvWriteFrame( wrVideo1, frame1 );
  cvWriteFrame( wrVideo2, frame2 );
  
  // 若按下 ESC 鍵,則退出程式
  char c = cvWaitKey(33);
  if( c==27 ) break;
 }
 // 釋放記憶體,關閉視窗
 cvReleaseCapture( &g_capture1 );
 cvReleaseCapture( &g_capture2 );
 cvReleaseVideoWriter( &wrVideo1 );
 cvReleaseVideoWriter( &wrVideo2 );
 cvDestroyWindow( "Video Test 1" );
 cvDestroyWindow( "Video Test 2" );

 return 0;
}