• 沒有找到結果。

應用程式使用 Filter 的方法

第五章 實驗介紹與結果

5.2 應用程式使用 Filter 的方法

當 Filter 開發完成後,最重要的是如何使用這個 Filter,所以本節將詳細 介紹如何使用我們開發出來的人臉偵測 Filter 來撰寫應用程式。首先當我們開 發完一個 Filter 時可以先透過 GraphEdit 調試看看這個 Filter 的功能正不正 常,而 GraphEdit 是由 DiectShow SDK 所提供的一個調試工具,如圖 5-13 所示 就是我們透過 GraphEdit 調試的結果

65

圖 5-13 GraphEdit 調試

在這個調試中,我們可以把 GraphEdit 看成是一個 Filter Graph Manager,

而我們要在這個 Graph 上拉出一條 Filter chain 去執行我們所要求的任務。所 以一開始拉一個視訊 Camera 當作 Source Filter,來為我們提供影像資訊來源,

接著連接我們開發好的人臉偵測的 Transform Filter,為我們對影像資訊做人 臉偵測的處理,最後再接一個 Video Render 來為我們顯示影像結果在螢幕上,

再來按下 play the graph 就可以開始看這整個功能是否正常,結果如預期是有 辦法徵測出人臉的位置,所以透過調試可以知道我們的 Filter 是正常可用的。

那就可以把我們的 Filter 拿給應用程式人員使用,而我們會給程式人員一個 Filter 的註冊檔(FDFilter.ax),以供他註冊使用,並且給他 Filter 的 CLSID(或 者他註冊後自行到註冊表查詢),供他在撰寫程式時呼叫 Filter 使用,前置準備 完成就可以來介紹如何開發應用程式。

要使用 Filter 開發當然要先建立一個 Filter Graph Manager 來幫我們管理 Filter,而且也要把我們會使用到的 Filter 都建立出來,以方便我們後續使用

66

而這些建立工作的程式碼如圖 5-14 所示

Filter Graph Manager 建立

視訊裝置建立

FaceDetect Filter 建立

圖 5-14 建立 Filter 程式碼 第一步:建立 Filter Graph Manager

透 過 CoCreateInstance 可 以 幫 我 們 呼 叫 建 立 COM 元 件 , 所 以 我 們 使 用 CoCreateInstance 來呼叫建立 Filter Graph Manager。

第二步:建立用到的 Filter

首先建立 Source Filter,而我們的 Source Filter 是視訊 Camera 硬體設備,

而要建立硬體設備需要透過 DirectShow 提供的 SystemDeviceEnum 這個系統設備 枚舉器來幫我們找到這個視訊設備,其用法就是先建立系統設備枚舉器,再來透 過 CreateClassEnumerator 函式來告知枚舉器我們要在那一個屬性的資料下做 搜尋,而這邊我們需求是視訊裝置,所以我們是在 VideoInputDevice 下做查找,

當設定好之後就可以開始使用 Next 做逐一的查找動作,那因為本電腦只有一個 VideoInput 的設備所以只會找到唯一一個裝置就是我們所要的,不然如果有很 多裝置就要再做一些判斷裝置名字的動作才能找到想要的那個裝置,而找到之後

67

透過 BindToObject 函式就會幫我們把硬體裝置建立起來。接著呼叫我們的 FaceDetect Filter 以及 Render Filter 就只要透過 CoCreateInstance 即可完 成。到這裡所有要使用的 Filter 都建立完成,接下來就要實現串接的動作,其 程式碼如圖 5-15 所示

取得 Source Filter 的輸出 Pin

取得 FaceDetect Filter 的輸入 Pin 與 Source Filter 的輸出 Pin 做連 接

圖 5-15 Filter 串接程式碼 第三步:添加 Filter 到 Filter Graph Manager

待連接的 Filter 必須處於同一個 Filter Graph Manager 中才能進行連接,所以 一開始要先透過 AddFilter 把要連接的 Filter 通通都加到 Filter Graph Manager 裡面。

第四步:Filter 連接

Filter 連接的基本流程就是三個步驟,取得 Pin、判斷 Pin、連接 Pin。以 Source

68

Filter 與 Transform Filter 連接為例,首先以 EnumPins 函式來建立 Pin 枚舉 器,接著再以 Next 來取得 Pin,因為 Source 只有一支 Pin 為輸出 Pin,所以我 們就無須再判斷取得的 Pin 是否為輸出 Pin,但 FaceDetect Filter 有兩支 Pin 一支輸出 Pin 一支輸入 Pin,所以當我們用 Next 取得 Pin 時,還要加以判斷是 否為我們所需要的輸入 Pin,而透過 PIN_INFO 結構裡面的 PIN_DIRECTION 成員 就可以幫助我們判斷是否為輸入 Pin,判斷出輸入 Pin 之後,就可以使用 Connect 函式以 Source Filter 的輸出 Pin 和 FaceDetect Filter 的輸入 Pin 作為參數完 成 Filter 之間連接的動作,用同樣的方法也可以把 FaceDetect Filter 跟 Render Filter 連接起來。

接著我們來介紹如何把視訊視窗嵌入到我們的應用程式視窗,以及 Filter Graph Manager 如何管理狀態,程式碼實現如圖 5-16 所示

圖 5-16 嵌入視訊視窗程式碼 第五步:管理狀態

我們透過 Filter Graph Manager 的 QueryInterface 為我們建立 IMediaControl 這個介面,而 IMediaControl 這個介面提供三個 API 給我們去執行 Graph 的三 種狀態,分別是 Run(Play the graph)、Pause(Pause the graph)、Stop(Stop the graph),因此我們就可以藉由這個介面去管理我們 Graph 的狀態。

69

第六步:嵌入 Render 視窗

透過 Filter Graph Manager 的 QueryInterface 為我們建立 IVideoWindow 這個 介面,這個介面就是提供給我們把 Filter Graph 的結果視窗嵌入到我們的應用 程式視窗中,這個介面有提供很多 API 讓我們可以輕易的去設定視窗,以下介紹 這些 API 的功能

¾ put_Owner : 設定要嵌入的視窗

¾ put_WindowStyle : 設置視窗的風格特性

¾ put_Left : 設置視窗 X 軸起始座標

¾ put_Top : 設置視窗 Y 軸起始座標

¾ put_Width : 設置視窗寬度

¾ put_Height : 設置視窗高度

¾ put_Visible : 顯示或隱藏視窗,OATRUE 代表顯示,OAFALSE 代表隱藏 設 置 好 嵌 入 的 視 窗 之 後 , 我 們 的 應 用 程 式 就 算 完 成 , 接 著 只 要 使 用 IMediaControl 這個介面來把狀態轉換成 Run 的形態就會開始在我們設定好的視 窗中播放處理好的視訊畫面,而且在這個應用程式中我們還實現了 Pause 以及 Stop 的狀態按鍵,這兩個按鍵也是簡單的用 IMediaControl 介面的 Pause 以及 Stop 的 API 就可以實現。如圖 5-17 就是應用程式開發完成的結果圖示。

圖 5-17 應用程式實驗結果

70