王全胜
摘要:颜色是物体的一种重要特征,人们可以依据颜色对物体进行分类、判断等。颜色识别很大程度上改变着人们的工作方式。使用计算机对颜色进行识别,可以极大地提高工作效率,降低工作成本。本文就opencv中使用HSV模型对红色识别过程中存在的识别不准确、不全面的情况进行了分析并提出解决方法,并在实践中加以验证。
关键词:opencv;颜色识别;红色;hsv python
中图分类号:TP18 文献标识码:A
文章编号:1009-3044(2021)25-0112-02
计算机视觉是使用计算机的摄像设备采集图像并进行识别,并从图像中获取信息的人工智能系统。简单的说,就是不但让计算机学会看,还让他知道看到了什么。以人看到的图像为例,我们可以从中辨认出形状、颜色、大小、亮度、色彩等。让计算机辨认出特定的颜色,就是颜色识别。颜色是物体的一种重要特征,人们可以依据颜色对物体进行分类、判断等。利用颜色特征,人们在很多行业的应用中获得了便利。比如,在快递行业,依据不同的颜色对流水线上的物品进行分拣;在农业,利用颜色识别判断果蔬的成熟程度、對异常作物进行定位、药物喷洒和进行田间杂草和作物的区分(智能除草);在公共安全方面,对火焰颜色的识别。大到卫星遥感监控山火,小到仓库火灾预警,颜色识别很大程度上改变着人们的工作方式。使用计算机对颜色进行识别,可以极大地提高工作效率,降低工作成本。视觉识别技术目前在工业检测、生物医学、X射线图像增强、遥感图像分析和空间技术等方面具有广泛的应用价值。
1 颜色识别的方法
颜色识别主要有两种方法,一种利用颜色模型识别,另一种采用训练分类器的方法识别,第一种方法稳定性并不高,经常调节白平衡,即Gamma值,来适应色温的变化,第二种方法也会受到未分类的特殊情况的影响,根据具体应用情况,择优选择。彩色图像的颜色模型有很多种形式,RGB、YUV、HSV、CMYK等,其中在图像处理以RGB最为直观理解且显示器系统采用就是此类模型,而HSV更符合人眼的颜色分辨,通常在HSV颜色空间下进行颜色识别。HSV分别指色相、饱和度、亮度。色相就是“是什么颜色”,饱和度就是颜色有多浓,亮度就是图像的明暗程度。
以HSV模型为例,它将颜色空间的模型对应于圆柱坐标系中的一个圆锥形子集,圆锥的顶面对应于V=1。它包含RGB模型中的R=1,G=1,B=1 三个面,所代表的颜色较亮。色彩H由绕V轴的旋转角给定。红色对应于角度0°,绿色对应于角度120°,蓝色对应于角度240°。
识别颜色的算法是读取照片像素点的颜色,转换成HSV模型中的值,看它是否在要识别的颜色区间内。把在此颜色区间内的点的集合作为掩模,与原照片按位进行与运算,就得出了要寻找的颜色区域。举个例子。我们要识别蓝色的范围,就把像素点转换成HSV模型。对照图一,看是否H(色相)在100至124之间,S(饱和度)是否在43至255之间,V(亮度)是否在46至255之间。如果同时满足这三个条件,我们就认为这个像素点是蓝色。这比较好理解。在实际的识别中,根据光线不同,这三个值会有稍许偏差。
2 识别红色的特殊之处
在使用无人机机载摄像头对色块进行识别、判断形状的过程中我们发现红色的识别成功率明显小于其他颜色。通过抓取掩模我们看到,本应是红色的区域掩模没有完全覆盖。通过图一的表我们可以看到红色的范围并不是连续的范围。它的H分布在0至10以及156至180。这两个范围的颜色都是红色,因为其分布在HSV模型中不连续,所以我们在给定颜色区间时只能给定其中一个。
3 掩模的抓取
我们使用python的opencv来做了实验。首先,我们选择了一张有色彩渐变的图片作为实验素材。
如图2,我们选择了一张联想的彩色羽毛壁纸作为素材。将0至10范围内的红色掩模(图3)和156至180范围内的红色掩模(图4)进行了对比。
如图4所示,两组掩码并不重合,但对应在图2上的区域都是红色。只要将两块区域合并再与图二做按位与操作,就能得到图二中的红色区域。
4 算法
有了想法,我们用python写了一段代码来实现。代码中使用了opencv和numpy。
import cv2
import numpy as np
def color_area(img, colors, thresholds):
"""
Args:
img:经过滤波的BGR图像
colors(list):需要分割的颜色
thresholds(dict):颜色的阈值
Returns:
mask(dict):{"颜色"(str):掩膜(二值图)}
"""
masks = {}
img_hsv=cv2.cvtColor(img, cv2.COLOR_BGR2HSV) #将图像转换成HSV模型
for color in colors:
low = thresholds[color][0]
high = thresholds[color][1]
mask = cv2.inRange(img_hsv,low,high)
s = np.sum(mask) # 判断掩膜是否全黑(没有对应颜色)
if s == 0 :
mask = None
masks[color] = mask