使用 OPenCV4 做颜色识别十分简单。本文章使用 python 语言来实现一个调色板和简单的颜色识别。
绘制一个调色板对颜色识别非常有用,当然你也可以使用 PS 等软件自带的调色板,那样会有更好的效果。
调色板的实现原理十分简单,就是通过滑动栏来选择不同的数值,来改变图像画布的颜色。因为在颜色识别中多使用 HSV 颜色空间作为识别阈值判定。所以这个调色板就是通过调节 HSV 空间的 "H"、"S"、"V" 的数值来显示一个 BGR 空间的图像。为什么显示的是 BGR 空间的图像呢?因为一般相机读取的格式都是 BGR 的。所以显示 BGR 空间的图像。总之就是:通过调节 HSV 空间的数值,显示 BGR 空间的图像。代码如下:
import cv2
import numpy as np
def nothing(x):
pass
# Trackbar
cv2.namedWindow("frame")
cv2.createTrackbar("H", "frame", 0, 179, nothing)
cv2.createTrackbar("S", "frame", 255, 255, nothing)
cv2.createTrackbar("V", "frame", 255, 255, nothing)
img_hsv = np.zeros((255, 500, 3), np.uint8)
while True:
h = cv2.getTrackbarPos("H", "frame")
s = cv2.getTrackbarPos("S", "frame")
v = cv2.getTrackbarPos("V", "frame")
img_hsv[:] = (h, s, v)
# 图像空间转换(HSV 转 BGR)
img_bgr = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2BGR)
# 数值是 HSV 空间的,但是显示的颜色是 BGR 空间的
cv2.imshow("frame", img_bgr)
key = cv2.waitKey(1)
if key == 27:
break
cv2.destroyAllWindows()
为什么说是简单的颜色识别呢?因为接下来要实现的程序,是有限制的。在 "S"、"V" 空间不变的条件下,只改变 "H" 空间的数值。因此所能识别的颜色有限,只能识别红、橙、黄、绿、紫这五种颜色。具体实现看代码:
import cv2
# 1.获取视频源
cap = cv2.VideoCapture(0)
if cap.open:
print("相机打开成功!\n")
else:
print("未能与相机建立连接...")
# 设置相机属性
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
while True:
# BGR 格式
_, frame = cap.read()
# 2.颜色空间转换(BGR 转 HSV)
hsv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# 获取图像的中心位置坐标,颜色识别就是识别的这一点
height, width, _ = frame.shape
cx = int(width / 2)
cy = int(height / 2)
# Pick pixel value
pixel_center = hsv_frame[cy, cx]
print(pixel_center)
# 获取 H 空间的数值,此颜色识别只考虑 H 空间,S, V 空间同理
hue_value = pixel_center[0]
# 3.颜色识别判定,只考虑 H 空间
color = "Undefined"
if hue_value < 5:
color = "RED"
elif hue_value < 22:
color = "ORANGE"
elif hue_value < 33:
color = "YELLOW"
elif hue_value < 78:
color = "GREEN"
elif hue_value < 131:
color = "BLUE"
elif hue_value < 170:
color = "VIOLET"
else:
color = "RED"
# 获取 BGR 空间中图像中心坐标值,用于使显示的文本和中心区域识别的物体同一个颜色
pixel_center_bgr = frame[cy, cx]
b, g, r = int(pixel_center_bgr[0]), int(pixel_center_bgr[1]), int(pixel_center_bgr[2])
# 图像左上角放置识别出来的颜色文本
cv2.putText(frame, color, (10, 50), 0, 1.5, (b, g, r), 2)
# 识别区域中心画圆
cv2.circle(frame, (cx, cy), 5, (25, 25, 25), 3)
cv2.imshow("video frame", frame)
key = cv2.waitKey(int(1000 / 30))
if key == 27:
break
cap.release()
cv2.destroyAllWindows()