电赛滚球控制系统树莓派代码
基础加发挥部分
图像二值化后,提取最大色块获得坐标即为小球坐标
只提取图像中间部分,避免外界非平板部分干扰
串口通信用的ttyUSB0口,直接一根数据线和stm32的串口1相连就可以了
连接屏幕可以展示效果,但也许有时候展示效果会耗时,建议到时候注释掉展示部分
#获取圆圈坐标并用串口通信将坐标r送到stm32进行处理
# -*- coding: utf-8 -*
import serial
import time
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
lower_red=np.array([156,43,46])
upper_red=np.array([180,255,255])
def DisBall(x,y,r,frame):
cv2.circle(frame, (x,y) , r , (0, 255, 0), 2)
cv2.circle(frame, (x,y) , 2 , (0, 0, 255), 3)
return frame
def Binary_Get_Ball(frame,show,area,thr):
cropped = frame[area[0]:area[1], area[2]:area[3]] #(上,下)(左,右)
gray_img = cv2.cvtColor(cropped, cv2.COLOR_BGRA2GRAY)#图像灰度化
ret,thresh=cv2.threshold(gray_img,thr[0],thr[1],cv2.THRESH_BINARY)
thresh=255-thresh
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] #轮廓检测
#如果存在轮廓
if len(cnts) > 0:
#找到面积最大的轮廓
c = max(cnts, key = cv2.contourArea)
#确定面积最大的轮廓的外接圆
((center_x, center_y), radius) = cv2.minEnclosingCircle(c)
if (show==True):
cv2.circle(cropped, (int(center_x), int(center_y)), int(radius), (0, 255, 255), 2)
cv2.circle(cropped, None, 5, (0, 0, 255), -1)
print('红色色块的中心坐标',(int(center_x),int(center_y)))
else:
center_x=0
center_y=0
radius=0
return center_x,center_y,radius,cropped
if __name__=="__main__":
# 打开串口
ser = serial.Serial("/dev/ttyUSB0", 9600, timeout=0.2)
#剪切区域(上,下)(左,右)
area=[40,435,155,540]
#二值化阈值
thr=[80,255]
time1=time.time()
while(1):
ret, frame = cap.read()
#得到小球坐标
x,y,r,frame=Binary_Get_Ball(frame,show=True,area=area,thr=thr)
time_change=time.time()-time1
time_change=int(time_change*1000)
print('time:'+str(time_change).rjust(3,'0'))
#展示画圆效果
x=int(x)
y=int(y)
r=int(r)
frame = DisBall(x,y,r,frame)
send_data='#'+str(x).rjust(3,'0')+str(y).rjust(3,'0')+str(time_change).rjust(3,'0') #起始标志'#',圆心的x和y
ser.write(send_data.encode("utf8"))
print(send_data)
if (x==0 and y==0 and r==0):
pass
else:
time1=time.time()
# 展示图片
cv2.imshow("capture", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
# 存储图片
cv2.imwrite("camera.jpg", frame)
break
if ser != None:
ser.close()
cap.release()
cv2.destroyAllWindows()
发挥题其他:追光者(追踪红色激光)
#获取圆圈坐标并用串口通信将坐标r送到stm32进行处理
# -*- coding: utf-8 -*
import serial
import time
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
lower_red=np.array([156,43,46])
upper_red=np.array([180,255,255])
def DisBall(x,y,r,frame):
cv2.circle(frame, (x,y) , r , (0, 255, 0), 2)
cv2.circle(frame, (x,y) , 2 , (0, 0, 255), 3)
return frame
def Binary_Get_Point(frame,show,area,thr,thr1):
cropped = frame[area[0]:area[1], area[2]:area[3]] #(上,下)(左,右)
gray_img = cv2.cvtColor(cropped, cv2.COLOR_BGRA2GRAY)#图像灰度化
ret,thresh=cv2.threshold(gray_img,thr[0],thr[1],cv2.THRESH_BINARY)
ret,thresh1=cv2.threshold(gray_img,thr1[0],thr1[1],cv2.THRESH_BINARY)
thresh=255-thresh
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] #轮廓检测
cnts1 = cv2.findContours(thresh1.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] #轮廓检测
#如果存在轮廓
if len(cnts) > 0:
#找到面积最大的轮廓
c = max(cnts, key = cv2.contourArea)
#确定面积最大的轮廓的外接圆
((center_x, center_y), radius) = cv2.minEnclosingCircle(c)
if (show==True):
cv2.circle(cropped, (int(center_x), int(center_y)), int(radius), (0, 255, 255), 2)
cv2.circle(cropped, None, 5, (0, 0, 255), -1)
print('小球的中心坐标',(int(center_x),int(center_y)))
else:
center_x=0
center_y=0
radius=0
#如果存在轮廓
if len(cnts1) > 0:
#找到面积最大的轮廓
c1 = max(cnts1, key = cv2.contourArea)
#确定面积最大的轮廓的外接圆
((center_x1, center_y1), radius1) = cv2.minEnclosingCircle(c1)
if (show==True):
cv2.circle(cropped, (int(center_x1), int(center_y1)), int(radius1), (0, 255, 255), 2)
cv2.circle(cropped, None, 5, (0, 0, 255), -1)
print('激光的坐标',(int(center_x1),int(center_y1)))
else:
center_x1=0
center_y1=0
radius1=0
return center_x,center_y,radius,center_x1,center_y1,radius1,cropped
if __name__=="__main__":
# 打开串口
ser = serial.Serial("/dev/ttyUSB0", 9600, timeout=0.2)
#剪切区域(上,下)(左,右)
area=[40,435,155,540]
#二值化阈值
thr=[80,255]
thr1=[200,255]
time1=time.time()
while(1):
ret, frame = cap.read()
x,y,r,x1,y1,r1,frame=Binary_Get_Point(frame,show=True,area=area,thr=thr,thr1=thr1)
time_change=time.time()-time1
time_change=int(time_change*1000)
print('time:'+str(time_change).rjust(3,'0'))
#展示画圆效果
x=int(x)
y=int(y)
r=int(r)
x1=int(x1)
y1=int(y1)
r1=int(r1)
frame = DisBall(x,y,r,frame)
frame = DisBall(x1,y1,r1,frame)
send_data='#'+str(x).rjust(3,'0')+str(y).rjust(3,'0')+str(time_change).rjust(3,'0') #起始标志'#',圆心的x和y
ser.write(send_data.encode("utf8"))
print(send_data)
send_data='$'+str(x1).rjust(3,'0')+str(y1).rjust(3,'0')+str(time_change).rjust(3,'0')
ser.write(send_data.encode("utf8"))
print(send_data)
if (x==0 and y==0 and r==0):
pass
else:
time1=time.time()
# 展示图片
cv2.imshow("capture", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
# 存储图片
cv2.imwrite("camera.jpg", frame)
break
if ser != None:
ser.close()
cap.release()
cv2.destroyAllWindows()