import time
import cv2
import numpy as np
import math
import serial
# ser = serial.Serial('/dev/ttyUSB0', 115200)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
def emitMessage(position, _right, _up):
ser = serial.Serial('COM5', 115200)
# ltemp = []
length = 3
for i in range(length):
p = position[i] * 100
p = int(p)
bp = int.to_bytes(p, 2, byteorder='little', signed=False)
ser.write(bp)
# ltemp.append(bp[:1])
# ltemp.append(bp[1:])
light_open = 1
is_right = _right
is_up = _up
ser.write(bytes.fromhex(hex(light_open).lstrip("0x").zfill(2)))
ser.write(bytes.fromhex(hex(is_right).lstrip("0x").zfill(2)))
ser.write(bytes.fromhex(hex(is_up).lstrip("0x").zfill(2)))
# ltemp.append(bytes.fromhex(hex(light_open).lstrip("0x").zfill(2)))
# ltemp.append(bytes.fromhex(hex(is_right).lstrip("0x").zfill(2)))
# ltemp.append(bytes.fromhex(hex(is_up).lstrip("0x").zfill(2)))
# for b in ltemp:
# print('{:02x}'.format(b[0]), end=' ')
# print()
time.sleep(0.1)
ser.close()
def detect(frame, flag):
# 转换颜色空间为HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# 根据红色的HSV范围创建掩膜
if flag == 'red':
"""
lor = np.array([160, 0, 250])
hir = np.array([180, 255, 255])
"""
mask = cv2.inRange(hsv, np.array([160, 0, 250]),np.array([180, 255, 255])) # 红 捕捉到了比较暗的区域
elif flag == 'green':
mask = cv2.inRange(hsv, np.array([80, 0, 230]), np.array([120, 255, 255])) # 绿 还需调整
# mask = cv2.inRange(hsv, np.array([80, 0, 200]), np.array([120, 255, 210])) # 绿 还需调整
mask = cv2.dilate(mask, None, iterations=5)
# 寻找轮廓
contours, _ = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if len(contours) > 0:
# 找到面积最大的轮廓
max_contour = max(contours, key=cv2.contourArea)
# 计算轮廓的最小外接圆
((x, y), radius) = cv2.minEnclosingCircle(max_contour)
# print(x,y)
# if x<140 or x>380 or y<210 or y>460:
# return -1
# 计算轮廓的矩形边界框
rect = cv2.minAreaRect(max_contour)
box = cv2.boxPoints(rect)
box = np.int0(box)
# 绘制轮廓和边界框
cv2.drawContours(frame, [box], 0, (0, 255, 0), 2)
cv2.circle(frame, (int(x), int(y)), int(radius), (0, 255, 255), 2)
cv2.putText(frame, flag, (int(x), int(y) + int(radius)), cv2.FONT_HERSHEY_SIMPLEX, 1, 1)
# 计算中心坐标
M = cv2.moments(max_contour)
center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
# 在图像上绘制中心坐标
cv2.circle(frame, center, 5, (0, 0, 255), -1)
return center
next_red_center=(0,0)
def read_usb_capture():
# 选择摄像头的编号
cap = cv2.VideoCapture(0) # 0是笔记本自带摄像头
# 添加这句是可以用鼠标拖动弹出的窗体
# cv2.namedWindow('video', cv2.WINDOW_AUTOSIZE)
# cv2.resizeWindow("video", 640, 480) # 设置长和宽
# points_list = []
flag=1
key1 = 0
points_list = [(0, 0) for i in range(5)]
while (cap.isOpened()): # 循环
ret, frame = cap.read() # read放回2个值,第一个是True和False 是否打开 第二个是传入图像
frame = frame[130:390, 190:450]#上下左右
if flag:
box1 = lunkuo(frame) # 每帧进行轮廓检测,更新直角点
for i in range(len(box1)):
points_list[i] = box1[i]
points_list[4] = box1[0]
flag=0
red_center = detect(frame, 'red')
if red_center==None:
red_center=next_red_center
if points_list[key1][1] - red_center[1] < 0:
_up = 1
else:
_up = 0
if points_list[key1][0] - red_center[0] < 0:
_right = 0
else:
_right = 1
if red_center == None:
if points_list[key1][0] - red_center[0] < 0:
red_center[0]-=1
else:
red_center[0] += 1
if points_list[key1][1] - red_center[1] < 0:
red_center[1] += 1
else:
red_center[1] -= 1
dlta_x = abs(points_list[key1][1] - red_center[1])
dlta_y = abs(points_list[key1][0] - red_center[0])
if dlta_x > dlta_y:
dx = min(dlta_x, 10)
dy = dx * dlta_y / dlta_x
else:
dy = min(dlta_y, 10)
dx = dy * dlta_x / dlta_y
if math.sqrt(dlta_x ** 2 + dlta_y ** 2) < 5:
key1 += 1
if key1 == 5:
break
continue
print(red_center)
print(points_list[key1])
print("dlta_x", points_list[key1][1] - red_center[1])
print("dlta_y", points_list[key1][0] - red_center[0])
print("dx", dx)
print("dy", dy)
next_red_center=(red_center[0]+dx,red_center[1]+dy)
emitMessage((dx, dy, 1), _up, _right)
# pt_index = (0, 1, 2, 3, 0)
# for i in range(4):
# pt1 = box1[pt_index[i]]
# pt2 = box1[pt_index[i + 1]]
# cv2.line(frame, pt1, pt2, (0, 255, 0), 2)
# cv2.imshow('video', frame) # 显示出来
cv2.waitKey(10)
# 释放画面
cap.release()
cv2.destroyAllWindows()
def lunkuo(img): # 检测轮廓
img1_ = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换为灰度
_,binary=cv2.threshold(img1_,0,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU)
kernel1 = np.ones((5, 5), np.uint8)
erode = cv2.erode(binary, kernel1)
# img_ = cv2.GaussianBlur(erode, (5, 5), 0) # 高斯滤波去噪点
# img__ = cv2.Canny(erode, 75, 200) # Canny边缘检测
img__ = cv2.dilate(erode, None, iterations=1) # 扩张
# img__ = cv2.erode(img__, None, iterations=1) # 腐蚀
# 轮廓检测
contours, _ = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
print('img.shape', img.shape)
cnt = contours[0]
cv2.drawContours(img, [cnt], 0, (0, 255, 0), 1)
cnt = contours[1]
cv2.drawContours(img, [cnt], 0, (0, 0, 255), 1)
rect1 = cv2.minAreaRect(contours[0])
box1 = cv2.boxPoints(rect1)
box1 = np.array(box1).astype(int)
rect2 = cv2.minAreaRect(contours[1])
box2 = cv2.boxPoints(rect2)
box2 = np.array(box2).astype(int)
box = np.mean(np.array((box1, box2)), 0)
box = np.array(box).astype(int)
for i in range(len(box)):
cv2.circle(img, tuple(box1[i]), 1, (0, 255, 0), 2)
cv2.circle(img, tuple(box2[i]), 1, (0, 0, 255), 2)
cv2.circle(img, tuple(box[i]), 1, (0, 255, 255), 2)
cv2.line(img, tuple(box[0]), tuple(box[1]), (0, 255, 255), 1)
cv2.line(img, tuple(box[1]), tuple(box[2]), (0, 255, 255), 1)
cv2.line(img, tuple(box[2]), tuple(box[3]), (0, 255, 255), 1)
cv2.line(img, tuple(box[3]), tuple(box[0]), (0, 255, 255), 1)
# cv2.imshow("1", img)
# cv2.waitKey(0)
return box
read_usb_capture() # 开始