目录

第5章  颜色检测

5.1 实现原理

5.2 Lab颜色模型

5.3 cv :: threshold() 阈值函数

5.4 计算图像之间的距离

5.4.1 公式计算

5.4.2 cv::absdiff()

5.4.3 cv::floodFill()

5.5 完整代码


Github代码地址:GitHub - Qinong/OpenCV

第5章  颜色检测

颜色检测用来识别图像中所有像素的某种颜色。这个算法必领输人一幅图像和一个颜色,并且返回一个二值图像,显示具有指定颜色的像素。在运行算法前,还要指定一个阈值,即能接受的颜色的公差。

5.1 实现原理

算法的核心对每个像素进行循环扫描,把像素颜色和目标颜色做比较。可以这样写这个循环:

cv::Mat ColorDetector::process(const cv::Mat &image) {result.create(image.size(),CV_8U);// 转换成Lab色彩空间if (useLab)cv::cvtColor(image, converted, CV_BGR2Lab);// 获取迭代器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>();// 获取转换图像的迭代器if (useLab) {it = converted.begin<cv::Vec3b>();itend = converted.end<cv::Vec3b>();}// 遍历每个像素for ( ; it!= itend; ++it, ++itout) {// 通过像素与阈值比较 // getDistanceToTargetColor()见完整代码if (getDistanceToTargetColor(*it)<maxDist) {*itout= 255;} else {*itout= 0;}}return result;
}

要先创建迭代器实现扫描循环,在每个迭代步骤中计算当前像素的颜色与目标颜色的距离,检查它是否在公差(maxDist )范围之内。如果是,就在输出图像中赋值 255( 白色),否则就赋值 0( 黑色)。

5.2 Lab颜色模型

Lab颜色模型弥补了RGB和CMYK两种色彩模式的不足。它是一种设备无关的颜色模型,也是一种基于生理特征的颜色模型。 Lab颜色模型由三个要素组成,一个要素是亮度(L),a 和b是两个颜色通道。a包括的颜色是从深绿色(低亮度值)到灰色(中亮度值)再到亮粉红色(高亮度值);b是从亮蓝色(低亮度值)到灰色(中亮度值)再到黄色(高亮度值)。因此,这种颜色混合后将产生具有明亮效果的色彩。

Lab模式既不依赖光线,也不依赖于颜料,它是CIE组织确定的一个理论上包括了人眼可以看见的所有色彩的色彩模式。Lab模式弥补了RGB和CMYK两种色彩模式的不足。同RGB颜色空间相比,Lab是一种不常用的色彩空间。它是在1931年国际照明委员会(CIE)制定的颜色度量国际标准的基础上建立起来的。

Lab颜色空间中的取值范围:

  • L分量用于表示像素的亮度,取值范围是[0,100],表示从纯黑到纯白;
  • a表示从红色到绿色的范围,取值范围是[127,-128];
  • b表示从黄色到蓝色的范围,取值范围是[127,-128]。

下图所示为Lab颜色空间的图示:

5.3 cv :: threshold() 阈值函数 

cv::threshold()函数创建一个二值图像。这个函数通常用于将所有像素与某个阈值(第三个参数)进行比较,在常规阈值化模式 (CV::THRESH_BINARY)下,将所有大于指定阈值的像素赋值为预定的最大值(第四个参数),将其他像素赋值为 0。

double cv::threshold(  cv::InputArray src, cv::OutputArray dst, double thresh,  double maxValue,  int thresholdType
);  
  • src: 多通道的输入图像,8bits或者32bits float
  • dst: 与src的同尺寸、类型、通道数的输出图像
  • thresh: 阈值(介于最大值和最小值之间的一个值)
  • maxval: 与两种阈值类型(THRESH_BINARY & THRESH_BINARY_INV)结合使用,用于指定最大的值
  • type: 阈值的类型

阈值的类型

作用
THRESH_BINARY  最常见的作法,设置一个阈值,大于的时候取最大值(maxval是threshold的参数),否则取0。
 THRESH_BINARY_INV 
 
与THRESH_BINARY相反,大于阈值取0,否则取最大值,maxval对于THRESH_BINARY和THRESH_BINARY_INV有意义。
THRESH_TRUNC 
 
截断型,大于阈值的统一将为阈值,其余不变。
THRESH_TOZERO 
 
过滤型,大于阈值的保持不变,其余设置为0。
THRESH_TOZERO_INV 
 
大于阈值0,其他不变。
THRESH_MASK 
 
THRESH_OTSU 
 
大津阈值
 THRESH_TRIANGLE  矩形阈值

5.4 计算图像之间的距离

5.4.1 公式计算

要计算两个颜色向量间的距离,可使用这个简单的公式:

return abs (color [0]-target [0])+abs (color [1]-target [1])+abs (color [2]-target [2]);

(1)公式计算颜色检测

// 计算两个颜色之间的城区距离
int 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]);}

5.4.2 cv::absdiff()

计算两个数组(图像)差的绝对值: dst(I)c = abs(src1(I) - src2(I)c),所有数组(图像)必须有相同的数据类型、相同的大小(或ROI大小)。

void cv::absdiff( const CvArr* src1, const CvArr* src2, CvArr* dst );  
  • src1:第一个原数组  
  • src2:第二个原数组  
  • dst:输出数组 

5.4.3 cv::floodFill() 

cv::floodFill()在判断一个像素时,要检查附近像素的状态,这是为了识别某种颜色的相关区域。用户只需指定一起始位置和允许的误差,就可以找出颜色接近的连续区域。

// 构造函数1
int floodFill(InputArray image, Point seedPoint, Scalar newVal, Rect* rect=0,Scalar ioDiff=Scalar(), Scalar upDiff=Scalar(), int flags=4)
// 构造函数2
int floodFill(InputArray image, InputArray mask, Point seedPoint, Scalar newVal, Rect* rect=0,Scalar ioDiff=Scalar(), Scalar upDiff=Scalar(), int flags=4)

(1) cv::absdiff()检测颜色

 // 使用cv::floodFill函数ColorDetector colordetector(230, 190, 130, 45, true);  // 第3个构造函数cv::floodFill(image,            // 输入/输出图像cv::Point(100, 50),         // 起始点cv::Scalar(255, 255, 255),  // 填充颜色(cv::Rect*)0,               // 填充颜色的边界距离cv::Scalar(35, 35, 35),     // 偏差的最小/最大阈值cv::Scalar(35, 35, 35),     // 正差阈值,两个阈值通常相等cv::FLOODFILL_FIXED_RANGE); // 与起始点像素比较cv::namedWindow("Image2");cv::Mat image2 = colordetector(image);cv::imshow("Image2", image2);cv::waitKey();

5.5 完整代码

/*colordetector.h头文件
*/
#if !defined COLORDETECT
#define COLORDETECT#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>class ColorDetector {private:int maxDist;     // 允许的最小差距cv::Vec3b target;    // 目标颜色cv::Mat converted;   // 转换的图像bool useLab;         // 是否使用Lab色彩空间cv::Mat result;  // 存储二值映射结果的图像public:// 不同的构造函数// 在此初始化默认参数ColorDetector() : maxDist(100), target(0,0,0), useLab(false) {}ColorDetector(bool useLab) : maxDist(100), target(0,0,0), useLab(useLab) {}ColorDetector(uchar blue, uchar green, uchar red, int mxDist=100, bool useLab=false): maxDist(mxDist), useLab(useLab) { // 设置需要检测的颜色setTargetColor(blue, green, red);}// 计算与目标颜色的距离int getDistanceToTargetColor(const cv::Vec3b& color) const {return getColorDistance(color, target);}// 计算两个颜色之间的城区距离int 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 process(const cv::Mat &image);cv::Mat operator()(const cv::Mat &image) {cv::Mat input;if (useLab) { cv::cvtColor(image, input, CV_BGR2Lab);    // 转换成Lab色彩空间}else {input = image;}cv::Mat output;cv::absdiff(input,cv::Scalar(target),output);   // 计算目标图像的绝对距离std::vector<cv::Mat> images;cv::split(output,images);    // 分割图像的通道output= images[0]+images[1]+images[2];   // 合并3个通道// 设定阈值cv::threshold(output,  // 输入图像output,  // 输出图像maxDist, // 阈值255,     // 最大值cv::THRESH_BINARY_INV); // 阈值类型return output;}//设置颜色距离的阈值void setColorDistanceThreshold(int distance) {if (distance<0)distance=0;maxDist= distance;}// 获取颜色距离的阈值int getColorDistanceThreshold() const {return maxDist;}// 设置需要检测的颜色void setTargetColor(uchar blue, uchar green, uchar red) {// BGR的次序target = cv::Vec3b(blue, green, red);if (useLab) {// 创建临时的单像素图像cv::Mat tmp(1, 1, CV_8UC3);tmp.at<cv::Vec3b>(0, 0) = cv::Vec3b(blue, green, red);// 转换成Lab色彩空间cv::cvtColor(tmp, tmp, CV_BGR2Lab);target = tmp.at<cv::Vec3b>(0, 0);}}// 设置需要检测的颜色void setTargetColor(cv::Vec3b color) {target= color;}// 获取需要检测的颜色cv::Vec3b getTargetColor() const {return target;}
};#endif
/*颜色检测处理函数
*/
#include "colordetector.h"
#include <vector>cv::Mat ColorDetector::process(const cv::Mat &image) {result.create(image.size(),CV_8U);// 转换成Lab色彩空间if (useLab)cv::cvtColor(image, converted, CV_BGR2Lab);// 获取迭代器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>();// 获取转换图像的迭代器if (useLab) {it = converted.begin<cv::Vec3b>();itend = converted.end<cv::Vec3b>();}// 遍历每个像素for ( ; it!= itend; ++it, ++itout) {// 通过像素与阈值比较 if (getDistanceToTargetColor(*it)<maxDist) {*itout= 255;} else {*itout= 0;}}return result;
}
/*主函数
*/
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "colordetector.h"int main()
{// step1// 创建检测图像的对象ColorDetector cdetect;// step2// 读取原图像cv::Mat image= cv::imread("Ferrar_F8.png");if (image.empty())return 0; cv::namedWindow("Image");cv::imshow("Image", image);// step3// 设置输入参数与输出图像处理效果cdetect.setTargetColor(230,190,130);cv::namedWindow("Image1");cv::Mat image1 = cdetect.process(image);cv::imshow("Image1",image1);// 使用cv::floodFill函数ColorDetector colordetector(230, 190, 130, 45, true);  // 第3个构造函数cv::floodFill(image,            // 输入/输出图像cv::Point(100, 50),         // 起始点cv::Scalar(255, 255, 255),  // 填充颜色(cv::Rect*)0,               // 填充颜色的边界距离cv::Scalar(35, 35, 35),     // 偏差的最小/最大阈值cv::Scalar(35, 35, 35),     // 正差阈值,两个阈值通常相等cv::FLOODFILL_FIXED_RANGE); // 与起始点像素比较cv::namedWindow("Image2");cv::Mat image2 = colordetector(image);cv::imshow("Image2", image2);cv::waitKey();return 0;
}

OpenCV - C++实战(05) — 颜色检测相关推荐

  1. 基于OpenCV的实战:轮廓检测(附代码解析)

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 利用轮廓检测物体可以看到物体的各种颜色,在这种情况下放置在静态和动 ...

  2. 使用 OpenCV 进行实时对象颜色检测

    在本文中,我们将讨论如何使用 python 和 OpenCV 检测单色对象.单色是指单一波长的光.我们将使用使用网络摄像头捕获的视频作为输入,并尝试检测单一颜色的对象,尤其是蓝色.但是,如果您正确设置 ...

  3. 3h精通OpenCV(七)-颜色检测

    0.准备工作 右击新建的项目,选择Python File,新建一个Python文件,然后在开头import cv2导入cv2库,import numpy并且重命名为np. import cv2 imp ...

  4. opencv项目实战信用卡的检测

    第一步先梳理一下我们的项目逻辑: 一. 找素材 (数字模板,银行卡照片等) 二. 识别数字则需要我们对数字模板进行处理.因此下面我们开始处理数字模板. 1.将数字模板处理成灰度图,再进行二值处理.这样 ...

  5. 【Opencv图像处理】BGB转HSV与颜色检测

    BGB转HSV与颜色检测 什么是HSV色彩空间? Opencv代码 静态图片颜色检测 结果展示 视频颜色检测 结果展示 什么是HSV色彩空间? HSV(色相.饱和度.值,也称为 HSB [色相.饱和度 ...

  6. python颜色识别原理_python+opencv实现颜色检测、轮廓检测、颜色追踪

    准备工作 python配置numpy和openCv库 读取图像和视频图像cv2.imread(路径) cv2.imshow(窗口名称,输出对象) cv2.waitkey(等待时间)import cv2 ...

  7. 《OpenCv视觉之眼》Python图像处理十六:Opencv图像处理实战一之图像中的硬币检测

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  8. 《OpenCv视觉之眼》Python图像处理十九:Opencv图像处理实战四之通过OpenCV进行人脸口罩模型训练并进行口罩检测

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  9. OpenCV 颜色检测| color detection

    OpenCV 颜色检测 1.导入必要的包并初始化相机 import cv2 import numpy as np# Reading the image img = cv2.imread('test.j ...

最新文章

  1. C++的集成开发环境(IDE)
  2. Spring注解方式实现定时器
  3. 233 Matrix HDU - 5015
  4. Elasticsearch 5.2.x 使用 Head 插件连接不上集群
  5. python flv转mp4_ffmpeg将多个flv文件合成为mp4(python版)
  6. 进程通信方法的特点以及使用场景
  7. python格式化输出作业_Python格式化输出
  8. Android 跳转权限设置界面的终极方案
  9. 【数学建模】基于matlab模糊二元决策树【含Matlab源码 038期】
  10. Nodejs的各种数据库驱动地址汇总
  11. DoDAF示例图绘制
  12. 【资讯】时间的朋友2017跨年演讲全回顾
  13. 深入了解Spark SQL的Catalyst Optimizer
  14. jbpm支持xpdl的标准了吗?
  15. python 根据word生成ppt_python操作word、ppt的详解
  16. Linux驱动学习笔记之触摸屏驱动
  17. 在带头结点单链表中查找最大值,将其与最后一个元素交换(交换值)
  18. 【实验】实验课总结3 实验二
  19. 大疆精灵4与双目视觉智能导航系统
  20. 光纤收发器的选择与维护!

热门文章

  1. 不经一番寒彻骨,怎得梅花扑鼻香,android开发艺术探索电子
  2. caffe-ristretto:定点方案
  3. 解析Activity中的onCreate方法
  4. snat与dnat的区别
  5. 控制BLDC资料汇总
  6. Java 11已经不再完全免费,不要陷入Oracle的Java 11陷阱
  7. MFC 加载gif动态图片的方法
  8. 电脑蓝牙耳机连接不稳定_一个困扰我半年的 macOS 蓝牙有时断连的问题终于解决了!...
  9. python list[list] or list[list, list, list]
  10. MySQL简介,什么是数据库?