EmguCV Image Process: Process Video Sequences
參考OpenCV 2 Computer Vision Application Programming Cookbook第十章
介紹內容如下:
Reading video sequences
Processing the video frames
Writing video sequences
Tracking feature points in video
Extracting the foreground objects in video
這次要來介紹如何透過EmguCV來處理視訊檔案
在視訊的訊號中,包含了連續的影像
稱之為:frame
frame與frame之間的固定間隔時間則稱為:frame rate
當這些frame在非常快速的變換之下
內容看起來就像是會動一樣
但其實這過程只是將一張一張的frame不斷地呈現出來而已
過去受限於電腦硬體,要處理視訊檔案是非常棘手的一件事
但由於現在電腦的強度越來越強,速度越來越快
視訊處理已經變得越來越熱門,也越來越容易
本章節將會介紹如何讀取、控制、儲存影片視訊檔案
透過EmguCV中capture這個類別
可以非常簡單的取出影片的frame
甚至還提供了許多基本的控制功能,相當實用
下面來看如何取出frame
//Open the video file Capture capture = new Capture(@"video.avi"); //Get the frame rate double rate = capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FPS); //Delay between each frame in ms //corresponds to video frame rate int delay = (int)(1000 / rate); bool stop = false; //current video frame Image<Bgr, Byte> frame; string windowTitle = "video window"; CvInvoke.cvNamedWindow(windowTitle); while (!stop) { //read next frame if any frame = capture.QueryFrame(); if (frame == null) { break; } CvInvoke.cvShowImage(windowTitle, frame); //introduce a delay //or press key to stop if (CvInvoke.cvWaitKey(delay) >= 0) { stop = true; } } CvInvoke.cvDestroyWindow(windowTitle); //Close the video file. //Not required since called by destructor capture.Dispose();這邊先建立一個Capture的類別
建構式中帶入視訊檔案的完整錄影檔名
然後去取出這段影片的frame rate
(capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FPS))
利用一個while迴圈
不斷的去呼叫capture.QueryFrame()取出最新的一張frame
直到影片播完,取不到frame時,就跳出while
這裡利用CvInvoke.cvNamedWindow(windowTitle)建立一個視窗
利用這個視窗來顯示frame
透過指定window的title來顯示CvInvoke.cvShowImage(windowTitle, frame);
並做frame與frame之間的延遲,CvInvoke.cvWaitKey(delay)
顯示結果就像這樣:
可以看到左上方的title為video window
Capture這個類別提供了很多功能可玩
像是可以取出整部影片的所有frame數量
double totalFrames = capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_COUNT);
那也可以取出當前的frame的index
也可以跳到你指定的index來撥放
這兩個方法搭配起來,就可以實作快轉的功能
double frameCount = capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES); capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES, frameCount + 30);
將每次frame播完後就往後跳30張frame的快轉!!
Capture提供的功能很多
有興趣的人可以到EmguCV官網的文件查詢
而這個功能還可以擷取電腦上的USB camera,或是筆電上的web cam
只要在Capture的建構式不帶入參數,或是帶入index
代表第一支camera、第二支camera等
Capture capture = new Capture();或是
Capture capture = new Capture(0);
都是取出預設第一支camera
有一點要提醒的是
USB camera跟web cam是沒有所謂的FPS
所以在 capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FPS)
取出來的值會為0
因此可將那段程式碼改成
int delay = (rate > 0) ? (int)(1000 / rate) : 1;
這樣就沒問題啦!!
下一篇將介紹如何透過包裝來彈性的處理視訊檔案
沒有留言:
張貼留言