星期一, 10月 29, 2012

Week 8: 回呼函數 callback function

1. 什麼是回呼函數(callback function)?

a. 函數的呼叫(call)與回覆(return)

在程式的執行過程中, 當主程式呼叫一個函數 (call function) 時, 程式會跳到函數繼續執行, 當遇到 return 指令時, 就會返回主程式的呼叫點繼續執行。

b. Callback Function = Call + Back + Function

當我們執行某個應用程式時, 針對 Form 上各個物件所發生的事件, 嚴格來說可以分成兩類:

(1) 由使用者觸發, 如使用者透過滑鼠或鍵盤所觸發的事件。

這類事件, 在 object-oriented 程式語言中, 是用 event-driven 的設計, 使用者針對個別物件, 撰寫不同事件處理程序來因應。

(2) 非由使用者觸發, 乃系統自行發生的事件。

如程式發生錯誤情況, 或系統做了特定事件, 如從視訊裝置擷取一個畫面。此類事件, 使用者就可以設定 callback function 來因應這些事件的發生。

2. 預覽回呼函數 preview callback function

當視訊擷取驅動程式接收到來自視訊裝置的畫面(frame), 在 preview 模式之下, 會將此畫面顯示在所連結的視訊視窗之中。

我們可以透過 capSetCallbackOnFrame 這個函數來指定當發生 frame preview 之前, 先執行一個特定的 callback function, 即預覽回呼函數。這個預覽回呼函數的名稱可以由我們自由命名, 但是傳入的參數個數與其資料型態則必須符合 VFW 的規定。

// 使用者自行寫的預覽回呼函數必須在公用變數宣告區宣告
LRESULT CALLBACK FrameCallBack( HWND hwndCapture, PVIDEOHDR lpvhdr );

// 設定 callback function 與視訊擷取視窗之間的連結,
// 請將此行放到開啟視訊擷取視窗, 並開始 preview 的指令後

capSetCallbackOnFrame(hwndCapture, &FrameCallBack);

3. 如何關閉預覽回呼函數?

capSetCallbackOnFrame(hwndVideo, NULL);

4. VFW 函式介紹:

a. 取得視訊畫面基本資料 (capGetVideoFormat)

b. BITMAPINFO structure

c. BITMAPINFOHEADER structure

5. 範例程式 Webcam Programming (4): 預覽回呼函數

範例程式 Webcam Programming (4) 主要分成五個部分:
part A: 預覽回呼函數之設定與關閉
part B: 預覽回呼函數與視訊資料表頭結構
part C: 透過預覽回呼函數將預覽畫面變成灰階畫面
part D: 透過預覽回呼函數在視訊畫面中填入單一顏色的長方塊
part E: 透過預覽回呼函數將圖片置入視訊擷取視窗之中

part A: 預覽回呼函數之設定與關閉

本部分的主要目的是讓同學了解視訊擷取視窗之預覽回呼函數的設定與使用方法。要設定預覽回呼函數, 是透過 capSetCallbackOnFrame 函式完成的, 函式的輸入參數有二, 視訊擷取視窗的代碼(handle)與所設定預覽回呼函數之位址。當程式開啟視訊擷取視窗後, 顯示預覽的畫面總數到 TLabel 元件上。

首先, 我們在 Mainmenu 元件之中新增 Preview Callback Function 的功能列, 用來切換不同功能的預覽回呼函數及關閉預覽回呼函數(Off)。圖 4-A-1 的功能列分別就是範例程式 Webcam Programming (4) 的 A(Frame Counter)、C(Gray Mode)、D(Object)、E(Object)等四個部分。


圖 4-A-1

在圖 4-A-2 之中, 可以看到在視訊擷取視窗的右邊, 放置了一個目前 Caption 設定為 FC 的 TLabel 元件。在程式執行的過程中, 本元件將負責顯示目前已顯示的畫面總數。


圖 4-A-2

part B : 預覽回呼函數與視訊資料表頭結構



圖 4-B-3


圖 4-B-4


part C : 透過預覽回呼函數將預覽畫面變成灰階畫面 

part C 的目的是讓同學有能力存取視訊擷取視窗的緩衝區記憶體中的畫面資料。


圖 4-B-5

延伸想法: 可以將視訊畫面變成特定色調嗎?



請參考 影像處理課程作業三。當然也可以透過 ColorDialog 讓使用者選定顏色後, 計算出所選定顏色的 YUV 値, 再將 UV 値放進 YUY2 攝影機的緩衝區記憶體, 就大功告成了!

補充資料: RGB pixel formats

星期一, 10月 22, 2012

Week 7: Webcam Programming (3) 錄影控制

1. VFW 函式介紹:

a. 取得與設定錄影檔案名稱 (capFileGetCaptureFile, capFileSetCaptureFile)

b. 預先配置視訊檔案磁碟空間 (capFileAlloc)

c. 開始連續視訊串流擷取 (capCaptureSequence)

d. 結束連續視訊串流擷取 ( capCaptureAbort, capCaptureStop )

兩個函式的主要差別在於 capCaptureAbort 函式只會將所擷取的視訊資料存入 AVI 檔案之中, 而 capCaptureStop 則會將視訊與音訊資料一併存入 AVI 檔案之中。


2. 範例程式 Webcam Programming (3)

範例程式 Webcam Programming (3) 所設定的學習目標主要是靜態影像擷取與動態視訊錄影之實作。分成 3 個部分:
part A - 靜態影像擷取
part B - 錄影參數之取得與設定
part C - 錄影控制

範例程式 Webcam Programming (3) 的第 3 個主題是錄影控制, 包含錄影檔案名稱的取得與設定、預先配置硬碟空間給 AVI 檔案, 啟動錄影與停止錄影。

part C - 錄影控制

除了錄影參數的設定之外, 使用者還可以透過 capFileSetCaptureFile 函式設定儲存檔案的名稱, 透過 capFileAlloc 函式來配置預先設定之磁碟空間大小, 然後就可以使用 capCaptureSequence 函式開始錄製一段影片了。





提醒同學注意, 如果你的電腦有安裝 Codec 壓縮程式, 也可以透過視訊壓縮對話盒來設定壓縮程式, 這樣你所錄製的影片, 就會使用你所選定的壓縮程式來錄製影片。



下面這段影片就是使用 Xvid MPEG-4 Codec 所錄製的壓縮影片。

星期一, 10月 15, 2012

Week 6: Webcam Programming (3) 靜態影像擷取

1. VFW 函式介紹:

a. 靜態影像擷取
( capGrabFrame, capGrabFrameNoStop )

b. 視訊畫面複製到剪貼簿( capEditCopy )

c. 視訊畫面存成 BMP 檔案( capFileSaveDIB )

d. 取得與設定錄影參數
( capCaptureGetSetup, capCaptureGetSetup )

e. CAPTUREPARMS structure

2. 範例程式 Webcam Programming (3)

範例程式 Webcam Programming (3) 所設定的學習目標主要是靜態影像擷取與動態視訊錄影之實作。分成 3 個部分:
part A - 靜態影像擷取
part B - 錄影參數之取得與設定
part C - 錄影控制

part A - 靜態影像擷取


關於靜態影像擷取, 我們針對 VFW 所提供的 4 個函式, 分別使用 4 個 TButton 元件, 如圖 3-A-1 。當使用者按下 Button 時, 就會啟動相關的事件處理程序執行函式。程式內容詳見範例程式 Webcam Programming (3)


圖 3-A-1

當使用者按下 Grab Frame 的 Button 時, 視訊擷取視窗的畫面會暫時靜止, 以便讓使用者觀看所擷取的畫面內容, 如圖 3-A-2。


圖 3-A-2

當使用者按下 Edit Copy 的 Button 時, 視訊擷取視窗的畫面會被複製到剪貼簿之中, 使用者可以從其他的應用程式中, 使用 Ctrl-V "貼上", 就可將剪貼簿中的畫面內容貼到影用程式之中。圖 3-A-3 是使用Windows所提供的小畫家, 貼上剪貼簿內容所呈現的結果。


圖 3-A-3

當使用者按下 File Save DIB 的 Button 時, 視訊擷取視窗的畫面會被存成所設定的 bmp 檔案, 圖 3-A-4 所顯示的是使用 File Save DIB 按鈕所儲存的 bmp 檔案內容。


圖 3-A-4

part B - 錄影參數之取得與設定

要將視訊擷取視窗的畫面錄影成視訊檔案之前, 必須先設定各個相關的錄影參數, 由於所需設定的參數太多, 因此, 在 vfw.h 之中, 將各個錄影參數集合起來, 定義了一個結構資料型態 CAPTUREPARMS structure, 方便程式設計師宣告使用。在範例程式 Webcam Programming (3) 之中, 宣告 cpCaptureParms 為 CAPTUREPARMS 資料型態。

CAPTUREPARMS cpCaptureParms;

關於錄影參數的取得與設定, 我們提供了 3 個版本的範例程式:
版本 1 : 所有的錄影參數都用 TLabel 元件顯示在 pcWebcam TPageControl 元件的 tsCaptureParameter 分頁之中, 如圖 3-B-1。


圖 3-B-1

版本 2 : 將錄影參數中, 屬於布林資料型態的參數改成使用 TCheckBox 元件顯示, 使用者可以直接點選更改設定, 如圖 3-B-2。


圖 3-B-2

版本 3 : 將錄影參數中, 屬於整數資料型態的參數改成使用 TEdit 元件顯示, 使用者可以直接輸入更改設定, 如圖 3-B-3。


圖 3-B-3

參考資料:







星期一, 10月 08, 2012

Week 5: Webcam Programming (2)

1. VFW 函式介紹:

a. 視訊參數對話盒 ( Video Dialog Box )

(1) 視訊來源對話盒 ( capDlgVideoSource ):
視訊來源對話盒的功能主要有 3 項: 選擇不同的視訊信號輸入、調整視訊輸入的色調、對比、亮度、飽和度、清晰度... 及調整視訊類比訊號轉成數位訊號的品質設定。
(2) 視訊格式對話盒 ( capDlgVideoFormat ):
透過視訊格式對話盒可以設定視訊裝置擷取的畫面解析度、選擇像素位元深度及壓縮。
(3) 視訊顯示對話盒 ( capDlgVideoDisplay )
若視訊裝置驅動程式提供視訊顯示對話盒, 使用者就可以設定輸出到顯示螢幕的色調、對比、亮度、色彩校正等相關內容,但大部分的 USB 攝影機驅動程式都沒有提供視訊顯示對話盒。
(4) 視訊壓縮對話盒 ( capDlgVideoCompression )
如果電腦安裝了多種視訊壓縮程式,就可以透過視訊壓縮對話盒來選擇所要使用的視訊壓縮程式及其相關設定。

b. 取得視訊擷取視窗狀態 ( capGetStatus )

c. TCapStatus structure

2. 範例程式 Webcam Programming (2)

範例程式 Webcam Programming (2) 所設定的學習目標是了解視訊裝置驅動程式所提供的功能與掌握視訊擷取視窗的狀態。分成 3 個部分:
part A - 取得視訊裝置驅動程式的效能
part B - 開啟各種視訊參數對話盒
part C - 取得視訊擷取視窗狀態

part B - 開啟各種視訊參數對話盒


圖 2-A-4

圖 2-A-4 中的 Dialog 功能列共有 4 項開啟視訊參數對話盒, 所對應的事件處理程序請參考範例程式 Webcam Programming (2), 當程式執行 Webcam | Driver | Capacities 之後, 四項功能表中, 如果驅動程式沒有提供的對話盒會直接被 disable 掉, 如圖 2-A-5。


圖 2-A-5

從 Capacities 所顯示的訊息中, 可以得知驅動程式並沒有提供視訊顯示對話盒。因此功能表中的 Video Display 功能已經被 disable 掉了, 如圖 2-A-6 。


圖 2-A-6

下面三個圖則是分別開啟的視訊來源對話盒、視訊格式對話盒、視訊壓縮對話盒。


圖 2-B-1 視訊來源對話盒


圖 2-B-2 視訊格式對話盒


圖 2-B-3 視訊壓縮對話盒

値得一提的是, 當電腦安裝了任何的視訊編碼器之後, 在視訊壓縮對話盒中就會自動加入所安裝的編碼器供你選擇與進行細部壓縮設定。這邊推薦一個屬於開放原始碼的 MPEG 4 Codec - Xvid 供大家安裝與使用, 關於 Xvid 的相關說明, 詳見維基百科 Xvid 條目。下圖是安裝後, 視訊壓縮對話盒已經提供 Xvid MPEG-4 Codec 的選項了。


圖 2-B-4 視訊壓縮對話盒提供 Xvid MPEG-4 Codec 選項

part C - 取得視訊擷取視窗狀態

請同學利用上課實作時間, 參考 part A 自行完成 part C!
暫不提供範例程式。





首先, 在 tsInformation 分頁中, 新增 18 個 TLabel 元件, 用來顯示視訊擷取視窗的狀態(Capture Window Status), 如圖 2-C-1。注意! hPalCurrent 是用來記錄目前所使用調色盤的 handle, 因此沒有將其顯示出來。


圖 2-C-1

接著, 在 Webcam | Capture Window 功能表中, 新增 Status 子功能, 如圖 2-C-2。


圖 2-C-2

最後, 執行 Webcam | Capture Window | Status 將會顯示視訊擷取視窗的狀態, 如圖 2-C-3。


圖 2-C-3

星期一, 10月 01, 2012

Week 4: Webcam Programming (2)

1. VFW 函式介紹:

a. 調整視訊畫面大小 ( capPreviewScale )

b. 取得視訊裝置驅動程式的效能 ( capDriverGetCaps )

c. 視訊參數對話盒 ( Video Dialog Box )

(1) 視訊來源對話盒 ( capDlgVideoSource )
(2) 視訊格式對話盒 ( capDlgVideoFormat )
(3) 視訊顯示對話盒 ( capDlgVideoDisplay )
(4) 視訊壓縮對話盒 ( capDlgVideoCompression )

2. 範例程式 Webcam Programming (1) 分成 3 個部分:
part A - 取得視訊裝置驅動程式的相關資訊
part B - 將網路攝影機所擷取到的畫面放到視訊擷取視窗顯示出來
part C - 更改視訊擷取視窗的大小

本週我們將介紹 Part C 的部分:

part C - 更改視訊擷取視窗的大小


圖 1-B-7

上圖是範例程式 Webcam Programming (1) Part B 的執行結果, 視訊結取視窗動態地顯示了網路攝影機所拍攝的畫面。

上週課程結束前, 我們讓同學思考一個問題, 就是將的視訊擷取視窗的大小改成 640*480, pnlCaptureWindow 的 width 改成 650, Height 改成 490, 執行後的畫面如下圖。


圖 1-C-1

你知道發生什麼事嗎?

提示: 比較圖 1-B-7 與圖 1-C-1 兩張圖片的拍攝內容!

比較兩張圖片的內容後, 發現圖 1-B-7 的內容為圖 1-C-1 內容的左上角 1/4 的圖片內容。

因此, 攝影機所拍攝的畫面大小如果比所建立的視訊擷取視窗還要大, 就會只有顯示左上角的部分, 並不會完整顯示所拍攝的畫面內容。


圖 1-C-2

圖 1-C-2 是網路攝影機與所拍攝物品的位置圖, 從攝影機所瞄準的角度觀察, 木雕鳥確實不是攝影機所瞄準的, 圖 1-B-7 畫面所呈現的, 木雕鳥位於畫面的正中央其實是只顯示左上角 1/4 所呈現的錯覺。

VFW 提供了一個函式 capPreviewScale , 可以解決攝影機畫面大小與視訊擷取視窗大小不相同的問題。除此, 搭配 Win32 API 的 MoveWindow 函式來調整視訊擷取視窗的大小, 就可以依照需求隨時調整視訊擷取視窗的大小, 畫面也會依照視窗大小隨著縮放, 而不會只顯示部分拍攝畫面。

首先, 在 Webcam 功能表中新增 Preview Scale 的功能, 然後新增 On 與 Off 兩個子功能, 如下圖。


圖 1-C-3

Preview Scale | On 與 Preview Scale | Off 的事件處理程序請參閱範例程式 Webcam Programming (1), 執行 Preview Scale | On 之後, 網路攝影機所拍攝的畫面就會隨著視訊擷取視窗大小的變化而調整。

接著, 在 WebCam 功能表的 Capture Window 子功能中新增一個 Size 子功能, 然後在 Size 子功能之下, 再進一步建立新一層子功能, 分別是 320 * 240 與 640 * 480, 如下圖。


圖 1-C-4

同樣地, 請參閱 Webcam Programming (1) 中, 兩個子功能 Webcam | Capture Window | Size | 320 * 240 與 Webcam | Capture Window | Size | 640 * 480 的事件處理程序。下圖是執行 Preview Scale | On 之後, 接著再更改視訊擷取視窗的大小為 320 * 240, 我們可以看到不但視訊擷取視窗變小了, 畫面中的內容也跟著縮小了, 不再像圖 1-B-7 般, 只有左上角的畫面了。


圖 1-C-5

3. 範例程式 Webcam Programming (2)


範例程式 Webcam Programming (2) 所設定的學習目標是了解視訊裝置驅動程式所提供的功能與掌握視訊擷取視窗的狀態。分成 3 個部分:
part A - 取得視訊裝置驅動程式的效能
part B - 開啟各種視訊參數對話盒
part C - 取得視訊擷取視窗狀態

part A - 取得視訊裝置驅動程式的效能

由於範例程式 Webcam Programming (2) 需要顯示較多的資訊, 因此, 我們修改畫面的顯示方式, 從 Tool palette 中的 win32 分群中, 找到 TPageControl 類別, 新增一個 PageControl 元件到 Form1 之中。PageControl 元件的 Property Name 設定為 pcWebcam; Property Height 設定為 540; Property Width 設定為 730。接著, 在點選 PageControl pcWebcam 元件之後, 用滑鼠右鍵依序新增兩個 pages。第 1 個 page 的 Property Name 設定為 tsCaptureWindow, Property Caption 設定為 Capture Window; 第 2 個 page 的 Property Name 設定為 tsInformation, Property Caption 設定為 Information。

完成上述的設定之後, 就可以開始將各種元件放置到各個分頁之中。首先, 我們將原先放置於 Form1 之中的 pnlCaptureWindow 移到 tsCaptureWindow 分頁之中 (利用 Ctrl+X, Ctrl+V 就可以移入), 如圖 2-A-1。圖 2-A-1 中的 pnlCaptureWindow 的 Property Color 我們已經更改為淡綠色, 讓同學容易分辨。


圖 2-A-1

然後將 lblDriverDescription, lblCapDriverName, lblCapDriverVer 等 3 個 Labels 移到 tsCaptureWindow 分頁之中。最後, 再新增 7 個 Labels 作為顯示驅動程式效能之用, 如圖 2-A-2。


圖 2-A-2

接著, 在 MainMenu1 產生第二列功能表 Dialog, 一共有 4 個功能(MenuItem), 做為分別開啟 Video Source、Video Format、Video Display、Video Compression 等 4 個對話盒(dialog) 之用, 如圖 2-A-3。


圖 2-A-3

透過 capDriverGetCaps 函式可以掌握是訊裝置的效能為何? 驅動程式提供了什麼對話盒供使用者調整視訊裝置? 在 vfh.h 之中, 宣告了 tagCapDriverCaps 結構資料型態, 因此, 我們可以在公共變數宣告的區域中, 宣告一個 tagCapDriverCaps 資料型態的變數, 做為驅動程式傳遞訊息給我們的橋樑。當程式成功地呼叫了 capDriverGetCaps 函式後, 所宣告的結構變數中, 就會被存放著代表驅動程式效能的各種參數值了。

我們在 WebCam | Driver 功能列中新增一個 Capabilities 子功能, 如圖 2-A-4, 其對應的事件處理程序請參閱 Webcam Programming(2) 的 part A 部分。


圖 2-A-4

圖 2-A-5 為 Webcam | Driver | Capabilities 功能執行後的顯示內容, 我們發現此攝影裝置的驅動程式並沒有提供 Video Display Dialog。


圖 2-A-5


圖 2-A-6