EmguCV 2.3 Application Programming : Processing Images with Classes
參考OpenCV 2 Computer Vision Application Programming Cookbook第三章
本篇介紹如下:
Using the Singleton design pattern
Using the Model-View-Controller architecture to design an application
Using the Singleton design pattern
上一篇介紹利用一個簡單的UI介面來操作顏色偵測
Singleton 是另一個相當常見的設計模式
通常翻譯成:獨體模式
Singleton的使用可以幫助方便存取class的instance
並且在program的執行中只會對此class產生一個instance
在這邊利用Singleton的實作,來存取上一篇提到的Controller物件
首先在ColorDetectorController中加入一個private的static成員
private static ColorDetectorController Singleton=null;Singleton用來維持一個class的instance
再來要提供一個取得instance的方法
而這個方法必須確保只會建立這個class的instance一次!
採用static的方法來建立class的instance
其中必須判斷是否已經建立過instance了
//Gets access to Singleton instance public static ColorDetectorController GetInstance() { //create the instance at first call if (Singleton == null) Singleton = new ColorDetectorController(); return Singleton; }先判斷Singleton是否為null
如果是才建立此class的instance,並回傳此instance
這邊要注意的是
這樣的寫法並不是thread-safe
如果要應付多個thread要有所改變,這裡先暫不討論!
//Releases the singleton instance of this controller. public static void Destroy() { if (Singleton != null) { //calls the dispose method of the singleton instance } Singleton=null; }由於C#無法直接delete instance
所以在if判斷式裡面
可以去呼叫此instance的dispose方法(如果有的話)
(或是任何釋放使用資源的方法)
這樣就完成了!
這時候要使用ColorDetectorController的class
都可以透過GetInstance()來存取ColorDetectorController的instance
就算有多個class要使用ColorDetectorController
也能保證只會建立一個ColorDetectorController的instance
在上一篇介紹的Chapter3Form在使用ColorDetectorController時就要做一些修改
這時候原本的區域成員_Controller就可以拿掉了
ColorDetectorController _Controller;這行可以刪掉了!!
原本有使用到此成員的地方都要做修正
依序把OpenButton_Click跟ProcessButton_Click改一改
private void OpenButton_Click(object sender, EventArgs e) { if (OpenFile.ShowDialog(this) == DialogResult.Cancel) { return;// User selects nothing } String imagePath = OpenFile.FileName; //Set the input image ColorDetectorController.GetInstance().SetInputImage(imagePath); //Show the input image CvInvoke.cvShowImage("Input Image", ColorDetectorController.GetInstance().GetInputImage()); }OpenButton_Click修正如上
所有之前參考_Controller的地方都要改成ColorDetectorController.GetInstance()
private void ProcessButton_Click(object sender, EventArgs e) { //Target color is hard-code here ColorDetectorController.GetInstance().SetTargetColor(30, 30, 45); ColorDetectorController.GetInstance().Process(); //Show the output image CvInvoke.cvShowImage("Output Image", ColorDetectorController.GetInstance().GetLastResult()); }ProcessButton_Click修正如上
這時候使用ColorDetectorController,不必再去找方法create這個class
也不必考慮什麼時候create
反正需要用到的時候就用ColorDetectorController.GetInstance()來取得唯一的instance!
ColorDetectorController.Destroy();而在程式被關閉時就可以呼叫Destroy的方法
當Controller實作Singleton的設計模式時
任何class要去存取Controller都會變得相當容易
這時候如果要更嚴謹的實作這個應用程式(application)
就需要更慎密的GUI了
這時候就需要用到MVC架構
Using the Model-View-Controller architecture to design an application
Model-View-Controller簡稱MVC,在維基中有詳細的介紹
在之前的實作中,應該有發現三個很重要的設計模式:
Strategy,Controller,Singleton
而這裡介紹的MVC的架構,就使用了這三種設計模式來做整合
MVC架構的好處就是清楚的切割應用邏輯上的關係
相信維基上已經說明得相當清楚了!
這裡就直接來討論實做吧!!
來記得我們當初寫的ColorDetector的class吧
這就是屬於實作演算法的部分
也就是所謂的Model這層
接下來我們又實做了ColorDetectorController
負責轉發請求給ColorDetector,對請求進行處理
也就是Controller這層
由於Controller的關係,使得建立一個UI變得容易
而之前寫的Windows Form就是屬於View這層
所以其實之前的實作就是逐漸在建立一個MVC的架構
只是之前的方式在設定偵測顏色、顏色的threshold都是寫死在程式中
現在再把這邊好好改一下就OK了!!
由於這裡要選擇顏色
所以從工具箱中拉入一個叫做:ColorDialog的物件
並把這個物件重新命名成:ColorDialog
然後再加入一個選擇顏色的Button,命名:SelectButton
在button click的時候抓取顏色
private void SelectButton_Click(object sender, EventArgs e) { if (ColorDialog.ShowDialog() != DialogResult.Cancel) { Color color= ColorDialog.Color; ColorDetectorController.GetInstance().SetTargetColor(color.R, color.G, color.B); } }這樣會跳出一個視窗,選擇顏色
然後將顏色的Red、Green、Blue傳入之前寫的方法SetTargetColor
這樣顏色就設定完成!!
再來從工具箱加入一個TrackBar,命名:DistanceBar
並把Minimum的值設為0,Maximum設為255
然後加入一個Label讓它顯示:Color Distance Threshold
再用另一個Label,命名為DistanceValue,並把value設為0
在拉動TrackBar的時候把值設定給Controller
private void DistanceBar_Scroll(object sender, EventArgs e) { DistanceValue.Text = DistanceBar.Value.ToString(); ColorDetectorController.GetInstance().SetColorDistanceThreshold(DistanceBar.Value); }拉動的時候把值給DistanceValue這個Label,讓它顯示在畫面上
這樣使用者才知道拉到多少數值
再把拉到的數值傳給SetColorDistanceThreshold
之前的畫面顯示是跳出新的視窗來
這邊從工具箱加入一個PictureBox,命名為:PictureBox
設定好長、寬,拖拉到適合的位置
在OpenImage跟Process時,要把圖顯示在這個PictureBox上面
//Show the input image ColorDetectorController.GetInstance().GetInputImage()); PictureBox.Image = ColorDetectorController.GetInstance().GetInputImage().ToBitmap();把OpenButton_Click原本show圖的程式改成用PictureBox來顯示
//Show the output image PictureBox.Image = ColorDetectorController.GetInstance().GetLastResult().ToBitmap();把ProcessButton_Click原本show圖的程式改成用PictureBox來顯示
整體的GUI畫面會變成這樣
多了顯示畫面、Color Distance Threshold的設定bar、Select Color的按鈕
操作的情況如下:
按下Open Image選擇你要的圖檔,這時候就會直接顯示在GUI上
這時候按下Select Color的按鈕就會跳出調色盤,讓使用者可以自由的選擇顏色
拉動Bar去調整Color Distance Threshold的值
再按下Process的按鈕就會看到最後處理的結果!!
這樣一個簡單的顏色偵測應用程式就完成了!!
你也可以來試試看!!
沒有留言:
張貼留言