opencv颜色识别python_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]

20200329192328555.jpeg

四、下面先来说一下指定颜色的识别,这里我们利用摄像头来识别黄色,然后把黄色区域用一个圆给框起来。例如,我们可以使用黄色的乒乓球来做实验。

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)

20200329200537683.png

以上只是提供了颜色识别的简单思路,主要是熟悉如何在HSV颜色空间进行颜色识别。不同的场景还需要根据实际情况进行修改。

原文链接:https://blog.csdn.net/qq_39507748/article/details/105184428

你可能感兴趣的:(opencv颜色识别python_opencv使用HSV颜色空间实现颜色识别)