利用OpenCV進行【視頻的讀取】與【保存視頻文件或者圖像】源碼!~

利用OpenCV進行【視頻的讀取】與【保存視頻文件或者圖像】源碼!~

爲了能夠更好的支持AVI視頻的讀取,請安裝K-Lite Codec Pack Full 3.9.3 Beta
下載地址:http://dl.pconline.com.cn/html_2/1/124/id=6563&pn=0.html

#include <afx.h>
#include <iostream>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>

using namespace std;

/////////////////////////////////////////////////////////
//作者:Flobert_Young
//日期:2008-05-22
//說明:
//   需要配置OpenCV的開發環境,並且一定要確保當前Project里加入了cv.lib cxcore.lib highgui.lib庫
//鏈接錯誤解決方法:
//   編譯時出現unresolved   external   symbol   __endthreadex 的處理方法
//   菜單   Project->Settings...   在   C/C++   頁,
//   在   Category   下拉框裏選擇   Code   Generation,
//   然後在   Use   run-time   library   裏選擇
//   Debug   Multithreaded   (   Debug   版本時用   )
//   或者   Multithreaded   (   release   版本時用).
/////////////////////////////////////////////////////////

enum CaptureCase
{
CAP_FROM_CAM = 0,
CAP_FROM_VIDEO = 1,
};

enum PlayVideoCase
{
FRAME_BY_FRAME = 0,
FRAME_BY_INDEX = 1,
};

//////////////////////////////////////
//函數聲明
int FrameByFrame(CvVideoWriter * pVideoWriter,IplImage *pFrame,bool bSave,
     CvCapture * pCapture,char *pVideoSaveName,int nWaitKeyTime);

int FrameByIndex(CvCapture * pCapture,IplImage *pFrame,
     int cap_prop,int cap_prop_value,
     CString strSaveImagePath);

//////////////////////////////////////
//主函數部分
int main()
{
int ret = 0;
bool bErr = 0;
bool bSave = 0; //0 - 不保存視頻文件;1 - 保存視頻文件
CaptureCase cap_case = CAP_FROM_VIDEO;   //設置成從視頻文件中獲取圖像
PlayVideoCase play_case = FRAME_BY_FRAME; //設置成一幀一幀的播放視頻文件
int nWaitKeyTime = 40; //顯示圖像所間隔的時間,以“毫秒”爲單位

//////////////////////////////////////
//變量聲明
CvCapture * pCapture = NULL; //用於在視頻中捕獲圖像
char szVideoFileName[] = "C://電影.AVI";   //!將打開的視頻文件名設置成"C://1.mpg"
char szVideoSaveName[] = "C://VideoSave.avi"; //!將保存視頻文件的名字設置成"C://VideoSave.avi"
CString strSaveImagePath = "C://";    //!保存圖片的目錄名
CvVideoWriter * pVideoWriter = NULL; //用於保存視頻文件
IplImage * pFrame = NULL;
IplImage * pImage = NULL;

switch(cap_case)
{
case CAP_FROM_CAM:
   //函數cvCaptureFromCAM()參數說明:
   //要使用的攝像頭索引。如果只有一個攝像頭或者用哪個攝像頭也無所謂,那使用參數-1應該便可以。
   pCapture = cvCaptureFromCAM(-1); //和函數cvCreateCameraCapture()有什麼區別???
   if(NULL==pCapture) //打開攝像頭
   {
    cout<<"ERROR: 攝像頭讀取失敗!"<<endl;
    bErr = 1;
   }
   break;

case CAP_FROM_VIDEO: //打開視頻文件
   pCapture = cvCaptureFromFile(szVideoFileName); //和函數cvCreateFileCapture()有什麼區別???
   if(NULL==pCapture)
   {
    cout<<"ERROR: 視頻文件讀取失敗!"<<endl;
    bErr = 1;
   }
   break;
}

if(!bErr)
{
   switch(play_case)
   {
   case FRAME_BY_FRAME:
    FrameByFrame(pVideoWriter,pFrame,bSave,pCapture,szVideoFileName,nWaitKeyTime);
    break;

   case FRAME_BY_INDEX:
    //在窗口上顯示視頻的61%部分的那一幀圖像
    int cap_prop_value = 61;
    FrameByIndex(pCapture,pFrame,CV_CAP_PROP_POS_AVI_RATIO,cap_prop_value,strSaveImagePath);
    break;
   }
}


char ch;
cin>>ch;


return ret;
}

 

int FrameByFrame(CvVideoWriter * pVideoWriter,IplImage *pFrame,bool bSave,
     CvCapture * pCapture,char *pVideoSaveName,int nWaitKeyTime)
{
int ret = 0;
/****************************************/
///////////////////////////
//1.逐幀讀取視頻
int nCurFrameIndex = 0;
cvNamedWindow("Frame_By_Frame",1);

//在圖像窗口左上角顯示“Current Frame: **”字符串
CString strFrameString;
CvFont font;
cvInitFont( &font,CV_FONT_HERSHEY_SIMPLEX,0.5,0.5,0,2,8 );

//創建視頻文件寫入器
//第二個參數fourcc - 四個字符用來表示壓縮幀的codec
//例如,CV_FOURCC('P','I','M','1')是MPEG-1 codec,
//CV_FOURCC('M','J','P','G')是motion-jpeg codec等。
//在Win32下,如果傳入參數-1,可以從一個對話框中選擇壓縮方法和壓縮參數。
//這裏是按20幀/s進行寫入視頻文件的,但是當右鍵"C://VideoSave.avi"屬性 -> 摘要,
//發現“持續時間: 0:00:02   幀速率: 500幀/秒”???
//如果改成30幀/s,則發現屬性改爲“持續時間: 0:00:01   幀速率: 750幀/秒”???
if(1==bSave)
{
   pVideoWriter = cvCreateVideoWriter(pVideoSaveName,-1,20,cvSize(640,480),1);
}
if((NULL!=pVideoWriter&&bSave)||(!bSave))
{  
   while(pFrame = cvQueryFrame(pCapture))
   {
    if(1==bSave)
    {
     //將獲取的視頻文件一幀一幀的寫入要保存的視頻文件中
     cvWriteFrame(pVideoWriter,pFrame);
    }
   
    nCurFrameIndex++;
    strFrameString.Format("Current Frame: %d",nCurFrameIndex);
    cvPutText( pFrame,strFrameString,cvPoint( 5,pFrame->height-15 ),&font,cvScalar( 0,255,0 ) );
   
    cvShowImage("Frame_By_Frame",pFrame);
    if(0==bSave) //如果是保存視頻時,則加快顯示速度
    {
     cvWaitKey(nWaitKeyTime);
    }
    else
    {
     cvWaitKey(10); //如果選擇保存視頻時,好像不能夠正常顯示圖像???
    }
   }
  
   if(1==bSave)
   {
    //釋放視頻寫入器
    cvReleaseVideoWriter(&pVideoWriter);
   }
  
   cvDestroyWindow("Frame_By_Frame");
   cvReleaseCapture(&pCapture);
}
else
{
   cout<<"ERROR:創建CvVideoWriter * 失敗!"<<endl;
}
/****************************************/

ret = 1;
return ret;
}

 

int FrameByIndex(CvCapture * pCapture,IplImage *pFrame,int cap_prop,int cap_prop_value,
     CString strSaveImagePath)
{
int ret = 0;

/****************************************/
///////////////////////////
//2.讀取第i幀視頻
cvNamedWindow("FrameIndex_i",1);
//目前這個函數對視頻文件只支持:
//CV_CAP_PROP_POS_MSEC, CV_CAP_PROP_POS_FRAMES, CV_CAP_PROP_POS_AVI_RATIO
switch(cap_prop)
{
case CV_CAP_PROP_POS_MSEC:
   //讀取視頻中第cap_prop_value秒的圖像
   cvSetCaptureProperty(pCapture,CV_CAP_PROP_POS_MSEC,cap_prop_value);
   break;
  
case CV_CAP_PROP_POS_FRAMES:
   //讀取視頻中第cap_prop_value幀的圖像
   cvSetCaptureProperty(pCapture,CV_CAP_PROP_POS_FRAMES,cap_prop_value);
   break;
  
case CV_CAP_PROP_POS_AVI_RATIO:
   //讀取視頻中cap_prop_value%處的圖像
   double ratio = cap_prop_value/100.0; //100.0是爲了將除法的結果轉化成“浮點型”
   cvSetCaptureProperty(pCapture,CV_CAP_PROP_POS_AVI_RATIO,ratio);
   break;
}

if(pFrame = cvQueryFrame(pCapture))
{
   //保存當前圖像
   CString strSaveImageName;
   CString strTmp;
   strTmp.Format("SaveImage_%d.bmp",cap_prop_value);
   strSaveImageName = strSaveImagePath + strTmp;
   cvSaveImage(strSaveImageName,pFrame);

   cvShowImage("FrameIndex_i",pFrame);
   cvWaitKey(-1);
}

cvDestroyWindow("FrameIndex_i");
cvReleaseCapture(&pCapture);
/****************************************/

ret = 1;
return ret;
}

 

【來源】

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章