opencv学习笔记二十一:使用HSV颜色空间实现颜色识别

一、颜色空间介绍
       RGB 颜色空间是大家最熟悉的颜色空间,即三基色空间,任何一种颜色都可以由该三种 颜色混合而成。然而一般对颜色空间的图像进行有效处理都是在 HSV 空间进行的,HSV(色调 Hue,饱和度 Saturation,亮度 Value)是根据颜色的直观特性创建的一种颜色空间, 也称六角锥体模型。

       为什么会选择 HSV 空间而不是 RGB 空间? 对于图像而言,识别相应的颜色在 RGB 空间、 HSV 空间或者其它颜色空间都是可行的。之所以选择 HSV,是因为 H 代表的色调基本上可以 确定某种颜色,再结合饱和度和亮度信息判断大于某一个阈值。而 RGB 由三个分量构成, 需要判断每种分量的贡献比例。即 HSV 空间的识别的范围更广,更方便。

二、三种颜色空间转换(Gray,RGB,HSV)
       在OpenCV中有超过150种的颜色空间转换的方法,但是我们经常会用到的也就只有两种,即 BGR->Gray 和 BGR->HSV。注意 Gray 和 HSV 不可以互相转换。 颜色空间转换函数是:cv2.cvtColor(input_image, flag)

  • BGR->Gray: flag 就是 cv2.COLOR_BGR2GRAY

  • BGR->HSV: flag 就是 cv2.COLOR_BGR2HSV

三、OpenCV 中 HSV 颜色空间的取值范围:H [0, 179] S [0, 255] V [0, 255]opencv学习笔记二十一:使用HSV颜色空间实现颜色识别_第1张图片
四、下面先来说一下指定颜色的识别,这里我们利用摄像头来识别黄色,然后把黄色区域用一个圆给框起来。例如,我们可以使用黄色的乒乓球来做实验。

import cv2
import time
import numpy as np

cap=cv2.VideoCapture(0)

#设置摄像头分辨率为(640,480)
#如果感觉图像卡顿严重,可以降低为(320,240)
cap.set(3,480)
cap.set(4,320)

#设置黄色的阙值
yellow_lower=np.array([156,43,46])
yellow_upper=np.array([180,255,255])

time.sleep(1)

while 1:
    #ret为是否找到图像,frame是帧本身
    ret,frame=cap.read()

    frame=cv2.GaussianBlur(frame,(5,5),0)#高斯滤波                    
    hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV) #转hsv               
    '''
    这一句代码是关键,它是根据你设置的阈值,比如上面的黄色的阈值,
    在这个掩膜中,原图像素值在阈值之间的像素点会被设置为255,否则
    就设置为0
    '''
    mask=cv2.inRange(hsv,yellow_lower,yellow_upper)          #生成掩膜
    
    #形态学操作,对掩膜进行一系列形态学操作,使后面的与运算效果更好
    mask=cv2.erode(mask,None,iterations=2)#腐蚀操作                   
    mask=cv2.dilate(mask,None,iterations=2)#膨胀操作                  
    mask=cv2.GaussianBlur(mask,(3,3),0)#高斯滤波                      
    
    #这个是进行与运算之后的结果,只有黄色部分被保留
    #其实在这个例子中的res和mask是一样的,都是黄色部分被保留了下来
    res=cv2.bitwise_and(frame,frame,mask=mask)#与运算               
    #检测颜色的轮廓
    cnts=cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,
                          cv2.CHAIN_APPROX_SIMPLE)[-2]       
    if len(cnts)>0:
        cnt = max (cnts,key=cv2.contourArea)
        (x,y),radius=cv2.minEnclosingCircle(cnt)
        #找到后在每个轮廓上画圆
        cv2.circle(frame,(int(x),int(y)),int(radius)*2,
                   (255,0,255),2)                            
        print('x:',x,'y:',y)
    cv2.imshow('capture',frame)
    if cv2.waitKey(1)==29:
        break
cap.release()
cv2.destroyAllWindows()

每一句代码的解释已经在上面了,整体的思路就是先根据颜色阈值设置掩膜,有了掩膜我们就可以得到想要识别的颜色所在的区域。紧接着我们对其进行轮廓检测,找到最大的那个轮廓以排除一些干扰,最后根据轮廓信息画出其外接圆即可。

五、下面来说一下如果进行不指定颜色的颜色识别,这里我们使用的是静态图片,提供一张颜色分明的图片,我们识别出它是什么颜色。

import cv2
import numpy as np

def color_hist(img):
    mask=np.zeros(img.shape[:2],dtype=np.uint8)
    '''
    设置掩膜,目的是只对中间这部分进行H分量的直方图统计,
    不对整张图进行统计,是因为图的关键内容一般都是在中间
    '''
    mask[70:170,100:220]=255
    '''
    这里选择[0,180]是因为在HSV中H的范围是[0,179];
    也即横坐标表示的是H的值,和你的尺寸,比如上面的
    70.170.100.220这几个数没关系
    '''
    hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
    '''
    计算该图像的直方图,得到的hist_mask是一维数组,长度就是180,
    所以这里的object_H表示数组的某个位置
    就可以理解为它就是表示0-179里的某个数,代表像素值=object_H的
    像素点最多,因此就可以辨别颜色
    '''
    hist_mask=cv2.calcHist([hsv],[0],mask,[180],[0,180])
    object_H=np.where(hist_mask==np.max(hist_mask))
    print(object_H[0])
    return object_H[0]
'''
根据上述计算出的像素点最多的一个H的值,也即object_H,就可以根据其范围大致估计图片的颜色
'''
def color_distinguish(object_H):
    try:
       if object_H>26 and object_H<34: color='yellow'
       elif object_H>156 and object_H<180 : color='red'
       elif object_H>100 and object_H<124: color='blue'
       elif object_H>35 and object_H<77 : color='green'
       elif object_H>78 and object_H<99:color=='cyan-blue' 
                                            
       elif object_H>6 and object_H<15: color ='orange'
       else: color='None'
       print(color)
       return color
   except:pass

if __name__=='__main__':
    img=np.ones((240,320,3),dtype=np.uint8)*128
    img[60:180,80:240]=[0,255,255]
    object_H=color_hist(img)
    color_distinguish(object_H)
    cv2.imshow('image',img)
    cv2.waitKey(0)
    

opencv学习笔记二十一:使用HSV颜色空间实现颜色识别_第2张图片
       以上只是提供了颜色识别的简单思路,主要是熟悉如何在HSV颜色空间进行颜色识别。不同的场景还需要根据实际情况进行修改。

参考链接:https://www.yahboom.com/study/Pi_motion

你可能感兴趣的:(opencv学习笔记二十一:使用HSV颜色空间实现颜色识别)