opencv学习(3):在算法设计中使用策略模式
一个设计模式是一个可靠的、可重用的方案,用于解决软件设计中频繁出现的问题。策略设计模式的目标是将算法封装在类中。因此可以很容易的替换一个现有的算法,或者把几个算法组合起来进行更复杂的处理,都会更加容易。而且这种模式能够尽可能地将算法的复杂性隐藏在一个直观的编程接口之后,因而有利于算法的部署。
比方说,我们需要构建一个简单的算法,它可以鉴别图像中含有给定颜色的所有像素。该算法输入的是图像以及颜色,并返回表示含有指定颜色的像素的二值图像。该算法还要指定另外一个参数,用来表示对颜色偏差的容忍度。算法的核心部分实现方法如下:
————————————————
/*
鉴别图像中含有给定颜色的所有像素,并返回表示含有指定颜色的像素的二值图像
*/
#include "pch.h"
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
class ColorDetector
{
public:
//构造函数初始化
ColorDetector() :minDist(100) //是指一个默认值,通常会设置为空,这里使用100作为距离通常是一个可接受的值
{
target[0] = target[1] = target[2] = 0;
}
//设置容忍阈值,并保证值大于0
void setColorDistanceThreshold(int distance)
{
if (distance < 0)
distance = 0;
minDist = distance;
}
//获取容忍阈值
int getColorDistanceThreshold() const
{
return minDist;
}
//下面方法一样,也可作为上面两个函数的重载
int getColorDistanceThreshold(int distance)
{
if (distance < 0)
distance = 0;
minDist = distance;
return minDist;
}
//设置目标颜色
void setTargetColor(unsigned char red,
unsigned char green,
unsigned char blue)
{
target[2] = red;
target[1] = green; //
target[0] = blue;
}
//设置目标颜色,函数重载,降低算法使用难度
void setTargetColor(Vec3b color)
{
target = color;
}
//获取目标颜色
Vec3b getTargetColor() const
{ //必须是类的成员函数才能const 标记说明
return target;
}
//计算当前像素和目标颜色距离
int getDistance(const Vec3b& color)
{
return abs(color[0] - target[0]) +
abs(color[1] - target[1]) +
abs(color[2] - target[2]);
}
//
Mat process(const Mat &image);
private:
int minDist;
Vec3b target;
Mat result;
};
//按需重新分配二值图像(只有两种灰度/非黑即白)
Mat ColorDetector::process(const Mat &image)
{
result.create(image.rows, image.cols, CV_8U);
Mat_<Vec3b>::const_iterator it = image.begin<Vec3b>();
Mat_<Vec3b>::const_iterator itend = image.end<Vec3b>();
Mat_<uchar>::iterator itout = result.begin<uchar>();
for (; it != itend; ++it,++itout)
{
if (getDistance(*it) < minDist)
{
*itout = 255;
}
else
{
*itout = 0;
}
}
return result;
}
int main()
{
//创建图像处理的对象
ColorDetector cdetect;
//读取输入图像
Mat image = imread("C:/Users/mk12306/Pictures/Saved Pictures/Tony.jpg");
if (!image.data)
{
cout << "picture read failure" << endl;
return -1;
}
cdetect.setTargetColor(81, 24, 31); //图片的颜色
namedWindow("result"); //显示结果
imshow("result", cdetect.process(image));
waitKey();
return -1;
}
原图:
效果图:
这里还介绍一个获取颜色RGB值的方法:
如果你想知道某个背景色的rbg值是多少,可以用画图工具打开,用工具里面的颜色吸取器,然后取你想要的颜色,最后3的位置会变成你选取的颜色。
接下来点击编辑颜色,方框就出现你选取颜色的RGB值。