4.3 颜色分离模块
4.3.1颜色空间
颜色空间又名彩色空间,在对物体进行颜色识别时,选择合适的颜色空间很重要。常用的颜色空间模型有RGB、YUV、HSV、CMY和HSI等,其中最基本而且最常见的颜色空间为RGB颜色空间。该文主要使用RGB和HSV2个颜色空间模型来研究电线的颜色识别。
RGB分别代表光谱的三原色,即红、绿、蓝,RGB颜色空间不仅易于映入其他颜色空间中,而且可以与它们相互转换,易受光线影响、不直观性、且3个颜色分量相互关联是RGB颜色空间的缺点所在。RGB颜色空间的三维模型如下图
HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。
这个模型中颜色的参数分别是:色调(H),饱和度(S),明度(V)。
色调H:用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;
饱和度S:表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
明度V:明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
RGB和CMY颜色模型都是面向硬件的,而HSV(Hue Saturation Value)颜色模型是面向用户的。
HSV模型的三维表示从RGB立方体演化而来。设想从RGB沿立方体对角线的白色顶点向黑色顶点观察,就可以看到立方体的六边形外形。六边形边界表示色彩,水平轴表示纯度,明度沿垂直轴测量。
且已有前人通过实验计算出大致颜色的各分量范围,便在此基础上调试
4.3.2 RGB色彩空间转HSV色彩空间
原理:
通过调用cv2库中的cvtColor方法将RGB的原图转化成HSV图
代码段:
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
处理结果:
4.3.3 颜色分离
原理:
通过对HSV色彩空间的理解和HSV色彩表下,调试出四个颜色区间用于分离绿色、蓝色、橙色、褐色
绿色:H分量:35-77 S分量:43-255 V分量:46-255
蓝色:H分量:100-124 S分量:43-255 V分量:46-255
橙色:H分量:11-25 S分量:100-255 V分量:150-255
褐色:H分量:0-10 S分量:43-255 V分量:46-255
处理结果:
4.3.4 颜色点统计
原理:
由于橙色和褐色在HSV色域中不能完全分离,且四条白线掺杂着其他四种颜色,不能完全分离出八条颜色,固采用对线条轮廓内的像素点符合相应颜色区间内像素点的个数,个数多的线的轮廓为纯色,否则为相应的白线,并且先识别出橙色的两条线之后,再识别褐色的两条线,从而实现橙色和褐色的分离。最后将八条线的顺序:白橙、橙、白绿、蓝、白蓝、绿、白褐、褐的结果显示在原图上如下图所示
首先识别绿色,得出两个最大值的线的轮廓之后,数值最大的轮廓为纯色,否则为相应的白色,如green列表中,最大值为148,此线条轮廓为绿色,次大值为71,此线条轮廓为白绿色,下次遍历时便剔除这两条线的轮廓,以此循环直至识别完八条线。
def calColPbl(self, roi, box, color):
x,y,w,h = box
count = 0
if color == 'green':
for i in range(w):
for j in range(h):
if (self.low_green[0] < roi[y+j,x+i,0] < self.high_green[0]) and \
(self.low_green[1] < roi[y+j,x+i,1] < self.high_green[1]) and \
(self.low_green[2] < roi[y+j,x+i,2] < self.high_green[2]):
count = count + 1
if color == 'blue':
for i in range(w):
for j in range(h):
if (self.low_blue[0] < roi[y+j,x+i,0] < self.high_blue[0]) and \
(self.low_blue[1] < roi[y+j,x+i,1] < self.high_blue[1]) and \
(self.low_blue[2] < roi[y+j,x+i,2] < self.high_blue[2]):
count = count + 1
if color == 'orange':
for i in range(w):
for j in range(h):
if (self.low_orange[0] < roi[y+j,x+i,0] < self.high_orange[0]) and \
(self.low_orange[1] < roi[y+j,x+i,1] < self.high_orange[1]) and \
(self.low_orange[2] < roi[y+j,x+i,2] < self.high_orange[2]):
count = count + 1
if color == 'brown':
for i in range(w):
for j in range(h):
if (self.low_brown[0] < roi[y+j,x+i,0] < self.high_brown[0]) and \
(self.low_brown[1] < roi[y+j,x+i,1] < self.high_brown[1]) and \
(self.low_brown[2] < roi[y+j,x+i,2] < self.high_brown[2]):
count = count + 1
return count
def colorDetection(self, raw_img, roi, boxes):
if len(boxes) != 8:
return False
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
# # hsv_roi = cv.GaussianBlur(hsv_roi, (5,5), 0)
cv.imshow('hsv',hsv_roi)
for color in self.color_detect:
cal_result = []
cal_result = [self.calColPbl(hsv_roi, box, color) for box in boxes]
max_index = cal_result.index(max(cal_result))
cal_result[max_index] = 0
smax_index = cal_result.index(max(cal_result))
if max_index == smax_index:
return False
max_box = boxes[max_index]
smax_box = boxes[smax_index]
boxes.remove(max_box)
boxes.remove(smax_box)
max_str = eval('self.'+str(color))
smax_str = eval('self.'+str(color)+'_w')
image = cv.putText(raw_img, max_str, (182+max_box[0],155+max_box[1]), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1)
image = cv.putText(raw_img, smax_str, (182+smax_box[0],155+smax_box[1]), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1)
return True
处理结果: