opencv2—(6)基于类的图像处理程序设计

本文介绍了一种基于C++和OpenCV的图像颜色检测方法,通过面向对象的方式实现了颜色匹配和提取的功能。文章详细展示了如何利用Lab颜色空间提高颜色相似度判断的准确性。
传统的编程思路都是面向过程的,C++则是面向对象的编程,那么我们设计程序时应该充分使用C++封装的思想,把图像处理抽象成类。这样便于代码的维护和移植。
本篇的例子是构建一个简单算法,鉴别出图像中含有给定颜色的所有像素。该算法输入的是图像及颜色,并返回表示含有指定颜色的像素的二值图像。该算法还需要指定另一个参数,即对颜色偏差的容忍度。
但由于RGB颜色空间计算颜色之间的距离并不是衡量颜色相似度最好的方法,事实上,RGB并不是一个感知上均匀分布的色彩空间。为了解决这个问题,人们提出了感知上均匀分布的色彩空间,CIEL*a*b就是这样一个颜色空间。opencv函数cv::cvtColor可以轻易的在不同颜色空间进行转换。
下面贴代码:

ColorDetector.h

#pragma once
#include<opencv2\opencv.hpp>
#include<iostream>
class ColorDetector
{
private:
       cv::Mat m_converted;//转换颜色空间的图片
       int m_threshod;//容忍度偏差
       cv::Vec3b m_model;//要查找的颜色
public:
       cv::Mat m_result;//最终得到的二值图像
       ColorDetector();
       ~ColorDetector();
       void setModel(cv::Vec3b &target);//设置要查找的颜色
       
       void setModel(uchar red, uchar green, uchar blue);//设置查找颜色的接口,这种颜色值设置在RGB通道上
       
       void setModel2(uchar red, uchar green, uchar blue);//设置查找颜色的接口,这种颜色值转换到LAB颜色空间上
       
       void setThreshold(int distance);//设置容忍度的接口
       
       int getDistance(cv::Vec3b &pixls);//解算图像像素点与要查找的颜色的距离
       
       cv::Mat process(const cv::Mat &image);
       cv::Mat process2(const cv::Mat &image);
};
ColorDetector.cpp
#include "ColorDetector.h"
//构造函数,给成员变量初始化,容忍度偏差设为100,查找的三通道颜色默认设为0
ColorDetector::ColorDetector():m_threshod(100)
{
       m_model[0] = m_model[1] = m_model[2] = 0;
}
ColorDetector::~ColorDetector()
{
}
void ColorDetector::setModel(cv::Vec3b & target)
{
       m_model = target;//cv::Vec3b类型,三通道
}
void ColorDetector::setModel(uchar red, uchar green, uchar blue)
{
       m_model[0] = blue;
       m_model[1] = green;
       m_model[2] = red;
}
void ColorDetector::setModel2(uchar red, uchar green, uchar blue)
{
       cv::Mat tmp(1, 1, CV_8UC3);//定义一个三通道的像素点
       tmp.at<cv::Vec3b>(0, 0)[0] = blue;
       tmp.at<cv::Vec3b>(0, 0)[1] = green;
       tmp.at<cv::Vec3b>(0, 0)[2] = red;
       cv::cvtColor(tmp, tmp, CV_BGR2Lab);//颜色空间转换,把RGB——>Lab
       m_model = tmp.at<cv::Vec3b>(0, 0);
}
void ColorDetector::setThreshold(int distance)
{
       m_threshod = distance;//设置容忍度
}
//这里的距离公式采用1范数
int ColorDetector::getDistance(cv::Vec3b & pixls)
{
       return abs(pixls[0] - m_model[0])
              + abs(pixls[1] - m_model[1])
              + abs(pixls[2] - m_model[2]);
}
cv::Mat ColorDetector::process(const cv::Mat & image)
{
       m_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 out = m_result.begin<uchar>();
       while (it != itend)
       {
              //循环遍历,把查找到的颜色转换为二值图像,这里按照RGB空间的颜色距离解算
              if (getDistance(*it) < m_threshod)
                     *out = 255;
              else
                     *out = 0;
              ++it;
              ++out;
       }
       return m_result;
}
cv::Mat ColorDetector::process2(const cv::Mat & image)
{
       m_result.create(image.size(), CV_8U);
       m_converted.create(image.size(), image.type());
       //把输入图像从RGB颜色空间转换到Lab颜色空间
       cv::cvtColor(image, m_converted, CV_BGR2Lab);
       cv::Mat_<cv::Vec3b>::const_iterator it = m_converted.begin<cv::Vec3b>();
       cv::Mat_<cv::Vec3b>::const_iterator itend = m_converted.end<cv::Vec3b>();
       cv::Mat_<uchar>::iterator out = m_result.begin<uchar>();
       while (it != itend)
       {
              if (getDistance(*it) < m_threshod)
                     *out = 255;
              else
                     *out = 0;
              ++it;
              ++out;
       }
       return m_result;
}

main.cpp
#include"ColorDetector.h"
int main()
{
       
       cv::Mat image = cv::imread("boldt.jpg");
       ColorDetector detector;//构造类
       
       detector.setModel(130, 190, 230);//查找蓝天的颜色
       cv::namedWindow("Process");
       cv::imshow("Process", detector.process(image));
       detector.setModel2(130, 190, 230);//查找蓝天的颜色
       cv::namedWindow("Process2");
       cv::imshow("Process2", detector.process2(image));
       
       cv::waitKey(0);
       return 0;
}
运行结果:

参考原图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值