天天看點

【05】Opencv視訊播放控制

一個簡單的實作代碼:

#include"cv.h"
#include"highgui.h"

//設定全局變量,一個為滾動條的位置。回調函數需要用到的變量cvCapture也是全局變量,是以前面有g_,代表global

CvCapture*g_capture = NULL;//用來儲存圖像捕獲的資訊的結構體
int g_slider_pos = 0;
int frame_count = 0;//記錄播放的幀數


//當滑鼠滑動滑塊的時候 調用該回調函數
void onTrackbarSlider(int pos)//這個參數由cvCreateTrackbar傳入  它反映了目前滑塊被滑到的位置
{
	//設定目前視訊檔案的屬性
	cvSetCaptureProperty(
		g_capture,
		CV_CAP_PROP_POS_FRAMES,//機關為幀數的位置(隻對視訊檔案有效)
		pos                    //設定指定視訊擷取的屬性
		);
	frame_count = pos;
}

int main()
{
	cvNamedWindow("show");//建立視窗
	g_capture = cvCreateFileCapture("E:\\Linux基礎知識與系統管理\\01 運維基礎\\01_01_面授班開場.avi");//擷取視訊檔案
	//擷取視訊的全部幀數frames
	int frames = (int)cvGetCaptureProperty(
		g_capture,
		CV_CAP_PROP_FRAME_COUNT//視訊檔案中幀的總數
		);
	if (frames > 0)
	{
		//建立進度條
		//當你滑動滑塊的時候 會觸發一個事件執行cvCreateTrackbar 然後cvCreateTrackbar調用onTrackbarSlider 然後傳回while接着以前繼續循環
		//cvCreateTrackbar這個函數系統調用    onTrackbarSlider我們自己填寫代碼實作
		cvCreateTrackbar(
			"Pos", //進度條名稱
			"show",//所在視窗
			&g_slider_pos,//滑塊的位置
			frames,//滑塊位置的最大值。最小值一直是0
			onTrackbarSlider//回調函數   這裡面回調函數的聲明參數必須是×××的  傳回值為void
			//當你用滑鼠拉動滑塊的時候 就會産生一個消息  來執行這個回調函數
			);
	}
	IplImage*frame;
	while (true)
	{
		frame = cvQueryFrame(g_capture);//從攝像頭或者檔案中抓取并傳回一幀
		//cvQueryFrame的參數為CvCapture結構的指針。用來将下一幀視訊檔案載入記憶體,傳回一個對應目前幀的指針
		if (!frame)
		{
			break;
		}
		cvShowImage("show",frame);

		char c = cvWaitKey(33);//控制頻率
		if (c == 27)//ESC鍵
		{
			break;
		}
		//設定滑塊的位置   實作滑塊随視訊的播放而移動
		cvSetTrackbarPos(
			"pos",
			"show",
			frame_count//滑塊的位置
			);
		frame_count++;//每播放一幀的時候  加一
	}
	//釋放資源
	cvReleaseCapture(&g_capture);
	cvDestroyWindow("show");
	return 0;
}      

函數解釋:

擷取視訊檔案和攝像頭屬性的函數

/* retrieve or set capture properties */
CVAPI(double) cvGetCaptureProperty( CvCapture* capture,                                   int property_id );
capture     要擷取的視訊檔案指針
property_id 要擷取的屬性  傳入相應的宏傳回相應的屬性

CV_CAP_PROP_POS_MSEC        - 影片目前位置,為毫秒數或者視訊擷取時間戳
CV_CAP_PROP_POS_FRAMES      - 将被下一步解壓/擷取的幀索引,以0為起點
CV_CAP_PROP_POS_AVI_RATIO   - 視訊檔案的相對位置(0 - 影片的開始,1 - 影片的結尾)
CV_CAP_PROP_FRAME_WIDTH     - 視訊流中的幀寬度
CV_CAP_PROP_FRAME_HEIGHT    - 視訊流中的幀高度
CV_CAP_PROP_FPS             - 幀率
CV_CAP_PROP_FOURCC          - 表示codec的四個字元
CV_CAP_PROP_FRAME_COUNT     - 視訊檔案中幀的總數      

一個bug:

 有時候cvGetCapturePropetry在cvQueryFrame被調用一次後在調用cvGetCapturePropetry才會傳回正确的數值

建立一個滾動條

* create trackbar and display it on top of given window, set callback */
CVAPI(int) cvCreateTrackbar( const char* trackbar_name, //滾動條的名字
              const char* window_name,   //所在視窗的名字 
        int* value,                //指定建立時的滑塊位置
     int count,                 //滑塊位置的最大值。最小值一直是0
     CvTrackbarCallback on_change CV_DEFAULT(NULL));
     //每次滑塊位置改變時,調用該回調函數
 
 //typedef void (CV_CDECL *CvTrackbarCallback)(int pos);
 //on_change 每次滑塊位置被改變的時候,被調用函數的指針。
 //這個函數應該被聲明為void Foo(int); 如果沒有回調函數,這個值可以設為NULL      

回調函數:

 回調函數就是一個通過函數指針調用的函數

 如果你把函數的指針(位址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數

    回調函數不是由該函數的實作方法直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用于對該事件或條件進行響應

編輯

機制:

⑴定義一個回調函數;

⑵提供函數實作的一方在初始化的時候,将回調函數的函數指針注冊給調用者;

⑶當特定的事件或條件發生的時候,調用者使用函數指針調用回調函數對事件進行處理

設定攝像頭屬性的函數

CVAPI(int)    cvSetCaptureProperty( 
                   CvCapture* capture, //視訊擷取結構
                   nt property_id,    // 屬性辨別符
                   double value );
                                    
CV_CAP_PROP_POS_MSEC - 從檔案開始的位置,機關為毫秒
CV_CAP_PROP_POS_FRAMES - 機關為幀數的位置(隻對視訊檔案有效)
CV_CAP_PROP_POS_AVI_RATIO - 視訊檔案的相對位置(0 - 影片的開始,1 - 影片的結尾)
CV_CAP_PROP_FRAME_WIDTH - 視訊流的幀寬度(隻對攝像頭有效)
CV_CAP_PROP_FRAME_HEIGHT - 視訊流的幀高度(隻對攝像頭有效)
CV_CAP_PROP_FPS - 幀率(隻對攝像頭有效)
CV_CAP_PROP_FOURCC - 表示codec的四個字元(隻對攝像頭有效)