最近刚刚开始看《设计模式》,刚好最近也在从头开始OpenCV2,里面有讲到在图像算法设计中采用策略模式,照着例子实现了这个小demo,一下子明白所谓的策略模式倒底是个什么东东,这里mark一下。
策略模式(Strategy),用原书中的定义是:定义一系列的算法,把他们一个个的封装起来,并且是他们可以相互替换(相互替换这点还没有完全体会到)。这样算法的变换便可以独立于使用它的对象。用我直白的话说就是,把对一个对象(Context)进行处理的各种算法,封装到另外一个对象(Strategy)里面,这样我们便可以专注于Strategy,而不用担心修改算法的同时会对Context造成影响,只要这个Strategy还没有对Context起作用,我们对Strategy的改动都不会影响到Context,在实现的过程中省了好多心。
下面是一个小demo:
具体到这个demo中Strategy的实现是将对Mat(图片)处理的函数统统封装到一个类中,这里讲类中成员函数的声明和实现写在了一起。
/////////////////////////////////////////////////////////
//由strategy思想构造一个类
//类名:ColorDetector
//主要目的:检测一幅图像中是否存在目标颜色
/////////////////////////////////////////////////////////
#ifndef STRATEGY
#define STRATEGY
#endif // STRATEGY
#include
//#include
//#include
using namespace std;
using namespace cv;
class ColorDetector
{
public:
//空构造函数
ColorDetector():minDist(100){
//初始化默认参数
target[0]=target[1]=target[2]=0;
}
public:
//设置色彩阈值,阈值必须大于等于0
void setColorDistanceThreshold(int distance){
if(distance<0)
distance=0;
minDist=distance;
}
//获取色彩阈值
int getColorDistanceThreshold() const{
return minDist;
}
//设置需要检测的颜色
void setTargetColor(unsigned char red,unsigned char green,unsigned blue)
{
//BGR的顺序
target[2]=red;
target[1]=green;
target[0]=blue;
}
//设置需要检测的颜色
void setTargetColor(Vec3b color){
target=color;
}
//获取要检测的色彩值
Vec3b getTargetColor() const{
return target;
}
//计算目标与颜色的距离
int getDistance(const Vec3b &color)const{
return abs(color[0]-target[0])+abs(color[1]-target[1])+abs(color[2]-target[2]);
}
//检测目标颜色,并输出检测生成的图像
Mat process(const Mat &image){
//按需从新分配二值图像与输入图像尺寸相同,
result.create(image.size(),CV_8U);
//得到迭代器
Mat_::const_iterator it=image.begin ();
Mat_::const_iterator itend=image.end ();
Mat_::iterator itout=result.begin ();
//检测每个像素
for(;it!=itend;++it,++itout)
{
if(getDistance(*it)*itout=255;
else
*itout=0;
}
return result;
}
private:
//最小可接受距离
int minDist;
//目标色
Vec3b target;
//结果图像
Mat result;
};
封装好之后我们便能对调用它了,下面是调用Strategy类的实现:
#include最后说一下Qt中相对路径的问题,相对路径是相对工程根目录而言的,表达的格式是:“./resource/images/lena.jpg”,即在工程的根目录下有一个resource文件夹,resource内部有一个images文件夹,images内部有这幅图像lena.jpg。一开始我是将这幅图像放在了最开始建立工程时的文件夹下,发现找不到图片,其实Qt在build的过程中会根据是否勾选shadow build这一选项创建一个新的执行文件的目录。
#include "strategy.h"
#include
#include
#include
#include
using namespace cv;
using namespace std;
int main()
{
//创建图像处理对象
ColorDetector cdetector;
//Qt中当前路径显示
QDir dir;
QString pathname;
pathname = dir.currentPath();
qDebug()<
//读入图像
Mat image=imread("./resource/images/lena.jpg");
//Mat image=imread(path.toStdString().data());
if(!image.data)
return -1;
//设置输入参数
cdetector.setTargetColor(130,190,230);
namedWindow("result");
//处理并显示结果
imshow("result",cdetector.process(image));
waitKey();
return 0;
}
Shadow build是否勾选,构建目录是不一样的,将resource文件夹复制到构建目录下面。OK 运行成功!