#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
//打開視頻文件:其實就是建立一個VideoCapture結構
VideoCapture capture("../InputVideo/test.avi");
//檢測是否正常打開:成功打開時,isOpened返回ture
if(!capture.isOpened())
cout<<"fail to open!"<<endl;
//獲取整個幀數
long totalFrameNumber = capture.get(CV_CAP_PROP_FRAME_COUNT);
cout<<"整個視頻共"<<totalFrameNumber<<"幀"<<endl;
//設置開始幀()
long frameToStart = 300;
capture.set( CV_CAP_PROP_POS_FRAMES,frameToStart);
cout<<"從第"<<frameToStart<<"幀開始讀"<<endl;
//設置結束幀
int frameToStop = 400;
if(frameToStop < frameToStart)
{
cout<<"結束幀小於開始幀,程序錯誤,即將退出!"<<endl;
return -1;
}
else
{
cout<<"結束幀為:第"<<frameToStop<<"幀"<<endl;
}
//獲取幀率
double rate = capture.get(CV_CAP_PROP_FPS);
cout<<"幀率為:"<<rate<<endl;
//定義一個用來控制讀取視頻循環結束的變量
bool stop = false;
//承載每一幀的圖像
Mat frame;
//顯示每一幀的窗口
namedWindow("Extracted frame");
//兩幀間的間隔時間:
//int delay = 1000/rate;
int delay = 1000/rate;
//利用while循環讀取幀
//currentFrame是在循環體中控制讀取到指定的幀后循環結束的變量
long currentFrame = frameToStart;
//濾波器的核
int kernel_size = 3;
Mat kernel = Mat::ones(kernel_size,kernel_size,CV_32F)/(float)(kernel_size*kernel_size);
while(!stop)
{
//讀取下一幀
if(!capture.read(frame))
{
cout<<"讀取視頻失敗"<<endl;
return -1;
}
//這里加濾波程序
imshow("Extracted frame",frame);
filter2D(frame,frame,-1,kernel);
imshow("after filter",frame);
cout<<"正在讀取第"<<currentFrame<<"幀"<<endl;
//waitKey(int delay=0)當delay ≤ 0時會永遠等待;當delay>0時會等待delay毫秒
//當時間結束前沒有按鍵按下時,返回值為-1;否則返回按鍵
int c = waitKey(delay);
//按下ESC或者到達指定的結束幀后退出讀取視頻
if((char) c == 27 || currentFrame > frameToStop)
{
stop = true;
}
//按下按鍵后會停留在當前幀,等待下一次按鍵
if( c >= 0)
{
waitKey(0);
}
currentFrame++;
}
//關閉視頻文件
capture.release();
waitKey(0);
return 0;
}
(1)原視頻進行了簡單的均值濾波處理。
(2)雖然VideoCapture類中有grab(捕獲下一幀)和retrieve(對該幀進行解碼)操作,但是直接用read比較簡單。
(3)get函數的功能很強大,可以獲取關於視頻的大部分信息,具體內容可以查看幫助手冊。
(4)為了保證視頻播放的流暢性,幀與幀之間加入了時延。這個時延是通過幀率算出來的。