图像算法中的设计模式(二):用控制器设计模式实现功能模块间通信

在构建更复杂的程序时,你需要创建多个算法来协同工作,以实现一些高级功能。要合理地构建程序并让所有的类能互相通信,程序将会变得越来越复杂。因此在一个类中集中对程序进行控制,是非常有益的。这正是控制器设计模式背后的思想。

图像算法中的设计模式(一):使用策略模式设计算法 这篇博客里使用的颜色检测算法为例。设计一个Controller类,它的首要任务是创建执行程序所需的类。在这里只执行颜色检测这一算法,所以只有一个类,但更复杂的程序就会有多个类。
设计Controller类结构如下:

class Controller
{
private:
    ColorDetector cDetect;
    cv::Mat image;
    cv::Mat result;

public:
    Controller();
    void setTargetColor(uchar g, uchar b, uchar r);
    void setMaxDist(int dist);
    bool setInputImage(std::string filename);
    void process();
    cv::Mat getInputImage();
    cv::Mat getResultImage();
    ~Controller();
};
Controller::Controller()
{
    ColorDetector colorDetect;
    cDetect = colorDetect ;
}
void Controller::setTargetColor(uchar g, uchar b, uchar r) {
    cDetect.setTargetColor(g,b,r);
}

void Controller::setMaxDist(int dist) {
    cDetect.setMaxDist(dist);
}

bool Controller::setInputImage(std::string filename) {
    image = cv::imread(filename);
    return !image.empty();
}


void Controller::process() {
    result=cDetect.process(image);
}

cv::Mat Controller::getInputImage() {
    return image;
}

cv::Mat Controller::getResultImage() {
    return result;
}

Controller::~Controller()
{
}

可以看到,Controller类包含了所需的算法类,另外还有两个成员变量,作为输入和输出结果的引用。在Controller类中定义了设置和获取方法,通常它们只是简单地调用相关类中对应的方法。这个例子只用了一个算法类,但实际开发中通常会包含多个类。因此Controller的作用就是将请求重新定向到相关的类(在面向对象的编程中,这种机制成为委托)。
控制器模式简化了程序中类的接口,开发人员可以很容易地构建执行算法的程序接口。既不需要理解类与类是如何连接的,也不需要知道为了让所有类正确运行需要调用哪个类的哪个方法。所有的工作都由Controller类完成。开发者唯一需要做的,就是创建一个Controller类的实例。
Controller类的process方法运行算法。但是这个方法并不返回结果,想要得到最新的处理结果,需要调用另一个方法。
这里的Controller类也准备了应用开发者提供的数据,使用setInputImage方法会根据文件名,把图像装载进内存。

下面使用Visual Studio构建一个MFC对话框程序。首先将ColorDetector类和Controller类新创建进去。然后,只需要在对话框类中添加一个Controller类的成员变量,即可创建一个最基本的使用了控制器的对话框程序了。
这里写图片描述
创建两个按钮,一个用来选择图像,另一个用来启动处理,如下图所示:
这里写图片描述
两个按钮的消息处理函数如下:

void CMFCApplication1Dlg::OnBnClickedOpen()
{
    // TODO: Add your control notification handler code here
    CFileDialog dlg(TRUE, _T("*.bmp"), NULL, OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, _T("image files (*.bmp;*.jpg)| *.bmp; *.jpg|All Files(*.*)|*.*||"), NULL);
    dlg.m_ofn.lpstrTitle = _T("Open Image");

    //若选中了一个文件名
    if (dlg.DoModal() == IDOK) {
        std::string fileName = CStringA(dlg.GetPathName());

        if (controller.setInputImage(fileName)) {
            cv::imshow("Input Image", controller.getInputImage());
        }
    }
}
void CMFCApplication1Dlg::OnBnClickedProcess()
{
    // TODO: Add your control notification handler code here
    controller.setMaxDist(100);
    controller.setTargetColor(0, 150, 240);
    if (!controller.getInputImage().empty()) {
        controller.process();
        cv::Mat result = controller.getResultImage();
        cv::imshow("Output Result", result);

    }
}

运行结果:
这里写图片描述
如果程序更加复杂,显然会有更多的对话框来让用户选择算法的参数。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值