先上代码:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
import time
import cv2
import config
from serial_port import Serial
from camera import Camera
from detectors import SignDetector,TaskDetector
import threading
import numpy as np
class run:
def __init__(self):
self.front_camera = Camera(config.front_cam, [640, 480]) #前摄像头初始化
#config.front_cam 参数指定了要读
# 取的摄像头的设备编号或地址,而 [640, 480] 参数指定了读取的图像的尺寸。
self.com=Serial() #串口初始化
self.front_camera.start() #开启前摄像头线程
#程序会调用 Camera 类中的 run() 方法,在其中循环
# 读取摄像头图像,并将其保存在 self.front_image 中。
self.td = TaskDetector() #侧图标模型初始化
self.stopped = False #停止识别标志位
def front_start(self): #前图标模型线程
threading.Thread(target=self.front_updata, args=()).start()
print('front model start')
##############################################front
def front_updata(self):
k=0
while True:
if self.stopped:
print('front model stop')
break
self.x=1000
self.y=1000
self.front_image = self.front_camera.read()
if k <5:
k=k+1
else:
k=0
try:
self.signs = self.td.detect(self.front_image)
for self.sign in self.signs:
self.left = self.sign.relative_box[0]
self.top = self.sign.relative_box[1]
self.right = self.sign.relative_box[2]
self.bottom = self.sign.relative_box[3]
# self.front_val = str(self.sign)[5] + '=' + str(int(self.top))
self.x=((int(self.top * 480) + int(self.bottom * 480))/2)
self.y=(( int(self.left*640)+int(self.right*640))/2)
self.com.write("CB="+str(self.sign.index)+"+"+str(self.x) +"+"+ str(self.y)+'\n')
print(("CB="+str(self.sign.index)+"+"+str(self.x) +"+"+ str(self.y)+'\n'))
except:
self.com.write("CB="+"0"+"+"+str(self.x)+"+"+str(self.y)+"+"+"\n")
print("CB="+str(0)+"+"+str(self.x) +"+"+ str(self.y)+'\n')
def cc_show(self):#cc_show方法用于将检测到的标志在图像上显示出来,但在代码中被注释掉了。
try:
#draw_res(self.front_image, self.signs)
#draw_res(self.side_image, self.tasks)
#self.front_frame = draw_cruise_result(self.front_image, self.csruise_result)
cv2.imshow("show", self.front_frame)
#cv2.imshow("show1", self.front_image)
except:
print('show error')
################################################result
if __name__=='__main__':
fig=0
num=0
go = run()
go.front_start()
#定义了front_start方法,该方法会开启一个线程并调用front_updata方法,用于获取
# 前置摄像头的图像,并进行标志检测和位置计算。然后将检测结果通过串口发送给其他硬件设备。
time.sleep(0.5)
print('go')
while True:
if fig==1:
name = 'picc/' + 'o' + str(num) + ".jpg"
data = (-(80 - go.front_val) / 80)
print(data)
cv2.imwrite(name, go.front_image)
f.write(name + " " + str(data) + "\n")
print(name + " " + str(go.send) + " is OK!")
num = num + 1
if cv2.waitKey(1) & 0xFF == ord('s'):
fig=1
if cv2.waitKey(1) & 0xFF == ord('a'):
fig=0
f.close()
print("over")
break
# if cv2.waitKey(1) & 0xFF == ord('d'):
# f.close()
# break
# cv2.waitkey(1)
#
# cv2.destroyAllWindows()
1,其中新建了一条独立线程(通过使用threading.Thread
函数,可以让self.front_updata
方法在一个独立的线程中运行,不会阻塞主线程的执行。)
其中的arg=() :
参数 args
用于指定要传递给目标函数 target
的参数,是一个元组类型。如果目标函数不需要传递参数,则 args
可以为空,即 args=()
。
在这个特定的代码中,args=()
表示 self.front_updata()
函数没有需要传递的参数。
start()
是 Thread
类提供的一个方法,用于启动一个新的线程来执行指定的函数(或方法)。调用 start()
方法后,线程会在后台异步执行指定的函数,不会阻塞主线程。如果没有调用 start()
方法,线程不会执行。同时,每个线程只能被启动一次,多次调用 start()
方法会抛出异常。
2,解析front_updata方法:
这段代码定义了一个名为front_updata
的方法,用于在前置摄像头上检测目标并发送控制信号给单片机。
方法主要的步骤包括:
-
用一个无限循环(
while True
)来不断读取前置摄像头的图像,并处理图像中的目标。如果self.stopped
的值为True
,则跳出循环。 -
首先将坐标
self.x
和self.y
的值设为1000,表示当前没有检测到目标。然后通过self.front_camera.read()
方法读取前置摄像头的图像,并将其保存在self.front_image
变量中。(将self.x和self.y的值设为1000的目的是在没有检测到目标时,将其坐标值设置为一个特殊的值,以便在后续使用这些值时能够知道目标没有被检测到。例如,在代码中,如果self.x和self.y的值没有被更新,则会将其设为1000,并在发送到串口时加上一个特殊的标记,以便在接收方知道当前没有检测到目标。这样可以避免在没有检测到目标时出现意外的行为或错误。) -
为了减少目标检测的计算量,设置了一个计数器
k
,每5帧图像才进行一次目标检测。 -
如果计数器
k
达到5,则调用目标检测器(self.td.detect()
方法)在当前图像中检测目标。检测结果保存在self.signs
列表中,遍历每一个目标(self.sign in self.signs
),获取目标的左上角和右下角坐标(self.left
、self.top
、self.right
和self.bottom
)。 -
根据目标的左上角和右下角坐标,计算目标在图像中的中心点坐标,并将其赋值给
self.x
和self.y
。然后调用self.com.write()
方法将控制信号发送给单片机,格式为“CB=目标编号+x坐标+y坐标+换行符”。 -
如果在目标检测过程中发生异常,则默认当前图像中没有目标,将控制信号“CB=0+1000+1000+换行符”发送给单片机。同时,在终端上打印出“CB=0+x坐标+y坐标+换行符”的消息。
注意,该方法中涉及到一些变量和方法的来源需要在其他代码中寻找。比如self.stopped
是一个标志位,用于控制线程的停止;self.td.detect()
方法是目标检测器的接口方法,用于检测目标并返回检测结果;self.com.write()
方法用于向串口发送数据,用于控制机器人运动。