做一个实时摄像头识别程序:电脑会自动识别画面里的物体,标注出它的颜色和形状,还会给不同形状画不同颜色的框!
一、代码
python
import cv2
import numpy as np
# ---------------------- 1. 颜色判断函数 ----------------------
def get_color(h, s, v):
# 处理低饱和度(白/灰/黑)
if s < 80 or v < 80:
return "White/Gray"
# 红色:H在0-10或170-180之间
if (h >= 0 and h < 10) or (h >= 170 and h <= 180):
return "Red"
elif h >= 40 and h < 80:
return "Green"
elif h >= 100 and h < 130:
return "Blue"
elif h >= 15 and h < 35:
return "Yellow"
else:
return "Other"
# ---------------------- 2. 形状判断函数 ----------------------
def get_shape(approx):
sides = len(approx)
if sides == 3:
return "Triangle"
elif sides == 4:
return "Rectangle"
elif sides >= 6:
return "Circle"
else:
return "Unknown"
# ---------------------- 3. 主程序:打开摄像头 ----------------------
cap = cv2.VideoCapture(0) # 0代表默认摄像头
while True:
ret, frame = cap.read()
if not ret:
break
# 预处理
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 自适应二值化,比固定阈值更稳 thresh,_ = cv2.thresh(gray,127,255,cv2.THRESH_BINARY_INV)
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) #gray 灰度图,255最大值,方法,反转灰度, 11 块大小(奇数,把图片分成多少 × 多少的小方块),2 让阈值更灵敏 / 更迟钝,这个值越大越迟钝
# 找轮廓
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
area = cv2.contourArea(cnt)
if area < 1000: # 过滤小噪点,可根据效果调整
continue
# 1. 形状判断
epsilon = 0.04 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
shape = get_shape(approx)
# 2. 找物体中心点
M = cv2.moments(cnt)
if M["m00"] == 0:
continue
cx = int(M["m10"] / M["m00"])
cy = int(M["m01"] / M["m00"])
# 3. 取中心点颜色
h_val, s_val, v_val = hsv[cy, cx]
color_name = get_color(h_val, s_val, v_val)
# 4. 画轮廓 + 写文字
if shape == "Triangle":
draw_color = (0, 255, 255) # 黄色框
elif shape == "Rectangle":
draw_color = (0, 255, 0) # 绿色框
elif shape == "Circle":
draw_color = (0, 0, 255) # 红色框
else:
draw_color = (255, 255, 255) # 白色框
cv2.drawContours(frame, [approx], -1, draw_color, 2)
text = f"{color_name} {shape}"
cv2.putText(frame, text, (cx-60, cy), cv2.FONT_HERSHEY_SIMPLEX, 0.6, draw_color, 2)
# 显示结果
cv2.imshow("Real-Time Shape & Color Detection", frame)
# 按ESC键退出
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
二、关键代码和原理解析
python
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
使用自适应的方式获取阈值x ,当像素值>x时为黑(0),否则为白(1),最大值为255,周围使用高斯加权平均,中心元素的权重最大,越远越小。cv2.THRESH_BINARY_INV黑白反转,11 邻域窗口大小。2:常数C,微调阈值,C 越大 → 最终阈值 越小,C 越小 → 最终阈值 **越大,**C 越大 → 更多像素变成白色(前景)。
python
epsilon = 0.04 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True) #误差范围0.04*周长(闭环),闭环
寻找重心:
python
M = cv2.moments(cnt)
if M["m00"] == 0:
continue
cx = int(M["m10"] / M["m00"])
cy = int(M["m01"] / M["m00"])