|
|
from PyQt5 import QtCore,QtGui
|
|
|
from PyQt5.QtCore import QTimer,QCoreApplication,Qt,pyqtSignal
|
|
|
from PyQt5.QtWidgets import QApplication,QMainWindow,QMessageBox,QLabel,QWidget
|
|
|
from PyQt5.QtGui import QImage,QPixmap,QIcon
|
|
|
from UIfile.MainWindow2 import Ui_MainWindow
|
|
|
from myTello import myTello
|
|
|
import mySpeechRecognition_UI,myGesture_UI
|
|
|
import sys,datetime
|
|
|
import cv2,threading
|
|
|
import TelloCV_ball_people
|
|
|
import AlphaPose_control
|
|
|
|
|
|
class mainWindow(QMainWindow,Ui_MainWindow):
|
|
|
sent_move_distance_per_step = pyqtSignal(int) #向子窗口发送当前设置的步长
|
|
|
def __init__(self):
|
|
|
super(mainWindow, self).__init__()
|
|
|
self.setupUi(self)
|
|
|
|
|
|
#子窗口
|
|
|
self.speechRecognitionUI = mySpeechRecognition_UI.mySpeechRecognition_UI() #语音识别窗口
|
|
|
self.gestureUI = myGesture_UI.myGesture_UI() #手势控制窗口
|
|
|
|
|
|
# #加载中
|
|
|
# self.loadingUI = myLoadingUI.myLoading_UI(self)
|
|
|
# self.loadingUI_thread = loading_thread(self.loadingUI)
|
|
|
# self.loadingUI_thread.setDaemon(True)
|
|
|
# self.loadingUI_thread.start()
|
|
|
|
|
|
self.iniUI()
|
|
|
self.statusBar_init() #初始化状态栏
|
|
|
self.signal_slot_init() #初始化控件触发与反应函数
|
|
|
self.Video_show_init() #有关视频显示的初始化
|
|
|
|
|
|
self.RMTT = False #标记是否连接到RMTT拓展板
|
|
|
|
|
|
self.date_fmt = '%Y-%m-%d_%H%M%S' #日期格式
|
|
|
|
|
|
|
|
|
def iniUI(self):
|
|
|
'''有关控件的初始化'''
|
|
|
self.power = False #标记是否打开了"电源",刚开始电源键是关闭的
|
|
|
|
|
|
self.move_distance_per_step = 20 # 设置初始的每次给出移动命令后移动的步长
|
|
|
self.speed = 25 #设置移动速度'
|
|
|
|
|
|
#同步设置主界面速度与步长的初始值
|
|
|
self.horizontalSlider_setSpeed.setValue(self.speed)
|
|
|
self.horizontalSlider_set_MoveDistancePerStep.setValue(self.move_distance_per_step)
|
|
|
|
|
|
|
|
|
def Video_show_init(self):
|
|
|
'''有关视频显示的初始化'''
|
|
|
self.is_show_initial_frame = True #标记是否显示原始视频
|
|
|
self.Tello_frame = None #存储Tello传回来的图像
|
|
|
|
|
|
self.timer_initial_video_show = QTimer(self) #用于显示原始图像的倒计时
|
|
|
self.timer_initial_video_show.timeout.connect(self.show_initial_frame)
|
|
|
|
|
|
self.channel = 3
|
|
|
|
|
|
def signal_slot_init(self):
|
|
|
'''各信号的初始化'''
|
|
|
self.pushButton_power.clicked.connect(self.powerBtn_clicked) #当电源键被按下时
|
|
|
self.pushButton_emergency_brake.clicked.connect(self.emergancyBtn_clicked) #紧急制动按钮
|
|
|
self.horizontalSlider_set_MoveDistancePerStep.valueChanged.connect(self.update_distance_per_step) #每次移动步长的更新
|
|
|
self.horizontalSlider_setSpeed.valueChanged.connect(self.update_speed) #移动速度的更新
|
|
|
|
|
|
#来自语音控制窗口相关的信号处理
|
|
|
self.radioButton_speech_control.clicked.connect(self.open_speechRecognition_Window) #当按下语音控制按钮时打开语音控制界面
|
|
|
self.speechRecognitionUI.when_closed.connect(self.speechRecognitionUI_closed) #当关闭语音控制界面时的触发函数
|
|
|
self.speechRecognitionUI.send_order_signal.connect(self.speech_control) #订阅来自子窗口返回的语音命令
|
|
|
self.speechRecognitionUI.speech_recognition_thread.send_LED_state.connect(self.update_LED_state) #订阅改变LED状态的消息
|
|
|
|
|
|
#手势控制相关信号
|
|
|
self.actiongestureControl.triggered.connect(self.open_gestureUI) #打开手势控制窗口
|
|
|
self.gestureUI.signal_send_order_to_Tello.connect(self.process_gesture_order) #处理手势控制的发过来的命令
|
|
|
self.sent_move_distance_per_step.connect(self.gestureUI.get_move_distance_per_step) #主窗口步长变化时,更新子窗口的步长
|
|
|
|
|
|
#目标跟踪相关信号
|
|
|
self.actiongreenBall.triggered.connect(self.start_ball_track) #开始球跟踪
|
|
|
self.timer_ball_track = QTimer()
|
|
|
self.timer_ball_track.timeout.connect(self.show_ball_track_img_and_control_tello)
|
|
|
|
|
|
self.timer_face_track = QTimer()
|
|
|
self.actionpeople.triggered.connect(self.start_face_track) #开始人脸跟踪
|
|
|
self.timer_face_track.timeout.connect(self.show_face_track_img_and_control_tello)
|
|
|
|
|
|
#体态控制
|
|
|
self.actionpostureControl.triggered.connect(self.start_pose_control)
|
|
|
self.timer_pose_control = QTimer()
|
|
|
self.timer_pose_control.timeout.connect(self.show_pose_control_result)
|
|
|
self.AlphaPose_control = AlphaPose_control.AlphaPose_control()
|
|
|
|
|
|
|
|
|
#关闭已打开功能
|
|
|
self.actioncloseALL.triggered.connect(self.close_ALL_functions)
|
|
|
|
|
|
# 拍照
|
|
|
self.pushButton_take_photo.clicked.connect(self.take_picture)
|
|
|
|
|
|
# 录像
|
|
|
self.pushButton_video_record.clicked.connect(self.record_video)
|
|
|
self.start_video_record = False
|
|
|
|
|
|
|
|
|
|
|
|
def update_speed(self):
|
|
|
'''速度设置更新函数'''
|
|
|
self.speed = self.horizontalSlider_setSpeed.value()
|
|
|
|
|
|
def update_distance_per_step(self):
|
|
|
'''步长设置更新函数'''
|
|
|
self.move_distance_per_step = self.horizontalSlider_set_MoveDistancePerStep.value()
|
|
|
|
|
|
self.sent_move_distance_per_step.emit(self.move_distance_per_step) #同时向子窗口发送现在的步长
|
|
|
|
|
|
def power_pushed_reply(self):
|
|
|
'''按下按钮时的弹窗,确保已经连接到Tello的WiFi'''
|
|
|
reply = QMessageBox(QMessageBox.Warning,'warning','请先确保已连接到Tello的Wi-Fi')
|
|
|
No = reply.addButton(self.tr('未连接'),QMessageBox.NoRole)
|
|
|
Yes = reply.addButton(self.tr('已连接(无拓展板)'),QMessageBox.YesRole)
|
|
|
RMTT = reply.addButton(self.tr('已连接(有拓展板)'),QMessageBox.YesRole)
|
|
|
reply.exec_()
|
|
|
if reply.clickedButton() == No:
|
|
|
return False
|
|
|
elif reply.clickedButton() == Yes:
|
|
|
return True
|
|
|
elif reply.clickedButton() == RMTT:
|
|
|
self.RMTT = True
|
|
|
return True
|
|
|
|
|
|
def powerBtn_clicked(self):
|
|
|
'''电源键按下的出发动作'''
|
|
|
#若此时电源处于关闭状态
|
|
|
if self.power == False:
|
|
|
reply = self.power_pushed_reply()
|
|
|
if not reply:
|
|
|
return
|
|
|
else:
|
|
|
try:
|
|
|
self.Tello = myTello() # 定义一个扩展tello实例,里面有更多的功能
|
|
|
self.about_tello_init()
|
|
|
|
|
|
self.connect_status_label_value.setText('连接成功')
|
|
|
self.power = True #标记电源为打开状态
|
|
|
|
|
|
#更新电源图标
|
|
|
self.pushButton_power.setIcon(QIcon(QPixmap("../ico/power_button_442px_1301172_easyicon_red.net.png")))
|
|
|
|
|
|
self.timer_initial_video_show.start(100)
|
|
|
|
|
|
except:
|
|
|
self.connect_status_label_value.setText('连接失败')
|
|
|
|
|
|
#如果此时电源处于打开状态
|
|
|
elif self.power == True:
|
|
|
self.power = False
|
|
|
if self.Tello != None:
|
|
|
self.Tello.land() #确保着陆
|
|
|
self.timer_initial_video_show.stop() #停止显示图像的计时
|
|
|
self.timer_ball_track.stop()
|
|
|
self.timer_face_track.stop()
|
|
|
self.TelloCV.tracking = False
|
|
|
self.label_show_video_frame.clear() #清空显示
|
|
|
self.Tello.sock.close() #关闭socket,避免下次打开时冲突
|
|
|
self.Tello.quit() #关闭Tello的各线程
|
|
|
del self.Tello #释放Tello实例
|
|
|
self.pushButton_power.setIcon(QIcon(QPixmap("../ico/power_button_442px_1301172_easyicon.net.png"))) #更新电源图标
|
|
|
self.connect_status_label_value.setText('请按电源键尝试建立连接') #更新状态栏
|
|
|
|
|
|
def emergancyBtn_clicked(self):
|
|
|
'''紧急刹车'''
|
|
|
if self.power:
|
|
|
self.Tello.send('emergency')
|
|
|
else:
|
|
|
self.status.showMessage('请先连接Tello',2000)
|
|
|
|
|
|
def statusBar_init(self):
|
|
|
'''状态栏的初始化函数'''
|
|
|
self.status = self.statusBar()
|
|
|
self.connect_status_label = QLabel('连接状态:')
|
|
|
self.connect_status_label_value = QLabel('请按电源键尝试建立连接')
|
|
|
self.status.addPermanentWidget(self.connect_status_label,stretch=0,)
|
|
|
self.status.addPermanentWidget(self.connect_status_label_value,stretch=0)
|
|
|
|
|
|
|
|
|
def about_tello_init(self):
|
|
|
'''关于tello的初始化函数'''
|
|
|
|
|
|
# self.Tello.send('command') #直接进入手动控制模式
|
|
|
#存储飞行状态数据
|
|
|
self.prev_flight_data = None
|
|
|
#订阅飞行状态数据更新,并显示到LCDNumber上
|
|
|
self.Tello.subscribe(self.Tello.EVENT_FLIGHT_DATA,self.flight_data_handler)
|
|
|
|
|
|
#订阅拍照后发回来的照片
|
|
|
self.Tello.subscribe(self.Tello.EVENT_FILE_RECEIVED,self.handle_flight_received)
|
|
|
|
|
|
self.TelloCV = TelloCV_ball_people.TelloCV(self.Tello)
|
|
|
|
|
|
|
|
|
def __radioBtn_speechRecogniton_clicked(self):
|
|
|
'''语音识别按钮被按下的反馈函数'''
|
|
|
pass
|
|
|
|
|
|
def keyPressEvent(self, event):
|
|
|
'''键盘监听函数——当按下键时'''
|
|
|
"""
|
|
|
W S A D:前 后 左 右
|
|
|
Tab:起飞
|
|
|
L:降落
|
|
|
P:悬停
|
|
|
H:在手上落下
|
|
|
U I :向上 向下
|
|
|
J K:顺时针旋转 逆时针旋转
|
|
|
Z:前空翻
|
|
|
X:后空翻
|
|
|
C:左空翻
|
|
|
V:右空翻
|
|
|
"""
|
|
|
if self.power == True:
|
|
|
#判断各事件
|
|
|
if event.key() == Qt.Key_Tab:
|
|
|
self.status.showMessage('起飞')
|
|
|
# self.Tello.send('takeoff')
|
|
|
self.Tello.takeoff()
|
|
|
elif event.key() == Qt.Key_P:
|
|
|
self.status.showMessage('悬停')
|
|
|
self.Tello.forward(0)
|
|
|
self.Tello.backward(0)
|
|
|
self.Tello.left(0)
|
|
|
self.Tello.right(0)
|
|
|
elif event.key() == Qt.Key_H:
|
|
|
self.status.showMessage('在手上着落')
|
|
|
self.Tello.palm_land()
|
|
|
elif event.key() == Qt.Key_W:
|
|
|
self.status.showMessage('向前')
|
|
|
self.Tello.forward(int(self.speed))
|
|
|
elif event.key() == Qt.Key_A:
|
|
|
self.status.showMessage('向左')
|
|
|
self.Tello.left(int(self.speed))
|
|
|
elif event.key() == Qt.Key_S:
|
|
|
self.status.showMessage('向后')
|
|
|
self.Tello.backward(int(self.speed))
|
|
|
elif event.key() == Qt.Key_D:
|
|
|
self.status.showMessage('向右')
|
|
|
self.Tello.right(int(self.speed))
|
|
|
elif event.key() == Qt.Key_U:
|
|
|
self.status.showMessage('向上')
|
|
|
self.Tello.up(self.speed)
|
|
|
elif event.key() == Qt.Key_I:
|
|
|
self.status.showMessage('向下')
|
|
|
self.Tello.down(self.speed)
|
|
|
elif event.key() == Qt.Key_J:
|
|
|
self.status.showMessage('顺时针旋转')
|
|
|
self.Tello.clockwise(self.speed)
|
|
|
elif event.key() == Qt.Key_K:
|
|
|
self.status.showMessage('逆时针旋转')
|
|
|
self.Tello.counter_clockwise(self.speed)
|
|
|
|
|
|
def keyReleaseEvent(self, event: QtGui.QKeyEvent):
|
|
|
'''键盘监听函数——当按键释放时'''
|
|
|
if self.power == True:
|
|
|
if event.key() == Qt.Key_W:
|
|
|
self.Tello.forward(0)
|
|
|
self.status.clearMessage()
|
|
|
elif event.key() == Qt.Key_A:
|
|
|
self.Tello.left(0)
|
|
|
self.status.clearMessage()
|
|
|
elif event.key() == Qt.Key_S:
|
|
|
self.Tello.backward(0)
|
|
|
self.status.clearMessage()
|
|
|
elif event.key() == Qt.Key_D:
|
|
|
self.Tello.right(0)
|
|
|
self.status.clearMessage()
|
|
|
elif event.key() == Qt.Key_U:
|
|
|
self.status.clearMessage()
|
|
|
self.Tello.up(0)
|
|
|
elif event.key() == Qt.Key_I:
|
|
|
self.status.clearMessage()
|
|
|
self.Tello.down(0)
|
|
|
elif event.key() == Qt.Key_J:
|
|
|
self.status.clearMessage()
|
|
|
self.Tello.clockwise(0)
|
|
|
elif event.key() == Qt.Key_K:
|
|
|
self.status.clearMessage()
|
|
|
self.Tello.counter_clockwise(0)
|
|
|
elif event.key() == Qt.Key_Z:
|
|
|
self.status.showMessage('前空翻',1000)
|
|
|
self.Tello.flip_forward()
|
|
|
# self.Tello.send('flip f')
|
|
|
elif event.key() == Qt.Key_X:
|
|
|
self.status.showMessage('后空翻',1000)
|
|
|
self.Tello.flip_back()
|
|
|
elif event.key() == Qt.Key_C:
|
|
|
self.status.showMessage('左空翻',1000)
|
|
|
self.Tello.flip_left()
|
|
|
elif event.key() == Qt.Key_V:
|
|
|
self.status.showMessage('右空翻',1000)
|
|
|
self.Tello.flip_right()
|
|
|
elif event.key() == Qt.Key_L:
|
|
|
self.status.showMessage('降落')
|
|
|
self.Tello.land()
|
|
|
elif event.key() == Qt.Key_G:
|
|
|
self.status.showMessage('抛飞模式')
|
|
|
self.Tello.send('throwfly')
|
|
|
|
|
|
|
|
|
def flight_data_handler(self,event, sender, data):
|
|
|
'''处理飞行状态数据的变化'''
|
|
|
text = str(data)
|
|
|
text_list = text.split('|')
|
|
|
state_data = {}
|
|
|
#如果状态数据发生变化了,更新数据
|
|
|
if text != self.prev_flight_data:
|
|
|
for item in text_list:
|
|
|
key = ''
|
|
|
value = ''
|
|
|
flag = False
|
|
|
for x in item:
|
|
|
if x == ' ':
|
|
|
continue
|
|
|
elif x == ':':
|
|
|
flag = True
|
|
|
else:
|
|
|
if not flag:
|
|
|
key = key + x
|
|
|
else:
|
|
|
value = value + x
|
|
|
state_data[key] = value #添加到字典中
|
|
|
self.update_lcdNumbers(state_data)
|
|
|
# print(state_data)
|
|
|
self.prev_flight_data = text
|
|
|
|
|
|
def update_lcdNumbers(self,data:dict):
|
|
|
'''更新LCD,显示飞行状态,包括剩余电量、'''
|
|
|
for key in data:
|
|
|
if key == 'ALT':
|
|
|
self.lcdNumber_Height.display(data[key])
|
|
|
elif key == 'SPD':
|
|
|
self.lcdNumber_speed.display(data[key])
|
|
|
elif key == 'BAT':
|
|
|
#设置一下不同的电量对应不同的LCD颜色
|
|
|
if int(data[key]) < 70 and int(data[key]) >= 30:
|
|
|
self.lcdNumber_battery.setStyleSheet("color:rgb(255, 212, 0);") #黄色,中等电量
|
|
|
elif int(data[key]) >= 70:
|
|
|
self.lcdNumber_battery.setStyleSheet("color:rgb(33, 255, 6);") #绿色,充足电量
|
|
|
else:
|
|
|
self.lcdNumber_battery.setStyleSheet("color:rgb(255, 0, 22);") #红色,电量不足
|
|
|
self.lcdNumber_battery.display(data[key])
|
|
|
elif key == 'WIFI':
|
|
|
self.lcdNumber_WiFi.display((data[key]))
|
|
|
|
|
|
|
|
|
def open_speechRecognition_Window(self):
|
|
|
'''语音控制按钮被按下的反应'''
|
|
|
if self.power == False:
|
|
|
QMessageBox.warning(self, 'warning', "请先按电源键建立连接", buttons=QMessageBox.Ok)
|
|
|
self.radioButton_speech_control.setChecked(False)
|
|
|
self.radioButton_keyBoard_control.setChecked(True)
|
|
|
return
|
|
|
self.speechRecognitionUI.show() #显示子窗口
|
|
|
self.speechRecognitionUI.dockWidget.setFloating(True) #把浮动窗口浮动了
|
|
|
|
|
|
def speechRecognitionUI_closed(self):
|
|
|
'''语音窗口关闭时的反应'''
|
|
|
self.radioButton_speech_control.setChecked(False) #更新按钮状态
|
|
|
self.radioButton_keyBoard_control.setChecked(True)
|
|
|
|
|
|
def speech_control(self,is_tellopy_order,order):
|
|
|
'''语音控制Tello'''
|
|
|
print('Tello收到命令')
|
|
|
if is_tellopy_order == False:
|
|
|
_ = self.Tello.send(order)
|
|
|
else:
|
|
|
if order == 'T':
|
|
|
# self.Tello.send('takeoff')
|
|
|
self.Tello.takeoff()
|
|
|
# self.Tello.send('command')
|
|
|
elif order == 'H':
|
|
|
self.Tello.palm_land()
|
|
|
elif order == 'U':
|
|
|
self.Tello.up(self.speed)
|
|
|
elif order == 'L':
|
|
|
self.Tello.left(self.speed)
|
|
|
elif order == 'R':
|
|
|
# self.Tello.send('land')
|
|
|
self.Tello.land()
|
|
|
elif order == 'S':
|
|
|
self.Tello.backward(self.speed)
|
|
|
elif order == 'D':
|
|
|
self.Tello.right(self.speed)
|
|
|
elif order == 'P':
|
|
|
self.Tello.send('stop')
|
|
|
self.Tello.forward(0)
|
|
|
self.Tello.backward(0)
|
|
|
self.Tello.left(0)
|
|
|
self.Tello.right(0)
|
|
|
self.Tello.up(0)
|
|
|
self.Tello.down(0)
|
|
|
self.Tello.clockwise(0)
|
|
|
self.Tello.counter_clockwise(0)
|
|
|
elif order == 'FF':
|
|
|
self.Tello.flip_forward()
|
|
|
# self.Tello.send('flip f')
|
|
|
elif order == 'FS':
|
|
|
self.Tello.flip_back()
|
|
|
# self.Tello.send('flip b')
|
|
|
elif order == 'FL':
|
|
|
self.Tello.flip_left()
|
|
|
# self.Tello.send('flip l')
|
|
|
elif order == 'FR':
|
|
|
self.Tello.flip_right()
|
|
|
# self.Tello.send('flip r')
|
|
|
|
|
|
def update_LED_state(self,state:str):
|
|
|
'''更新顶部LED的状态'''
|
|
|
if self.RMTT == True:
|
|
|
if state == 'recording':
|
|
|
self.Tello.send('EXT led br 1.5 255 0 255')
|
|
|
elif state == 'executing':
|
|
|
self.Tello.send('EXT led 65 105 225')
|
|
|
else:
|
|
|
return
|
|
|
|
|
|
|
|
|
def open_gestureUI(self):
|
|
|
'''打开手势控制窗口'''
|
|
|
if self.power:
|
|
|
self.gestureUI.show()
|
|
|
self.gestureUI.dockWidget_HintHelp.setFloating(True)
|
|
|
self.sent_move_distance_per_step.emit(self.move_distance_per_step)
|
|
|
else:
|
|
|
QMessageBox.warning(self, 'warning', "请先按电源键建立连接", buttons=QMessageBox.Ok)
|
|
|
|
|
|
def process_gesture_order(self,result : str, order : str):
|
|
|
'''处理手势控制命令'''
|
|
|
#无效命令
|
|
|
if order == 'land':
|
|
|
self.Tello.land()
|
|
|
elif order == 'landhand':
|
|
|
self.Tello.palm_land()
|
|
|
else:
|
|
|
if order in ('cw 90','ccw 90','stop','takeoff','command'):
|
|
|
#这些命令不需要得到步长
|
|
|
self.Tello.send(order)
|
|
|
else:
|
|
|
self.Tello.send(order + ' ' + str(self.move_distance_per_step))
|
|
|
|
|
|
|
|
|
def show_initial_frame(self):
|
|
|
'''显示来自无人机的原始视频图像'''
|
|
|
#只有当电源打开以及"显示无人机图像"标记为真的时候才会显示图像
|
|
|
if self.is_show_initial_frame and self.power:
|
|
|
#显示原始无人机相机画面
|
|
|
self.img_w = self.label_show_video_frame.width()
|
|
|
self.img_h = self.label_show_video_frame.height()
|
|
|
self.Tello_frame = self.Tello.get_video_frame()
|
|
|
|
|
|
#检查是不是还没有跳完帧或者是不是没有解码成功
|
|
|
#假如解码失败
|
|
|
if self.Tello_frame == 'decode error':
|
|
|
self.status.showMessage('解码失败')
|
|
|
return
|
|
|
#解码成功但正在跳帧
|
|
|
else:
|
|
|
if self.Tello_frame == '':
|
|
|
return
|
|
|
else:
|
|
|
if self.start_video_record:
|
|
|
frame_BGR = cv2.cvtColor(self.Tello_frame, cv2.COLOR_RGB2BGR)
|
|
|
self.Video_Writer.write(frame_BGR)
|
|
|
self.Tello_frame = cv2.resize(self.Tello_frame, (self.img_w, self.img_h)) #将图像大小设置为显示窗口的大小
|
|
|
pixmap = QPixmap.fromImage(QImage(self.Tello_frame.data,self.img_w,self.img_h,self.channel*self.img_w,QImage.Format_RGB888))
|
|
|
self.label_show_video_frame.setPixmap(pixmap)
|
|
|
|
|
|
def start_ball_track(self):
|
|
|
'''开始绿球跟踪'''
|
|
|
if self.power:
|
|
|
#关闭显示原始图像
|
|
|
self.is_show_initial_frame = False
|
|
|
self.timer_initial_video_show.stop()
|
|
|
|
|
|
#关闭其他功能
|
|
|
self.timer_face_track.stop()
|
|
|
self.timer_pose_control.stop()
|
|
|
|
|
|
|
|
|
#开始跟踪并显示跟踪图像
|
|
|
self.status.showMessage('已开启绿球跟踪功能')
|
|
|
self.TelloCV.tracking = True
|
|
|
self.timer_ball_track.start(100)
|
|
|
else:
|
|
|
QMessageBox.warning(self, 'warning', "请先按电源键建立连接", buttons=QMessageBox.Ok)
|
|
|
|
|
|
def show_ball_track_img_and_control_tello(self):
|
|
|
'''跟踪绿球并显示跟踪图像'''
|
|
|
self.img_w = self.label_show_video_frame.width()
|
|
|
self.img_h = self.label_show_video_frame.height()
|
|
|
frame = self.Tello.get_video_frame()
|
|
|
if frame == '':
|
|
|
return
|
|
|
else:
|
|
|
image = self.TelloCV.ball_process_frame(frame)
|
|
|
image = cv2.resize(image, (self.img_w, self.img_h)) #将图像大小设置为显示窗口的大小
|
|
|
pixmap = QPixmap.fromImage(QImage(image.data, self.img_w, self.img_h, 3 * self.img_w, QImage.Format_BGR888))
|
|
|
self.label_show_video_frame.setPixmap(pixmap)
|
|
|
|
|
|
def close_ALL_functions(self):
|
|
|
'''关闭跟踪、手势控制、体态控制等功能,并开始显示原始图像'''
|
|
|
#关闭
|
|
|
self.timer_ball_track.stop()
|
|
|
self.timer_face_track.stop()
|
|
|
self.timer_pose_control.stop()
|
|
|
|
|
|
#打开原始图像显示
|
|
|
self.is_show_initial_frame = True
|
|
|
self.timer_initial_video_show.start(100)
|
|
|
|
|
|
self.TelloCV.tracking = False
|
|
|
|
|
|
def start_face_track(self):
|
|
|
'''开始人脸跟踪'''
|
|
|
if self.power:
|
|
|
#关闭显示原始图像
|
|
|
self.is_show_initial_frame = False
|
|
|
self.timer_initial_video_show.stop()
|
|
|
|
|
|
#关闭其他功能
|
|
|
self.timer_ball_track.stop()
|
|
|
self.timer_pose_control.stop()
|
|
|
|
|
|
#开始跟踪并显示跟踪图像
|
|
|
self.TelloCV.tracking = True
|
|
|
self.status.showMessage('已开启人脸跟踪功能')
|
|
|
self.timer_face_track.start(100)
|
|
|
else:
|
|
|
QMessageBox.warning(self, 'warning', "请先按电源键建立连接", buttons=QMessageBox.Ok)
|
|
|
|
|
|
def show_face_track_img_and_control_tello(self):
|
|
|
'''跟踪人脸并显示跟踪图像'''
|
|
|
self.img_w = self.label_show_video_frame.width()
|
|
|
self.img_h = self.label_show_video_frame.height()
|
|
|
frame = self.Tello.get_video_frame()
|
|
|
if frame == '':
|
|
|
return
|
|
|
else:
|
|
|
image = self.TelloCV.face_process_frame(frame)
|
|
|
image = cv2.resize(image, (self.img_w, self.img_h)) # 将图像大小设置为显示窗口的大小
|
|
|
pixmap = QPixmap.fromImage(QImage(image.data, self.img_w, self.img_h, 3 * self.img_w, QImage.Format_BGR888))
|
|
|
self.label_show_video_frame.setPixmap(pixmap)
|
|
|
|
|
|
def handle_flight_received(self, event, sender, data):
|
|
|
"""把拍照得到的照片存下来,存放在Pictures文件夹里"""
|
|
|
path = '../Pictures/tello-%s.jpeg' % (
|
|
|
datetime.datetime.now().strftime(self.date_fmt))
|
|
|
with open(path, 'wb') as out_file:
|
|
|
out_file.write(data)
|
|
|
print('Saved photo to %s' % path)
|
|
|
|
|
|
|
|
|
def take_picture(self):
|
|
|
'''拍照'''
|
|
|
if self.power:
|
|
|
self.Tello.take_picture()
|
|
|
else:
|
|
|
QMessageBox.warning(self, 'warning', "请先按电源键建立连接", buttons=QMessageBox.Ok)
|
|
|
|
|
|
def record_video(self):
|
|
|
'''录像'''
|
|
|
if self.power:
|
|
|
if not self.start_video_record:
|
|
|
fourcc = cv2.VideoWriter_fourcc(*'XVID')
|
|
|
self.Video_Writer = cv2.VideoWriter('Tello-Video-%s.avi'% (datetime.datetime.now().strftime(self.date_fmt)),fourcc, 20.0, (self.Tello.width,self.Tello.height))
|
|
|
self.start_video_record = True
|
|
|
self.pushButton_video_record.setText('录像中')
|
|
|
|
|
|
else:
|
|
|
self.start_video_record = False
|
|
|
self.pushButton_video_record.setText('')
|
|
|
|
|
|
self.Video_Writer.release()
|
|
|
|
|
|
def start_pose_control(self):
|
|
|
'''开始体态控制'''
|
|
|
if self.power:
|
|
|
#关闭显示原始图像
|
|
|
self.is_show_initial_frame = False
|
|
|
self.timer_initial_video_show.stop()
|
|
|
|
|
|
#关闭其他功能
|
|
|
self.timer_ball_track.stop()
|
|
|
self.timer_face_track.stop()
|
|
|
self.TelloCV.tracking = False
|
|
|
|
|
|
#开始体态控制
|
|
|
self.status.showMessage('已开启体态控制功能')
|
|
|
self.timer_pose_control.start(300)
|
|
|
# 加载模型
|
|
|
self.PoseModel = self.AlphaPose_control.downModel()
|
|
|
|
|
|
else:
|
|
|
QMessageBox.warning(self, 'warning', "请先按电源键建立连接", buttons=QMessageBox.Ok)
|
|
|
|
|
|
def show_pose_control_result(self):
|
|
|
'''显示体态控制图像'''
|
|
|
|
|
|
self.img_w = self.label_show_video_frame.width()
|
|
|
self.img_h = self.label_show_video_frame.height()
|
|
|
|
|
|
img_path = '../AlphaPose/duan_alphapose/photo/'
|
|
|
image = self.Tello.get_video_frame()
|
|
|
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
|
|
|
cv2.imwrite(img_path + 'frame.jpg', image) # 保存图片
|
|
|
|
|
|
# 载入图片
|
|
|
img_names = self.AlphaPose_control.GetImage(self.AlphaPose_control.args)
|
|
|
|
|
|
# alphapose处理
|
|
|
point_results = self.AlphaPose_control.Alphapose(img_names, self.PoseModel)
|
|
|
|
|
|
# 分析动作
|
|
|
if point_results is not None:
|
|
|
try:
|
|
|
pose,result_img = self.AlphaPose_control.PoseFind(point_results)
|
|
|
print(pose)
|
|
|
except:
|
|
|
self.AlphaPose_control.del_files(img_path) # 删除文件夹内图片
|
|
|
return
|
|
|
result_img= cv2.resize(result_img, (self.img_w, self.img_h)) # 将图像大小设置为显示窗口的大小
|
|
|
pixmap = QPixmap.fromImage(QImage(result_img.data, self.img_w, self.img_h, 3 * self.img_w, QImage.Format_BGR888))
|
|
|
self.label_show_video_frame.setPixmap(pixmap)
|
|
|
self.AlphaPose_control.del_files(img_path) # 删除文件夹内图片
|
|
|
else:
|
|
|
self.AlphaPose_control.del_files(img_path) # 删除文件夹内图片
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
|
|
|
app = QApplication(sys.argv)
|
|
|
mainWin = mainWindow()
|
|
|
mainWin.show()
|
|
|
sys.exit(app.exec()) |