楊青錦
東北財經(jīng)大學(xué)津橋商學(xué)院, 大連 116023
OpenCV下按視頻幀率(FPS)播放視頻
楊青錦
東北財經(jīng)大學(xué)津橋商學(xué)院, 大連 116023
本文闡述了如何在OpenCV下按視頻幀率(FPS)播放視頻。程序使用了Windows系統(tǒng)下的高精度計時器控制視頻播放的幀間隔時間。本文給出了高精度計時器的使用方法、實(shí)現(xiàn)時間控制功能的主要程序片段,并在文章的最后比較了高精度計時器與一般計時函數(shù)的精度。
OpenCV;幀率;高精度計時器;播放視頻
OpenCV; fps; high-resolution timer; play video
OpenCV是Intel公司資助的開源計算機(jī)視覺庫。它提供了幾百個C/C++函數(shù),實(shí)現(xiàn)了計算機(jī)視覺領(lǐng)域中大部分最常用的算法。使用OpenCV開發(fā)計算機(jī)視覺應(yīng)用程序,經(jīng)常要讀取從攝像機(jī)獲得的視頻流或視頻文件,獲得其中的每一幀,再對該幀進(jìn)行算法處理。如果要滿足程序交互性的需要,通常還要將算法處理過的幀按原視頻幀率(FPS, frame per second)顯示出來。OpenCV提供了視頻幀的讀取、顯示函數(shù)以及獲得視頻幀率屬性的函數(shù),而按幀率決定的幀時間間隔顯示幀,則需要自己編程來解決。
在程序中,首先要取得視頻的幀率屬性,并由此計算出幀間隔時間,代碼如下:
CvCapture* cvCreateFileCapture( const char* filename )的參數(shù)是要讀取的文件名,函數(shù)返回指向CvCapture結(jié)構(gòu)體的指針,該指針的作用類似于我們用fopen()函數(shù)打開文件,返回的指向FILE結(jié)構(gòu)體的指針,之后我們可以通過這個指針操作視頻文件。如果程序是從攝像機(jī)讀取視頻,則用cvCreateCameraCapture()代替該函數(shù)。
double cvGetCaptureProperty( CvCapture* capture, int property_id )的作用是得到視頻的屬性信息,參數(shù)CV_ CAP_PROP_FPS要求函數(shù)返回幀率。用1000除以幀率,就得到了以毫秒為單位的幀間隔時間。
通常一個處理視頻的OpenCV程序主循環(huán)如下所示:
IplImage* cvQueryFrame( CvCapture* capture )的功能是順序讀取視頻的一幀,如果視頻結(jié)束,則返回的指針為NULL。程序接下來將對幀進(jìn)行算法處理。在處理結(jié)束后,cvShowImage()將幀顯示在名為Video的窗口中。cvWaitKey(40)的作用是延時40毫秒。假如我們對每一幀不做任何算法處理,那么該循環(huán)體的功能,就是將該視頻以40毫秒的幀間隔(即25 fps)播放出來。然而在實(shí)際應(yīng)用中,算法處理部分總會占用不定量的時間,所以延時固定時長的做法是不成立的。要使循環(huán)體的執(zhí)行時間,即每一幀的處理時間,保持在幀率決定的幀間隔時間上,需要在循環(huán)體得首尾加入時間檢測代碼,即在開頭獲取開始時間,在末尾獲取結(jié)束時間,兩個時間的差值就是循環(huán)體執(zhí)行時間。如果循環(huán)體執(zhí)行時間小于幀間隔時間,則延時以確保循環(huán)體執(zhí)行時間滿足應(yīng)有的幀間隔時間。
在Windows操作系統(tǒng)下,我們用API函數(shù)QueryPerformanceFrequency()和QueryPerformanceCounter()進(jìn)行時間檢測。這兩個函數(shù)的聲明如下:
QueryPerformanceFrequency()的輸出值lpFrequency指向系統(tǒng)內(nèi)高精度性能計數(shù)器的頻率,QueryPerformanceCounter()的輸出值lpPerformanceCount指向調(diào)用時刻高精度性能計數(shù)器的計數(shù)。在使用時,兩次調(diào)用QueryPerformanceCounter(),所得結(jié)果的差值,除以QueryPerformanceFrequency()得到的頻率,就得到兩次調(diào)用的間隔時間。舉例來說,如QueryPerformanceFrequency()得到的高精度性能計數(shù)器的頻率是每秒50000次,先后兩次調(diào)用QueryPerformanceCounter()得到的值分別是1500和3500,那么兩次調(diào)用的時間間隔為(3500-1500)/50000=0.04秒。
上述兩個函數(shù)的參數(shù)都是 LARGE_ INTEGER* 類型,LARGE_INTEGER的定義如下:
由上可見,LARGE_INTEGER代表了一個64位的整數(shù),在一般程序中,我們只需要使用其低32位,即DWORD LowPart。
實(shí)現(xiàn)時間控制功能的完整程序片段如下所示:
在一般的對實(shí)時性要求不高的程序中,常使用Windows API函數(shù)GetTickCount()獲取時間間隔。MSDN關(guān)于GetTickCount()的時間精度說明在10~16毫秒之間,這對于一般應(yīng)用程序中的耗時計算是足夠的,但對于幀時間間隔在毫秒級的視頻播放來說,就顯得精度不足了。MSDN推薦了高精度計時器QueryPerformanceFrequency()和QueryPerformanceCounter()用于更高精度的計時,雖然MSDN沒有明確說明高精度計時器的所能達(dá)到的精度,因其精度取決于計算機(jī)處理器,但在筆者的實(shí)際應(yīng)用中,高精度性能計數(shù)器完全可以滿足視頻播放的毫秒級精度。
最后補(bǔ)充一點(diǎn),如果處理視頻的循環(huán)體執(zhí)行時間大于原視頻的幀間隔時間,造成視頻不能按原幀率播放,則需要優(yōu)化每幀的處理算法,使每幀的處理時間保持在限度之內(nèi),滿足實(shí)時性的需求。
[1]劉瑞禎,于仕琪.OpenCV教程 基礎(chǔ)篇. 北京北京航空航天大學(xué)出版社, 2007.
[2]Intel OpenCV1.0安裝包自帶幫助文檔.http:// opencvlibrary.sourceforge.net/,2007.
[3]Microsoft MSDN. http://msdn.microsoft.com/,4/10/2011.
How to play video at its original fps in OpenCV
Yang Qingjin
Kingbridge College of Dongbei University of Finance & Economics Dalian 116023
This article depicts how to play video at its original fps in OpenCV. The program uses highresolution timer of Windows system to play video at a certain frame interval. This article demonstrates the usage of high-resolution timer and the code segment implementing time control. In the end, this article compares the resolution between high-resolution timer and common timer function.
10.3969/j.issn.1001-8972.2012.21.032
楊青錦,1982,男,碩士,物流系統(tǒng)中的計算機(jī)視覺應(yīng)用。