识别正确的效果是框住图形并写出它的颜色形状,但识别空心图形的时候标了两个框,且没有写出颜色形状。
import cv2
import numpy as np
import time
cv2.MORPH_ELLIPSE
cv2.MORPH_OPEN
cv2.MORPH_CLOSE
# 定义颜色范围(HSV 颜色空间)
lower_red = np.array([0, 43, 46])
upper_red = np.array([10, 255, 255])
lower_blue = np.array([100, 43, 46])
upper_blue = np.array([124, 255, 255])
# 黑色通常是低明度值区域,这里假设 HSV 中明度值小于 50
lower_black = np.array([0, 0, 0])
upper_black = np.array([180, 255, 50])
# 打开摄像头
cap = cv2.VideoCapture(0)
# 开启总动曝光
cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0)
# 用以判断识别内容是否稳定
f_shape = ""
shape = ""
timer1 = 0
aspect_ratio = 0
is_running = True # 新增变量,用于控制识别是否运行
history = [] # 用于存储历史识别结果
while True:
# 读取键盘输入
key = cv2.waitKey(1) & 0xFF
if key == ord('s'):
is_running = not is_running
print(f"识别功能 {'开启' if is_running else '关闭'}")
if not is_running:
continue
# 读取帧
ret, frame = cap.read()
if not ret:
break
# 转换为 HSV 颜色空间
hsv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# 根据颜色范围创建掩膜
red_mask = cv2.inRange(hsv_frame, lower_red, upper_red)
blue_mask = cv2.inRange(hsv_frame, lower_blue, upper_blue)
black_mask = cv2.inRange(hsv_frame, lower_black, upper_black)
# 合并颜色掩码
combined_mask = cv2.bitwise_or(red_mask, cv2.bitwise_or(blue_mask, black_mask))
# 形态学操作
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
combined_mask = cv2.morphologyEx(combined_mask, cv2.MORPH_OPEN, kernel)
combined_mask = cv2.morphologyEx(combined_mask, cv2.MORPH_CLOSE, kernel)
# 平衡亮度
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
average_brightness = cv2.mean(gray_frame)[0]
if average_brightness < 50 or average_brightness > 200:
alpha = 1.5 if average_brightness < 50 else 0.8
frame = cv2.convertScaleAbs(frame, alpha=alpha, beta=0)
# 查找轮廓
contours, hierarchy = cv2.findContours(combined_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 先进行颜色判断
for contour in contours:
area = cv2.contourArea(contour)
if area < 10000: # 设置面积阈值,可根据实际情况调整
continue
# 获取轮廓的中心坐标
M = cv2.moments(contour)
if M["m00"]!= 0:
cx = int(M["m10"] / M["m00"])
cy = int(M["m01"] / M["m00"])
color = ""
pixel_color = hsv_frame[cy, cx]
if np.all((lower_red <= pixel_color) & (pixel_color <= upper_red)):
color = "Red"
elif np.all((lower_blue <= pixel_color) & (pixel_color <= upper_blue)):
color = "Blue"
elif np.all((lower_black <= pixel_color) & (pixel_color <= upper_black)):
color = "Black"
if color:
# 进行形状判断
approx = cv2.approxPolyDP(contour, 0.02 * cv2.arcLength(contour, True), True)
if len(approx) == 4:
x, y, w, h = cv2.boundingRect(approx)
aspect_ratio = float(w) / h
diagonal_length = np.sqrt(w * w + h * h)
# 更严格的正方形判断
if aspect_ratio >= 0.95 and aspect_ratio <= 1.2 and abs(diagonal_length - np.sqrt(2) * w) < 5:
if color == "Red":
shape = "Red hollow square"
elif color == "Blue":
shape = "Blue solid square"
elif aspect_ratio >= 1.4 and aspect_ratio <= 1.8:
if color == "Red":
shape = "Red solid rectangle"
elif color == "Blue":
shape = "Blue hollow rectangle"
else:
top_width = min(approx[0][0][0], approx[1][0][0]) - min(approx[2][0][0], approx[3][0][0])
bottom_width = max(approx[0][0][0], approx[1][0][0]) - max(approx[2][0][0], approx[3][0][0])
height = h
if top_width > bottom_width and top_width!= 0:
if height / top_width < 0.8:
if color == "Red":
shape = "Red hollow lower trapezoid"
elif color == "Blue":
shape = "Blue solid lower trapezoid"
else:
shape = "Lower Trapezoid"
elif top_width < bottom_width and bottom_width!= 0:
if height / bottom_width < 0.8:
if color == "Red":
shape = "Red solid upper trapezoid"
elif color == "Blue":
shape = "Blue hollow upper trapezoid"
else:
# 更严格的圆形判断
(x, y), radius = cv2.minEnclosingCircle(contour)
center = (int(x), int(y))
radius = int(radius)
area_circle = np.pi * radius * radius
if abs(area - area_circle) < 0.1 * area:
if color == "Blue":
shape = "Blue solid circle"
elif color == "Black":
shape = "Black solid circle"
cv2.putText(frame, shape, (cx - 50, cy), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 254), 2)
history.append(shape)
if len(history) > 10:
history.pop(0)
if all(result == history[0] for result in history):
f_shape = history[0]
timer1 += 1
else:
f_shape = ""
# 用方框框住识别内容
x, y, w, h = cv2.boundingRect(contour)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 显示结果
cv2.imshow('Frame', frame)
if timer1 == 30: # 增加连续判断次数
print(f_shape)
timer1 = 0
# 按下 'q' 键退出
if key == ord('q'):
break
print(aspect_ratio)
# 释放资源
cap.release()
cv2.destroyAllWindows()
识别空心图形:
识别实心图形: