OpenCV3 3.2 用策略设计模式(封装类)比较颜色

头文件ColorDetector.h

#pragma once
#include<iostream>
#include<opencv2/opencv.hpp>
#include<vector>
class ColorDetector
{
private:
    //颜色公差
    int maxDist;
    //目标颜色
    cv::Vec3b target;
public:
    //默认构造
    ColorDetector();

    //有参构造1
    ColorDetector(uchar blue, uchar green, uchar red, int distance);

    //有参构造2
    ColorDetector(cv::Vec3b color, int distance);

    //设置目标颜色函数1
    void setTargetColor(uchar blue, uchar green, uchar red);

    //设置目标颜色函数2
    void setTargetColor(cv::Vec3b color);

    //设置颜色公差
    void setColorDistance(int distance);

    //取颜色公差
    int getMaxDist() const;
    
    //取目标颜色
    cv::Vec3b getTargetColor() const;

    //用城区距离计算颜色差距以供类内调用
    int getColorDistance(const cv::Vec3b& color1, const cv::Vec3b& color2) const;

    //计算与目标颜色差距
    int getColorDistanceToTargetColor(const cv::Vec3b& color) const;

    //用迭代器遍历并返回二值图像
    cv::Mat process(const cv::Mat& image);

    //用自带的函数生成二值图像
    cv::Mat processThreshold(const cv::Mat& image);
};

源文件ColorDetector.cpp

#include"ColorDetector.h"
ColorDetector::ColorDetector()
{
    this->maxDist = 100;
    this->target = cv::Vec3b(0, 0, 0);
}

ColorDetector::ColorDetector(uchar blue, uchar green, uchar red, int distance)
{
    this->maxDist = distance;
    this->target = cv::Vec3b(blue, green, red);
}

ColorDetector::ColorDetector(cv::Vec3b color, int distance)
{
    this->maxDist = distance;
    this->target = color;
}

void ColorDetector::setTargetColor(uchar blue, uchar green, uchar red)
{
    this->target = cv::Vec3b(blue, green, red);
}

void ColorDetector::setTargetColor(cv::Vec3b color)
{
    this->target = color;
}

void ColorDetector::setColorDistance(int distance)
{
    this->maxDist = distance;
}

int ColorDetector::getMaxDist() const
{
    return this->maxDist;
}

cv::Vec3b ColorDetector::getTargetColor() const
{
    return 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]);
}

int ColorDetector::getColorDistanceToTargetColor(const cv::Vec3b& color) const
{
    return ColorDetector::getColorDistance(this->target, color);
}

实现1:使用迭代器逐个比较像素

cv::Mat ColorDetector::process(const cv::Mat& image)
{
    cv::Mat result;
    result.create(image.size(), CV_8UC1);
    cv::Mat_<cv::Vec3b>::const_iterator it1 = image.begin<cv::Vec3b>();
    cv::Mat_<cv::Vec3b>::const_iterator itend = image.end<cv::Vec3b>();
    cv::Mat_<uchar>::iterator it2 = result.begin<uchar>();

    for (; it1 != itend; it1++, it2++)
    {
        //如果颜色差距大于公差,则设为黑色
        if (ColorDetector::getColorDistanceToTargetColor(*it1) > (this->maxDist))
        {
            (*it2) = 0;
        }
        //否则设为白色
        else
        {
            (*it2) = 255;
        }
    }
    return result;
}

实现2:使用自带absdiffthreshold方法直接生成

该方法使用了absdiff函数计算图像像素与标量值之间差距的绝对值,再将三通道分开并相加,最后根据内置阈值函数将低于maxDist的值变为255,其余置为0。

cv::Mat ColorDetector::processThreshold(const cv::Mat& image)
{
    cv::Mat result;
    //将image与标量图像作差取绝对值并存到image中
    cv::absdiff(image, cv::Scalar(this->target), result);

    std::vector<cv::Mat> images;
    //把通道分割进三幅图像
    cv::split(result, images);
    //三个通道相加,自动转为CV_8UC1,且有saturate_cast函数自动取饱和
    result = images[0] + images[1] + images[2];

    //应用阈值函数,低于maxDist的都转为255,别的转为0
    cv::threshold(result, result, this->maxDist, 255, cv::THRESH_BINARY_INV);
    return result;
}

补充:cv::threshold函数的使用

函数签名

double threshold( InputArray src, OutputArray dst,
                               double thresh, double maxval, int type );

其中,参数分别为:
输入图像,输出图像,阈值,预定值,模式。

模式名作用
cv::THRESH_BINARY大于阈值置为预定值,其他像素置为0
cv::THRESH_BINARY_INV小于阈值置为预定值,其他像素置为0
cv::THRESH_TOZERO_TRUNC大于阈值置为阈值,其他像素不变
cv::THRESH_TOZERO_INV小于阈值不变,其他像素置为0
cv::THRESH_TOZERO大于阈值不变,其他像素置为0


其中,第一幅图为原图,后面五幅图分别为五种处理类型。

图片来源

效果(Processed1同Processed2)

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值