要求 :分辨出一个随机颜色(红色,蓝色)的图形(圆形,矩形,三角形)
思路 : HSV色块识别+轮廓提取+同一高度面积识别
一、HSV模型
HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。这个模型中颜色的参数分别是:色调(H),饱和度(S),明度(V)。
HSV色彩空间
注意:红色的H空间有两部分,需要将两部分融合后提取轮廓。
二、提取轮廓后,固定高度下分别检测圆形、正方形、三角形的面积阈值。
示例代码如下:
# encoding=utf-8
import cv2 as cv
import numpy as np
import time
import serial
def analysis(frame):
global red_triangle
global red_rectangle
global red_circle
global blue_triangle
global blue_rectangle
global blue_circle
h,w,ch = frame.shape
result = np.zeros((h, w, ch), dtype=np.uint8)
kernel = np.ones((5, 5), np.uint8)
l_red1 = np.array([[0,43,46]])
h_red1 = np.array([10,255,255])
l_red2 = np.array([[160,43,46]])
h_red2 = np.array([180,255,255])
l_blue = np.array([[100,43,46]])
h_blue = np.array([124,255,255])
try:
red_img=frame.copy()
hsv = cv.cvtColor(red_img, cv.COLOR_BGR2HSV)
binary=cv.inRange(hsv,l_red1,h_red1)
binary3=cv.inRange(hsv,l_red2,h_red2)
binary = cv.dilate(binary, kernel, iterations=1)#膨胀
binary3 = cv.dilate(binary3, kernel, iterations=1)
binary4=cv.addWeighted(binary,1,binary3,1,0)#两部分红色融合
cv.imshow('binary4:', binary4)
contours,binary1=cv.findContours(binary4,1,1)
draw_img=red_img.copy()
red_copy=cv.drawContours(draw_img,contours,-1,(255,0,0),2)
cv.imshow('red_img:', red_copy)
cnt=contours[0]
p1 = cv.arcLength(cnt, True)
area1 = cv.contourArea(cnt)
print("area1",area1)
print("p1",p1)
if 0 <= area1 <=30000:
print('R3')
ser.write(("SR3E").encode())
elif 30000 < area1 <= 35000:
print('R1')
ser.write(("SR1E").encode())
elif 35000 < area1 <= 60000:
print('R2')
ser.write(("SR2E").encode())
except:
pass
try:
blue_img=frame.copy()
hsv1 = cv.cvtColor(blue_img, cv.COLOR_BGR2HSV)
binary1=cv.inRange(hsv1,l_blue,h_blue)
binary1 = cv.dilate(binary1, kernel, iterations=1)
contours1,binary2=cv.findContours(binary1,1,1)
draw_img=blue_img.copy()
blue_copy=cv.drawContours(draw_img,contours1,-1,(255,0,0),2)
cv.imshow('blue_img:', blue_copy)
cv.imshow('binary1:', binary1)
cnt=contours1[0]
p2 = cv.arcLength(cnt, True)
area2= cv.contourArea(cnt)
print("area2",area2)
print("p2",p2)
if 0 <= area2 <=26000:
print('B3')
ser.write(("SB3E").encode())
elif 26000 < area2 <= 35000:
print('B1')
ser.write(("SB1E").encode())
elif 35000 < area2 <= 60000:
print('B2')
ser.write(("SB2E").encode())
except:
pass
#串口通信
if __name__ == "__main__":
ser = serial.Serial("/dev/ttyAMA0", 57600)
#color_str = ''
red_triangle = 0
red_rectangle = 0
red_circle = 0
blue_triangle = 0
blue_rectangle = 0
blue_circle = 0
#shape_color = []
cap = cv.VideoCapture('/dev/video0')
while (True):
ret, src = cap.read()
analysis(src)
if cv.waitKey(1) & 0xFF == ord('q'):
break
# 清空接收缓冲区
ser.flushInput()
cap.release()
cv.destroyAllWindows()
ser.close()



