第3章 处理图像的颜色
3.2 用策略设计模式比较颜色
1、基本原理
假设我们要构建一个简单的算法,用来识别图像中具有某种颜色的所有像素。这个算法必须输入一幅图像和一个颜色,并且返回一个二值图像,显示具有指定颜色的像素。在运行算法前,还需要指定一个参数,即能够接受的颜色公差。
2、代码实现
/**
* 文件名:example_colorDetector.cpp
* 日期:2021/03/28
* 作者:南风无良
*/
#include <iostream>
#include <opencv2/opencv.hpp>
class ColorDetector {
private:
int maxDist; // 允许的最小差距
cv::Vec3b target; // 目标颜色
cv::Mat result; // 存储二值映射结果的图像
public:
ColorDetector() : maxDist(0.0), target(0, 0, 0) {
}
ColorDetector(uchar blue, uchar green, uchar red, int mxDist);
void setColorDistanceThreshold(int distance);
int getColorDistanceThreshold() const;
void setTargetColor(uchar blue, uchar green, uchar red);
void setTargetColor(cv::Vec3b color);
cv::Vec3b getTargetColor() const;
int getDistance2TargetColor(const cv::Vec3b& color) const;
int getColorDistance(const cv::Vec3b& color, const cv::Vec3b& target) const;
cv::Mat process(const cv::Mat& image);
cv::Mat process(const std::string imageFile);
};
ColorDetector::ColorDetector(uchar blue, uchar green, uchar red, int mxDist)
{
this->target = cv::Vec3b(blue, green, red);
this->maxDist = mxDist;
}
// 设置颜色差距的阈值,阈值必须是正数,否则就设定为0
void ColorDetector::setColorDistanceThreshold(int distance)
{
if (distance < 0)
{
distance = 0;
}
this->maxDist = distance;
}
// 获取颜色差距的阈值
int ColorDetector::getColorDistanceThreshold() const
{
return this->maxDist;
}
// 设置需要检测的颜色 - 重载
void ColorDetector::setTargetColor(uchar blue, uchar green, uchar red)
{
this->target = cv::Vec3b(blue, green, red); // OpenCV颜色序列是BGR
}
void ColorDetector::setTargetColor(cv::Vec3b color)
{
this->target = color;
}
// 获取需要检测的颜色
cv::Vec3b ColorDetector::getTargetColor() const
{
return this->target;
}
// 计算与目标颜色之间的距离
int ColorDetector::getDistance2TargetColor(const cv::Vec3b& color) const
{
return getColorDistance(color, this->target);
}
// 计算两个颜色之间的城市距离
int ColorDetector::getColorDistance(const cv::Vec3b& color1, const cv::Vec3b& color2) const
{
return abs(color1[0] - color2[0]) + abs(color1[1] - color2[1]) + abs(color1[2] - color2[2]);
}
cv::Mat ColorDetector::process(const cv::Mat& image)
{
cv::Mat result;
result.create(image.size(), CV_8U);
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 (this->getDistance2TargetColor(*it) <= this->maxDist)
{
*itout = 255;
}
else
{
*itout = 0;
}
}
return result;
}
cv::Mat ColorDetector::process(const std::string imageFile)
{
cv::Mat image = cv::imread(imageFile);
cv::floodFill(image, cv::Point(100, 50), cv::Scalar(255, 255, 255), (cv: