图像算法中的设计模式(一):使用策略模式设计算法
2016-12-29 10:47
423 查看
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。总体来说,一个设计模式就是一个可重用的、让代码更容易被他人理解的、可靠性的解决方案。
策略设计模式的目的就是把算法封装进类。封装后,算法之间互相替换,或者把几个算法组合起来进行更复杂的处理,都会更加容易。而且这种模式能够尽可能地将算法的复杂性隐藏在一个直观的编程接口之后,因而有利于算法的部署。
本文以一个简单的算法设计为例:识别图像中具有某种颜色的所有像素。算法原理很简单,即对于一幅彩色图像,设其中某像素点的值为color1,待参考的目标颜色为color2;color1与color2都是具有3个元素的向量,求color1与color2之间的欧式距离distance;当distance小于一定阈值maxDist时认为该像素和参考目标像素相同,在输出结果图像中将其设为白色,反之设为黑色。
仅考虑算法实现,而不考虑设计模式,代码如下:
运行程序的结果:
输入图像
结果图像:
从这里开始引入“策略模式”。将上述颜色检测算法封装进一个策略类ColorDetector,这里先看一下封装完成后,部署和使用它的方法。
可以看出,层次清晰了很多,使用的时候只是调用了类对象的3个方法。
下面展示这个策略类的结构:
构造函数:
在运行构造函数时,类的实例会用默认值初始化算法的各种参数,以便它能立即进入可用状态。
还可以编写set和get方法来读写算法的参数值:
将算法执行过程封装进process方法:
可以看出,封装进这个类的算法相对简单。当算法的实现过程更加复杂,步骤繁多,并且包含多个参数时,策略设计模式会真正显示出强大的功能。
策略设计模式的目的就是把算法封装进类。封装后,算法之间互相替换,或者把几个算法组合起来进行更复杂的处理,都会更加容易。而且这种模式能够尽可能地将算法的复杂性隐藏在一个直观的编程接口之后,因而有利于算法的部署。
本文以一个简单的算法设计为例:识别图像中具有某种颜色的所有像素。算法原理很简单,即对于一幅彩色图像,设其中某像素点的值为color1,待参考的目标颜色为color2;color1与color2都是具有3个元素的向量,求color1与color2之间的欧式距离distance;当distance小于一定阈值maxDist时认为该像素和参考目标像素相同,在输出结果图像中将其设为白色,反之设为黑色。
仅考虑算法实现,而不考虑设计模式,代码如下:
#include"opencv2/opencv.hpp" #include"opencv2/core/core.hpp" #include"opencv2/highgui/highgui.hpp" #include<iostream> //计算两个颜色之间的欧式距离 float getColorDistance(const cv::Vec3b& color1,const cv::Vec3b& color2) { return cv::norm(color1,color2,cv::NORM_L2); } int main() { //打开图像并显示 cv::Mat image; image = cv::imread("56.jpg"); if (image.empty()) { //错误处理 std::cout << "图像打开发生错误"<<std::endl; return -1; } cv::namedWindow("Image"); cv::imshow("Image", image); //使用迭代器逐点比较与目标颜色的差距,并产生结果图像 cv::Mat result; result.create(image.size(), CV_8UC1); cv::Mat_<cv::Vec3b>::const_iterator it = image.begin<cv::Vec3b>(); cv::Mat_<cv::Vec3b>::const_iterator itend = image.end<cv::Vec3b>(); cv::Mat_<uchar>::iterator itout = result.begin<uchar>(); int MaxDist = 100; cv::Vec3b targetColor = cv::Vec3b(0, 150, 240); for (; it != itend; it++,itout++) { if (getColorDistance(*it, targetColor) <= MaxDist) { *itout = 255; } else *itout = 0; } //显示结果 cv::namedWindow("Result"); cv::imshow("Result", result); cv::waitKey(); return 0; }
运行程序的结果:
输入图像
结果图像:
从这里开始引入“策略模式”。将上述颜色检测算法封装进一个策略类ColorDetector,这里先看一下封装完成后,部署和使用它的方法。
int main() { //1.创建颜色检测算法类对象 ColorDetector cdetect; //2.读取输入图像 cv::Mat image; image = cv::imread("56.jpg"); if (image.empty()) { //错误处理 std::cout << "图像打开发生错误" << std::endl; return -1; } //3.设置输入参数 cdetect.setTargetColor(0,150,240); cdetect.setMaxDist(100); //4.处理图像并显示结果 cv::Mat result; result = cdetect.process(image); cv::namedWindow("Result"); cv::imshow("Result", result); cv::waitKey(); return 0; }
可以看出,层次清晰了很多,使用的时候只是调用了类对象的3个方法。
下面展示这个策略类的结构:
class ColorDetector{ private: cv::Vec3b targetColor;//目标颜色 int maxDist;//距离阈值 cv::Mat result;//结果图像 public: ColorDetector(); void setTargetColor(uchar g,uchar b,uchar r);//设置目标颜色 void setMaxDist(int dist);//设置距离阈值 float getColorDistance(const cv::Vec3b& color);//计算两个颜色之间的欧式距离 cv::Mat process(const cv::Mat& image);//封装整个算法处理过程 };
构造函数:
ColorDetector::ColorDetector():targetColor(cv::Vec3b(0,0,0)),maxDist(100) {}
在运行构造函数时,类的实例会用默认值初始化算法的各种参数,以便它能立即进入可用状态。
还可以编写set和get方法来读写算法的参数值:
//设置目标颜色 void ColorDetector::setTargetColor(uchar g,uchar b,uchar r) { targetColor = cv::Vec3b(g,b,r); } //设置距离阈值 void ColorDetector::setMaxDist(int dist) { if (dist < 0) dist = 0; maxDist = dist; }
将算法执行过程封装进process方法:
//计算两个颜色之间的欧式距离 float ColorDetector::getColorDistance(const cv::Vec3b& color) { return cv::norm(color, targetColor, cv::NORM_L2); } cv::Mat ColorDetector::process(const cv::Mat& image) { result.create(image.size(), CV_8UC1); cv::Mat_<cv::Vec3b>::const_iterator it = image.begin<cv::Vec3b>(); cv::Mat_<cv::Vec3b>::const_iterator itend = image.end<cv::Vec3b>(); cv::Mat_<uchar>::iterator itout = result.begin<uchar>(); for (; it != itend; it++, itout++) { if (getColorDistance(*it) <= maxDist) { *itout = 255; } else *itout = 0; } return result; }
可以看出,封装进这个类的算法相对简单。当算法的实现过程更加复杂,步骤繁多,并且包含多个参数时,策略设计模式会真正显示出强大的功能。
相关文章推荐
- OPENCV学习笔记3-1_算法设计中使用策略模式
- 在算法设计中使用策略模式
- 使用策略设计模式,反射,解决商城系统中的商品折扣问题
- OpenCV 2 学习笔记(10): 算法的基本设计模式<1>:策略模式(strategy pattern)
- Spring中使用到的设计模式 - 策略模式
- JAVA设计模式之策略模式的使用分析
- 举例讲解iOS应用开发中对设计模式中的策略模式的使用
- 浅学设计模式之策略<Strategy>模式及在android中的使用
- 策略设计模式:把可变的行为抽象出来形成一个算法簇
- 设计模式-代理模式与适配器模式实现代码重用以及策略模式的使用
- 设计模式之策略模式(使用C++)
- 设计模式实战(一)——使用策略模式(strategy pattern)实现多关键字排序
- OpenCV 2 学习笔记(13): 算法的基本设计模式<4> :使用Model-View-Controller模式创建一个应用程序
- 浅学设计模式之策略<Strategy>模式及在android中的使用
- 设计模式之使用Enum来实现strategy(策略模式系列2)
- 【设计模式】【策略模式 打折算法】
- Android使用的设计模式2——策略模式
- Android使用的设计模式2——策略模式
- android 策略设计模式使用
- 设计模式:策略模式(对象的某个行为,在不同的场景中,有不同的实现算法)