OpenCV颜色识别一般要以下步骤:
1 颜色空间转换,将BGR转换为HSV,用色调区分颜色
2 按照阈值滤出所识别的颜色
3 消除噪点,平滑边界
3 提取连续域,提取要识别的颜色
1 HSV
H:色调,用角度度量,范围0°到360°,从红色开始逆时针方向计算。红色为0°,红绿蓝间隔120°,互补色差180°。
S:饱和度,范围0到1,代表光谱色占颜色比例。0时颜色只有灰度,1时颜色为纯光谱色
V:明度,范围0到1,代表颜色明亮程度。0为黑色,1为白色
腐蚀(erosion)和膨胀(dilation)
腐蚀和膨胀作用:
1 消除噪声
2 分割独立图像元素
3 寻找极大值或极小值区域
膨胀:
将图像和任意寻找内涵进行卷积,提取覆盖区域的最大像素值。这一操作会使亮区扩展
腐蚀:
和膨胀正好相反,提取覆盖区域最下像素值1,这一操作让亮区变细,暗区变大
提取连通域:
两种像素邻接关系会构成连通域:4邻接(上下左右),和8邻接(包括对角线)
opencv里寻找连通域函数findContours()
·语法格式:
image,contours,hierarchy = cv2.findContours(image,mode,method)
式中返回值为:
·image: 与函数参数中的原始图像image一致。
·contours: 返回的轮廓。
·hierarchy: 图像的拓扑信息(轮廓层次)。
式中参数为:
·mode: 轮廓检索模式。
·method: 轮廓的近似方法。
参数mode:
cv2.RETR_EXTERNAL 只检测外轮廓
cv2.RETR_LIST检测的轮廓不建立等级关系
cv2.RETR_CCOMP建立两个等级的轮廓
cv2.RETR_TREE建立一个等级树结构的轮廓
参数method:
cv2.CHAIN_APPROX_NONE存储所有的轮廓点
cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
(具体算法实现可以去了解union-find算法)
颜色识别程序实现
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
red_min = np.array([0, 128, 46])
red_max = np.array([5, 255, 255])
red2_min = np.array([156, 128, 46])
red2_max = np.array([180, 255, 255])
yellow_min = np.array([15, 128, 46])
yellow_max = np.array([50, 255, 255])
while True:
ret,frame = cap.read()
x,y = frame.shape[0:2]
small_frame = cv2.resize(frame, (int(y / 2), int(x / 2)))
cv2.imshow('small', small_frame)
src = small_frame.copy()
res = src.copy()
hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
mask_red1 = cv2.inRange(hsv, red_min, red_max)
mask_red2 = cv2.inRange(hsv, red2_min, red2_max)
mask_yellow = cv2.inRange(hsv, yellow_min, yellow_max)
mask = cv2.bitwise_or(mask_red1, mask_red2)
mask = cv2.bitwise_or(mask, mask_yellow)
res = cv2.bitwise_and(src, src, mask=mask)
h, w = res.shape[:2]
blured = cv2.blur(res, (5, 5))
ret, bright = cv2.threshold(blured, 10, 255, cv2.THRESH_BINARY)
gray = cv2.cvtColor(bright, cv2.COLOR_BGR2GRAY)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
opened = cv2.morphologyEx(gray, cv2.MORPH_CLOSE, kernel)
closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, kernel)
contours, hierarchy = cv2.findContours(closed, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(src, contours, -1, (255, 0, 0), 2)
cv2.imsow("result", src)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
1 red_min = np.array([0, 128, 46])
red_max = np.array([5, 255, 255])
red2_min = np.array([156, 128, 46])
red2_max = np.array([180, 255, 255])
yellow_min = np.array([15, 128, 46])
yellow_max = np.array([50, 255, 255])
我们要识别两种红色和一种黄色。这里列出它们的阈值上下限作为图像二值化的取值范围
2 hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
把图像转化为hsv类型
3 mask_red1 = cv2.inRange(hsv, red_min, red_max)
mask_red2 = cv2.inRange(hsv, red2_min, red2_max)
mask_yellow = cv2.inRange(hsv, yellow_min, yellow_max)
mask = cv2.bitwise_or(mask_red1, mask_red2)
mask = cv2.bitwise_or(mask, mask_yellow)
res = cv2.bitwise_and(src, src, mask=mask)
图像二值化,提取满足阈值范围的像素
cv2.inRange(图像,阈值下限,阈值上限):将阈值范围内像素设为255,阈值之外像素设为0
cv2.bitwise_or(图像1,图像2):图像或运算实现叠加
cv2.bitwise_and(图像1,图像2):图像与运算实现叠加
4 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
opened = cv2.morphologyEx(gray, cv2.MORPH_CLOSE, kernel)
closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, kernel)
提取连续开闭区间用于降噪:
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
设置卷积核,第一个参数代表卷积核形状,有MORPH_RECT(矩形),MORPH_ELLIPSE(椭圆),MORPH_CROSS(十字形),第二个参数代表卷积核行和列
cv2.morphologyEx(要处理图像,处理方式,卷积核)
opened = cv2.morphologyEx(gray, cv2.MORPH_CLOSE, kernel)
开运算,先腐蚀后膨胀,可以消除小黑点,平滑边界。
closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, kernel)
闭运算,先膨胀后腐蚀,可以消除小黑洞
5 contours, hierarchy = cv2.findContours(closed, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(src, contours, -1, (255, 0, 0), 2)
提取连续域,得到区间