Instances Based on Opencv2: A Simple Analysis of MVC Architecture

A few months ago, one of my friends asked me for a favor that he wanted me to help him out with his digital recognition project. Fortunately, I had decided to go further for a master degree and I had plenty of time, moreover I was totally interested in computer vision, so I was happy to do him a favor.

Soon enough, I found some source code,which implemented two small projects, one of which was a small image processing system and the other was a digital recognition system based on the BP algorithm.The two small projects were implemented based on the MFC. Once I opened thesource code, I found there was a problem in the code organization, because it was kind of messy and totally hard to understand. As I have mentioned above,the two projects were implemented base on MFC which you can totally rely on to construct your own application, however, the implementation of the basic image processing algorithms and the BP algorithm should not have relied onthe MFC if one was considering the portability of some general algorithm’simplementations. But in the two projects’ source code, the implementation of thebasic image processing algorithms and the BP algorithm was somewhat relied onthe MFC, so I decided to extract the basic algorithms out of the original version and implement them using standard C++ language while learning the theoryof these algorithms.

Actually the thinking I was doing a few months ago is a matter of Design Pattern, and in the recent couple of days I was learning to do secondary development using opecv which is a famous opensource computer vision library, the same question came out again, so I decide to give a close thinking about it and write it down in detail.

Now I would like firstly analysis the architecture MVC in two aspects one of which is its advantage and the other is its essenceand then give an example of using MVC based on opencv version 2.

The most important advantage of the MVC architecture is that it has the objective of producing an application that clearly separates the application logic from the user interface. MVC stands for ModelView Controller in short and clearly it consists of three parts which could bedemonstrated as follows:

The Model contains the information concerning the application. It holds all of the data that is processed by the application.When new data is produced, it will inform the Controller, which in turn willask the view to display the new results. Often, the Model will group together several algorithms, possibly implemented following the Strategy pattern. All ofthese algorithms are part of the Model.

The View corresponds to the user interface. It is composed ofthe different widgets that present the data to the user and allow the user to interact with the application. One of its roles is to send the commands issued by the user to the Controller. When new data is available, it refreshes itself in order to display the new information.

The Controller is the module that bridges the View and theModel together. It receives requests from the View and relays them to the appropriate methods in the model. It is also informed when the Model changes its state, and consequently asks the View to refresh in order to display this new information.

The true essence of the MVC architecture is that it uses Strategy Pattern to build bond of the Model with the Controllerand the Controller with the View, meanwhile clearly build the separation between the Model and the View This bond and separation building could be vividly expressed using the following example base on the opencv version 2. Thefollowing content consists of main two parts: using Strategy Pattern to build bond and separation in MVC, using Singleton to design the Controller.

Using Strategy Pattern to build bond and separation in MCV

What is Strategy Pattern?

The Strategy Pattern could be described using the following picture.

The key structure here is to capsule thelogic abstract interface(DoAction()) of algorithms in the class Context, andthen delegate the implementation of algorithms to the class Strategy. Now wecan use it to build bond between classes.

Using Strategy Pattern to build bond between classes

Firstly we construct the Model class ColorDetectorModelbased on opencv version 2. The ColorDetectorModel class is an instance of the right part(Strategy) in the Strategy Pattern describing picture above, but itis simpler, because it does not use the inherit feature of object orientated programming, but it is ok for us to understand. The ColorDetectorModel builds a simple algorithm that will identify all of the pixels in an image which have agiven color. The algorithm has then to accept an image and a color as input and returns a binary image showing the pixels having the specified color.

classColorDetectorModel{

private:

//minimum acceptable distance

intminDist;

//target color

cv::Vec3b target;

//image containing resulting binary map

cv::Mat result;

//Computes the distance from target color.

intgetDistance(const cv::Vec3b&color)const{

returnabs(color[0]-target[0])+

abs(color[1]-target[1])+

abs(color[2]-target[2]);

/*

Euclideannorm of a vector

returnstatic_cast<int>(

cv::norm<int,3>(cv::Vec3i(color[0]-target[0],

color[1]-target[1],

color[2]-target[2])));

*/

/*

returnstatic_cast<int>(

cv::norm<uchar,3>(color-target);

*/

}

public:

//empty constructor

ColorDetectorModel(): minDist(100) {

//default parameter initialization here

target[0]=target[1]= target[2]= 0;

}

//Sets the color distance threshold.

//Threshold must be positive,

//otherwise distance threshold is set to 0.

voidsetColorDistanceThreshold(intdistance){

if(distance<0)

distance=0;

minDist=distance;

}

//Gets the color distance threshold

intgetColorDistanceThreshold() const {

returnminDist;

}

//Sets the color to be detected

voidsetTargetColor(unsignedcharred,

unsignedchargreen,

unsignedcharblue){

//BGR order

target[2]=red;

target[1]=green;

target[0]=blue;

}

//Sets the color to be detected

voidsetTargetColor(cv::Vec3bcolor){

target=color;

}

//Gets the color to be detected

cv::Vec3b getTargetColor() const{

returntarget;

}

cv::Mat process(const cv::Mat &image) {

//re-allocate binary map if necessary

// samesize as input image, but 1-channel

result.create(image.rows,image.cols,CV_8U);

// getthe iterators

cv::Mat_<cv::Vec3b>::const_iteratorit=

image.begin<cv::Vec3b>();

cv::Mat_<cv::Vec3b>::const_iteratoritend=

image.end<cv::Vec3b>();

cv::Mat_<uchar>::iterator itout=

result.begin<uchar>();

// foreach pixel

for( ; it!= itend; ++it, ++itout) {

//process each pixel ---------------------

//compute distance from target color

if(getDistance(*it)<minDist) {

*itout= 255;

} else{

*itout= 0;

}

// endof pixel processing ----------------

}

returnresult;

}

};

Secondly, we construct the Controller class ColorDetectorController based on opencv version 2. The ColorDetectorController class is an instance ofthe left part(Context) in the Strategy Pattern describing picture above.

classColorDetectorController{

private:

//the algorithm class

ColorDetectorModel *cdetect;

cv::Mat image; // The image to be processed

cv::Mat result; // The image result

public:

ColorDetectorController(){

//settingup the application

cdetect=newColorDetectorModel();

}

//Sets the color distance threshold

voidsetColorDistanceThreshold(intdistance){

cdetect->setColorDistanceThreshold(distance);

}

//Gets the color distance threshold

intgetColorDistanceThreshold() const {

returncdetect->getColorDistanceThreshold();

}

//Sets the color to be detected

voidsetTargetColor(unsignedcharred,

unsignedchargreen,unsignedcharblue){

cdetect->setTargetColor(red,green,blue);

}

//Gets the color to be detected

voidgetTargetColor(unsignedchar&red,

unsignedchar&green, unsignedchar&blue) const{

cv::Vec3b color= cdetect->getTargetColor();

red=color[2];

green=color[1];

blue=color[0];

}

//Sets the input image. Reads it from file.

boolsetInputImage(std::stringfilename){

image=cv::imread(filename);

if(!image.data)

returnfalse;

else

returntrue;

}

//Returns the current input image.

constcv::Mat getInputImage() const{

returnimage;

}

//Performs image processing.

voidprocess() {

result=cdetect->process(image);

}

//Returns the image result from the latest processing.

constcv::Mat getLastResult() const{

returnresult;

}

//Deletes processor objects created by the controller.

~ColorDetectorController(){

deletecdetect;

}

};

We can easily tell from the implementation of the ColorDetectionController that making an instance of theColorDetectionModel class as a member of the class ColorDetectionController is to build bond between the two classes. When we call the public functions of the ColorDetectionController class, it simply delegates requests to the object of the ColorDetectionModule class.

Using Strategy Pattern two times to build separation betweenclasses

Very much similar to the previous steps of building bond between classes using Strategy Pattern, we construct the Viewclass ColorDetectorView as below. However, this ColorDetectorView class is simply a demo to illustrate the usage of Strategy Pattern and it is not usable,but if you are familiar with MFC based application development then it is easy for you to understand the ColorDetectorView class and adjust it to theProjectNameView.h and ProjectNameView.cpp files of one of your MFC based applications, also you could use it to QT based applications if you have some requests of it. And from the ColorDetectorView class we can clearly see that it is separated from the ColorDetectorModel class, if you make some changes to the implementation ofthe basic algorithms in the ColorDetectorModel class, it will not affect theColorDetectorView class.

class ColorDetectorView {

private:

ColorDetectorControllercolordetect;

public:

//Callback method of "Open" button.

voidOnOpen()

{

//MFC widget to select a file of type bmp or jpg

CFileDialogdlg(TRUE, _T("*.bmp"), NULL,

OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,

_T("imagefiles (*.bmp; *.jpg)|*.bmp;*.jpg|All Files (*.*)|*.*||"),NULL);

dlg.m_ofn.lpstrTitle=_T("Open Image");

//if a filename has been selected

if(dlg.DoModal() == IDOK) {

//get the path of the selected filename

std::stringfilename= dlg.GetPathName();

//set and display the input image

colordetect.setInputImage(filename);

cv::imshow("InputImage",colordetect.getInputImage());

}

}

//Callback method of "Process" button.

voidOnProcess()

{

//target color is hard-coded here

colordetect.setTargetColor(130,190,230);

//process the input image and display result

colordetect.process();

cv::imshow("OutputResult",colordetect.getLastResult());

}

};

You may have noticed that there are some callback functions in the ColorDetectorView class, then, what is a callbackfunction?

Callback function is a function that could only be called bya function pointer which point to a certain function. It could be used when youpass a function pointer as a parameter to another function in the body of which it uses the function pointer parameter to call the function to which the functionpointer pointed.

Callback functions are not called by their implementers, but bysome other sides, the operating system for instance. Applications on the WindowsOperating System, is based on the message mechanism. The operating system Windows captures the users action and capsules the action in the message struct and put it into the message queue which is continuing with the kernel of Windows, then the application gets message, translates message, and dispatches message, after this the operating system will decide which callback function should be called,however the implementation of callback function should be done by the application developer. If you ever wrote an application based on the Win32 API,you should be very much familiar with it.

Using Singleton Pattern to design the Controller

Sometimes we want to control the number of objects in an application, because more objects mean more cost of resource of the system. For example, if only single one object of the class ColorDetectorController meets the need of developing andapplication, then we should forbid making more than two objects of it, for we can carelessly do so. And this problem could be solved by using the SingletonPattern that is used to facilitate access to a class instance and also toguarantee that only one instance of that class will exist during program execution.There is an example bellow, and I have talked about it in another blog context in chinese at 7.3) here http://remyspot.blog.51cto.com/8218746/1555464.

//colorDetectorController.h file

class ColorDetectorController {

private:

//pointer to the singleton

staticColorDetectorController *singleton;

ColorDetector*cdetect;

//private constructor

ColorDetectorController(){

//settingup the application

cdetect=new ColorDetector();

}

//Gets access to Singleton instance

staticColorDetectorController *getInstance() {

//Creates the instance at first call

if(singleton == 0)

singleton=new ColorDetectorController;

returnsingleton;

}

//Releases the singleton instance of this controller.

staticvoid destroy() {

if(singleton != 0) {

deletesingleton;

singleton=0;

}

}

};

//colorDetectorController.cpp file

#include "colorDetectorController.h"

ColorDetectorController *ColorDetectorController::singleton=0;

class ColorDetectorView {

private:

ColorDetectorControllercolordetect;

public:

//Callback method of "Open" button.

voidOnOpen()

{

//MFC widget to select a file of type bmp or jpg

CFileDialogdlg(TRUE, _T("*.bmp"), NULL,

OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,

_T("imagefiles (*.bmp; *.jpg)|*.bmp;*.jpg|All Files (*.*)|*.*||"),NULL);

dlg.m_ofn.lpstrTitle=_T("Open Image");

//if a filename has been selected

if(dlg.DoModal() == IDOK) {

//get the path of the selected filename

std::stringfilename= dlg.GetPathName();

//set and display the input image

ColorDetectorController::

getInstance()->setInputImage(filename);

cv::imshow("InputImage",ColorDetectorController::

getInstance()->getInputImage());

}

}

//Callback method of "Process" button.

voidOnProcess()

{

//target color is hard-coded here

ColorDetectController::

getInstance()->setTargetColor(130,190,230);

//process the input image and display result

ColorDetectorController::getInstance()->process();

cv::imshow("OutputResult",

ColorDetectorController::getInstance()->getLastResult());

}

//Callback method of "Close" button.

voidOnClose()

{

//Releases the Singleton.

ColorDetectorController::getInstance()->destroy();

OnOK();

}

};

时间: 2024-12-25 06:44:03

Instances Based on Opencv2: A Simple Analysis of MVC Architecture的相关文章

Rendering a simple ASP.NET MVC PartialView using JQuery Ajax Post call

http://stackoverflow.com/questions/15466597/rendering-a-simple-asp-net-mvc-partialview-using-jquery-ajax-post-call Rendering a simple ASP.NET MVC PartialView using JQuery Ajax Post call,布布扣,bubuko.com

Analysis of Baidu search engine

Rencently, my two teammates and I is doing a project, a simplified Chinese search engine for children(in primary school). We call it "kidsearch". Since our project will be based on Baidu search engine. I'd like to have a simple analysis of Baidu

Progress and Prospect of target detection technology based on deep learning

Viola-Jones face detector One of the more successful examples of object detection in the whole computer field is the Viola-Jones face detector that appeared around 2000,which makes it a more mature technique compared to the object detection.The basic

Java性能提示(全)

http://www.onjava.com/pub/a/onjava/2001/05/30/optimization.htmlComparing the performance of LinkedLists and ArrayLists (and Vectors) (Page last updated May 2001, Added 2001-06-18, Author Jack Shirazi, Publisher OnJava). Tips: ArrayList is faster than

五.Classification (I) – Tree, Lazy, and Probabilisti

五.Classification (I) – Tree, Lazy, and Probabilistic 五.分类(I)-树,延迟,和概率 In this chapter, we will cover the following recipes: 在本章中,我们将介绍下列菜谱:准备培训和测试数据集 1.Preparing the training and testing datasets Introduction 介绍 Classification is used to identify a c

Draft-JSS模板

IEEEtran.cls 1 %% 2 %% IEEEtran.cls 2007/03/05 version V1.7a 3 %% 4 %% 5 %% This is the official IEEE LaTeX class for authors of the Institute of 6 %% Electrical and Electronics Engineers (IEEE) Transactions journals and 7 %% conferences. 8 %% 9 %% S

Optimizing Oracle RAC

Oracle Real Application Clusters (RAC) databases form an increasing proportion of Oracle database systems. RAC was introduced in 2001 as part of Oracle 9i and was based on Oracle's earlier Oracle Parallel Server architecture. RAC is almost unique as

kafka producer源码

producer接口: /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this

awesome-php中英文资源整理(同步更新)

中文版 收集整理一些常用的PHP类库, 资源以及技巧. 以便在工作中迅速的查找所需… 这个列表中的内容有来自 awesome-php 的翻译, 有来自开发者周刊以及个人的积累等. 一个前端组件的列表 awesome-frontend 推荐 学习资源 PHP相关的有参考价值的社区,博客,网站,文章,书籍,视频等资源 PHP网站(PHP Websites) PHP The Right Way – 一个PHP实践的快速参考指导 PHP Best Practices – 一个PHP最佳实践 PHP We