EmguCV 2.3 Application Programming : Processing Images with Classes
參考OpenCV 2 Computer Vision Application Programming Cookbook第三章
本篇介紹如下:
Using a Controller to communicate with processing modules
Using a Controller to communicate with processing modules
上一篇介紹了一個簡單的顏色偵測演算法的功能
如果想要建立一個複雜的應用程式
可能需要開發很多個不同的處理演算法
並使這些演算法能夠組合在一起
而完成一些比較進階的功能或任務
如何在應用程式上設定參數和屬性
並且能夠和所有的功能類別做有效的溝通
會變得越來越困難、越來越複雜
在單一個類別中能夠集中控制這些功能或屬性是複雜且進階的工作
(也就是如何設計一個好的人機介面!!)
這也就是一個控制器(Controller)所扮演的重要角色
首先先建立一個名為ColorDetectorController的類別
記得要參考上一篇所寫的專案或dll (ColorDetectot)、還有Emgu相關的dll
這裡需要擁有三個屬性_ColorDetector、_Image、_Result
class ColorDetectorController { private ColorDetector _ColorDetector; //the algorithm class private Image<Bgr, Byte> _Image; //input image private Image<Gray, Byte> _Result; //output result public ColorDetectorController() { this._ColorDetector = new ColorDetector(); } }然後還必須把一些控制屬性的方法建立一下
所需要的屬性控制大致如下:
//Sets the color distance threshold public void SetColorDistanceThreshold(int distance) { this._ColorDetector.MinDist = distance; } //Gets the color distance threshold public int GetColorDistanceThreshold() { return this._ColorDetector.MinDist; } //Sets the color to be detected public void SetTargetColor(double red, double green, double blue) { this._ColorDetector.Color = new Bgr(blue, green, red); } //Gets the color to be detected public void GetTargetColor(ref double red, ref double green, ref double blue) { red = this._ColorDetector.Color.Red; green = this._ColorDetector.Color.Green; blue = this._ColorDetector.Color.Blue; } //Sets the input image. Reads it from file. public bool SetInputImage(string filename) { this._Image = new Image<Bgr, byte>(filename); if (this._Image == null) return false; else return true; } //Returns the current input image. public Image<Bgr, Byte> GetInputImage() { return this._Image; }以上這些都是屬性的設定
透過方法的呼叫來處理
(當然這邊你也可以直接用C#的get、set的方式來實作)
當然還需要運作的方法:
//Performs image processing public void Process() { this._Result= this._ColorDetector.Process(this._Image); } //Returns the image result from the lastest processing. public Image<Gray, Byte> GetLastResult() { return this._Result; }透過上面兩個方法,就可以執行運算和取得最後結果的影像
使用這個Controller的類別
你可以輕易的替應用程式建立一個介面來執行你的演算法
應用程式的程式設計者
不必知道這些類別裡面的運作機制,之間彼此是怎麼連結
或是花時間去了解哪一個方法在哪一個類別裡,需要那些屬性等等
這些都在Controller裡面做完了
使用者只需要建立一個Controller的類別
在屬性的控制上
由於這個簡單的例子只包含一個ColorDetector的類別
所以看起來似乎有點多此一舉
但是在大部分的情況下
一個Controller不只控制單一個類別
這時候Controller的角色就要去做到透過簡單的介面
正確的把需要的屬性對應到某個類別中的屬性
(也就是redirect的動作)
像是例子中的SetTargetColor跟GetTargetColor這兩個方法
使用者不必知道Color的結構(Bgr、Gray)
而是透過三個double的變數來控制和取得
在某些時候Controller也需要提供一些介面
讓應用程式面的使用者來提供資料
像是例子中的SetInputImage,透過一個字串
來讓Controller取得目標影像
並回傳是否成功
最後來看看如何用一個簡單的dialog-based的方法
透過剛剛的ColorDetectController來運作
並以C#中的windows form來呈現
首先我們先建立一個window form的專案,名稱為:Chapter3Form
再透過工具列建立幾個按鈕
共有四個按鈕的windows form
這裡建立了四個Button
分別命名為:OpenButton、ProcessButton、OKButton、CancelButton
再分別將OpenButton的text屬性改成:Open Image
ProcessButton的text屬性改成:Process
OKButton的text屬性改成:OK
CancelButton的text屬性改成Cancel
就大致完成了如上圖的配置狀況
這時候我們還要加入一個叫做 OpenFileDialog 的類別進來
直接從工具列中找到直接拖拉到wondows form中即可
將其更改名稱為:OpenFile
拖拉進去然後修改名稱
然後再設定OpenFile的屬性Filter:Image Files (*.jpg, *.bmp)|*.jpg; *.bmp;
這樣在選擇檔案的時候就能過濾出影像的格式(jpg跟bmp)
這樣UI的配置大致上完成
剩下的就是程式碼的部分
而在程式碼中記得要參考剛剛Controller的專案或dll
把該參考的參考進去
private ColorDetectorController _Controller; public Chapter3Form() { InitializeComponent(); //Windows form initial this._Controller = new ColorDetectorController(); }然後加入Controller這個類別
在建構式的時候先建立
這時候再來控制Open Image的按鈕
先從讀取圖片開始
//Callback method of "OpenButton" button 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 this._Controller.SetInputImage(imagePath); //Show the input image CvInvoke.cvShowImage("Input Image", this._Controller.GetInputImage()); }讀取使用者選取的影像路徑
透過Controller的SetInputImage把路徑傳進去
並透過CvInvoke的函式:cvShowImage把影像呈現出來
再來看看Process的程式
private void ProcessButton_Click(object sender, EventArgs e) { //Target color is hard-code here this._Controller.SetTargetColor(30, 30, 45); this._Controller.Process(); //Show the output image CvInvoke.cvShowImage("Output Image", this._Controller.GetLastResult()); }這邊透過SetTargetColor來設定偵測的顏色
這邊的顏色設定目前是寫死的程式碼中
(下一篇會改善這個問題)
然後就執行Process
再把結果呈現出來,就大功告成!!
在使用Controller的情況下
應用程式的開發者不需要知道ColorDetector所需要的屬性是什麼
或是使用特殊的類別或結構,像是Image、Bgr、Gray等等
只要建立一個Controller的類別
知道他的方法如何使用即可
使用情況如下:
按下Open Image就會跳出選擇視窗,選擇你要的影像
注意右下方的檔案類型
就是當初設定的OpenFile的Filter的屬性
選擇完後,會跳出一個新視窗,影像就會被呈現出來
這個視窗的文字就是CvInvoke.cvShowImage的第一個引數:Input Image
(CvInvoke.cvShowImage("Input Image", this._Image);)
接著再按下Porcess
運作的結果一樣會透過一個新的視窗呈現
這樣就完成了一個簡單的顏色偵測的應用程式
下一篇會來修正GUI上的一些設計,讓介面更加的friendly
沒有留言:
張貼留言