PYqt5编制电脑客户端控制树莓派小车并通过摄像头获取视频显示并保存到电脑本地

PYqt5编制电脑客户端控制树莓派小车并通过摄像头获取视频显示并保存到电脑本地

  • 计算机端
    • 编制控制界面
      • 此为成品图
      • UI部分
      • 逻辑部分
      • 解析
      • 效果图
  • 客户端
      • 讲解

计算机端

编制控制界面

此为成品图

PYqt5编制电脑客户端控制树莓派小车并通过摄像头获取视频显示并保存到电脑本地_第1张图片

UI部分



#  UI部分
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'car_coutoralmain.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWebEngineWidgets import QWebEngineView

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(835, 555)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(320, 390, 169, 31))
        self.label.setObjectName("label")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(320, 350, 169, 28))
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(320, 430, 169, 28))
        self.pushButton_2.setObjectName("pushButton_2")
        self.verticalScrollBar = QtWidgets.QScrollBar(self.centralwidget)
        self.verticalScrollBar.setGeometry(QtCore.QRect(70, 329, 81, 161))
        self.verticalScrollBar.setMaximum(2)
        self.verticalScrollBar.setSingleStep(1)
        self.verticalScrollBar.setPageStep(1)
        self.verticalScrollBar.setProperty("value", 1)
        self.verticalScrollBar.setOrientation(QtCore.Qt.Vertical)
        self.verticalScrollBar.setObjectName("verticalScrollBar")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(160, 340, 81, 41))
        font = QtGui.QFont()
        font.setFamily("AcadEref")
        font.setPointSize(20)
        self.label_2.setFont(font)
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(160, 380, 71, 61))
        font = QtGui.QFont()
        font.setFamily("AcadEref")
        font.setPointSize(20)
        self.label_3.setFont(font)
        self.label_3.setObjectName("label_3")
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(160, 440, 91, 41))
        font = QtGui.QFont()
        font.setFamily("AcadEref")
        font.setPointSize(20)
        self.label_4.setFont(font)
        self.label_4.setObjectName("label_4")
        self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit.setGeometry(QtCore.QRect(570, 40, 221, 31))
        font = QtGui.QFont()
        font.setFamily("Adobe 黑体 Std R")
        font.setPointSize(11)
        self.lineEdit.setFont(font)
        self.lineEdit.setObjectName("lineEdit")
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setGeometry(QtCore.QRect(530, 40, 31, 31))
        font = QtGui.QFont()
        font.setFamily("AcadEref")
        font.setPointSize(14)
        self.label_5.setFont(font)
        self.label_5.setObjectName("label_5")
        self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_3.setGeometry(QtCore.QRect(580, 80, 161, 41))
        font = QtGui.QFont()
        font.setFamily("AcadEref")
        font.setPointSize(14)
        self.pushButton_3.setFont(font)
        self.pushButton_3.setObjectName("pushButton_3")
        self.label_6 = QtWidgets.QLabel(self.centralwidget)
        self.label_6.setGeometry(QtCore.QRect(630, 120, 71, 41))
        font = QtGui.QFont()
        font.setFamily("AcadEref")
        font.setPointSize(14)
        self.label_6.setFont(font)
        self.label_6.setObjectName("label_6")
        self.spinBox = QtWidgets.QSpinBox(self.centralwidget)
        self.spinBox.setGeometry(QtCore.QRect(690, 380, 71, 51))
        font = QtGui.QFont()
        font.setFamily("AcadEref")
        font.setPointSize(14)
        self.spinBox.setFont(font)
        self.spinBox.setMinimum(1)
        self.spinBox.setMaximum(144)
        self.spinBox.setProperty("value", 20)
        self.spinBox.setObjectName("spinBox")
        self.label_7 = QtWidgets.QLabel(self.centralwidget)
        self.label_7.setGeometry(QtCore.QRect(540, 380, 141, 41))
        font = QtGui.QFont()
        font.setFamily("AcadEref")
        font.setPointSize(14)
        self.label_7.setFont(font)
        self.label_7.setObjectName("label_7")
        self.label_8 = QtWidgets.QLabel(self.centralwidget)
        self.label_8.setGeometry(QtCore.QRect(690, 440, 72, 15))
        self.label_8.setObjectName("label_8")
        self.label_9 = QtWidgets.QLabel(self.centralwidget)
        self.label_9.setGeometry(QtCore.QRect(811, 534, 261, 171))
        font = QtGui.QFont()
        font.setFamily("AcadEref")
        font.setPointSize(36)
        self.label_9.setFont(font)
        self.label_9.setObjectName("label_9")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 835, 26))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.qwebengine = QWebEngineView(self.centralwidget)
        self.qwebengine.setGeometry(QtCore.QRect(1, 1, 451, 321))
        self.qwebengine.setAutoFillBackground(False)
        self.qwebengine.setStyleSheet("background-color:rgb(170,170,127);")
        self.qwebengine.setObjectName("qwebengine")
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label.setText(_translate("MainWindow", "录制中...."))
        self.pushButton.setText(_translate("MainWindow", "录制"))
        self.pushButton_2.setText(_translate("MainWindow", "结束"))
        self.label_2.setText(_translate("MainWindow", "前进"))
        self.label_3.setText(_translate("MainWindow", "停止"))
        self.label_4.setText(_translate("MainWindow", "后退"))
        self.lineEdit.setText(_translate("MainWindow", "192.168.1.1"))
        self.label_5.setText(_translate("MainWindow", "IP"))
        self.pushButton_3.setText(_translate("MainWindow", "连接"))
        self.label_6.setText(_translate("MainWindow", "可以啦"))
        self.label_7.setText(_translate("MainWindow", "采集频率设置"))
        self.label_8.setText(_translate("MainWindow", "1-144"))
        self.label_9.setText(_translate("MainWindow", "by西木康"))

逻辑部分





#coding=gbk
'''
from PyQt5.QtWebEngineWidgets import QWebEngineView
        self.qwebengine = QWebEngineView(self.centralwidget)
        self.qwebengine.setGeometry(QtCore.QRect(1, 1, 451, 321))
        self.qwebengine.setAutoFillBackground(False)
        self.qwebengine.setStyleSheet("background-color:rgb(170,170,127);")
        self.qwebengine.setObjectName("qwebengine")
'''
import json
import os
import re
import hashlib
import datetime
import _thread
import time

import cv2
import sys
import socket
from PyQt5.QtCore import QUrl, QFileInfo
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWidgets import QApplication, QMainWindow,QGraphicsOpacityEffect,QWidget
from car_coutoralmain import Ui_MainWindow



IP = '192.168.2.17'
dremm = 'http://{}:8080/?action=stream'.format(IP)
Date_send = {"staus": '1' }
Date_countral = {"vedio": False,"Path":'./vio/',"Patn_s":'202205200853',"times": 1,"ffp_time": 50}
def sent_msg(msg):  # 创建 socket 对象

    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        host = IP
        port = 6666
        s.connect((host, port))

        #print(msg)
        msg = json.dumps(msg)
        s.sendall(msg.encode('utf-8'))
        s.close()

        print("发送成功")

    except:
        print("发送失败")


def vedio():
    print("kaishi")
    cap = cv2.VideoCapture(dremm)
    while(cap.isOpened()):

        ret, frame = cap.read()
        if frame is None:  # 防止后面卡死 或 视频最后为空
            break

        if Date_countral['vedio']:
            if os.path.exists(Date_countral["Path"]):
                pass
            else:
                os.mkdir(Date_countral["Path"])
            if os.path.exists(Date_countral["Path"] +  Date_countral["Patn_s"]):
                pass
            else:
                os.mkdir(Date_countral["Path"] +  Date_countral["Patn_s"])

            pathss = Date_countral["Path"] +  Date_countral["Patn_s"]+ '/{}.jpg'.format(Date_countral["times"])
            cv2.imwrite(pathss, frame)
            Date_countral["times"] += 1
        c = cv2.waitKey(Date_countral["ffp_time"])
        if c == 27:
            break

    cap.release()
    cv2.destroyAllWindows()
class Wepapp(QMainWindow):

    def __init__(self , parent = None):
        super().__init__(parent)
        self.__ui = Ui_MainWindow()
        self.__ui.setupUi(self)
        #load(QUrl(QFileInfo("base.html").absoluteFilePath()))
        #self.__ui.qwebengine.load(QUrl(QFileInfo("base.html").absoluteFilePath()))
        #self.pushButton_3.setGraphicsEffect(op)
        self.__ui.qwebengine.load(QUrl(r"http://192.168.2.17:8080/?action=stream"))
        self.__ui.label.setVisible(False)
        self.__ui.label_6.setVisible(False)
        self.__ui.pushButton_3.clicked.connect(self.reset_self)
        self.__ui.pushButton.clicked.connect(self.luzhi)
        self.__ui.pushButton_2.clicked.connect(self.tingzhi)
        self.__ui.verticalScrollBar.valueChanged.connect(self.movewhile)
        self.__ui.spinBox.valueChanged.connect(self.set_fft)


    def reset_self(self):
        IP = self.__ui.lineEdit.text()
        _thread.start_new_thread(vedio, ())
        self.__ui.label_6.setVisible(True)
    def luzhi(self):
        Date_countral["Patn_s"] = time.strftime("%Y%m%d%H%M%S", time.localtime())
        Date_countral["times"] = 1
        Date_countral["vedio"] = True
        self.__ui.label.setVisible(True)

    def tingzhi(self):
        Date_countral["vedio"] = False
        self.__ui.label.setVisible(False)


    def movewhile(self):
        Date_send["staus"] = self.__ui.verticalScrollBar.value()
        print(Date_send["staus"])
        sent_msg(Date_send)
    def set_fft(self):
        Date_countral["ffp_time"] = int(1000/self.__ui.spinBox.value())



if __name__ == '__main__':
    #_thread.start_new_thread(vedio, ())
    app = QApplication(sys.argv)
    MainWindow = Wepapp()
    MainWindow.show()
    sys.exit(app.exec_())

解析

'''
from PyQt5.QtWebEngineWidgets import QWebEngineView
        self.qwebengine = QWebEngineView(self.centralwidget)
        self.qwebengine.setGeometry(QtCore.QRect(1, 1, 451, 321))
        self.qwebengine.setAutoFillBackground(False)
        self.qwebengine.setStyleSheet("background-color:rgb(170,170,127);")
        self.qwebengine.setObjectName("qwebengine")
'''
想要把视频显示出来,就需要一个窗口,此段代码创建一个用于驱动网页的窗口,通过绑定树莓派摄像头的IP地址可以实时播放。

def sent_msg(msg):  # 创建 socket 对象

    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        host = IP
        port = 6666
        s.connect((host, port))

        #print(msg)
        msg = json.dumps(msg)
        s.sendall(msg.encode('utf-8'))
        s.close()

        print("发送成功")

    except:
        print("发送失败")
通过socket发送用于控制车辆运动的指令。
def vedio():
    print("kaishi")
    cap = cv2.VideoCapture(dremm)
    while(cap.isOpened()):

        ret, frame = cap.read()
        if frame is None:  # 防止后面卡死 或 视频最后为空
            break

        if Date_countral['vedio']:
            if os.path.exists(Date_countral["Path"]):
                pass
            else:
                os.mkdir(Date_countral["Path"])
            if os.path.exists(Date_countral["Path"] +  Date_countral["Patn_s"]):
                pass
            else:
                os.mkdir(Date_countral["Path"] +  Date_countral["Patn_s"])

            pathss = Date_countral["Path"] +  Date_countral["Patn_s"]+ '/{}.jpg'.format(Date_countral["times"])
            cv2.imwrite(pathss, frame)
            Date_countral["times"] += 1
        c = cv2.waitKey(Date_countral["ffp_time"])
        if c == 27:
            break
用于编写将摄像头的图像存于计算机本地,相关动作受UI按键的影响,以实现可控的录制。
    def reset_self(self):
        IP = self.__ui.lineEdit.text()
        _thread.start_new_thread(vedio, ())
        self.__ui.label_6.setVisible(True)
    def luzhi(self):
        Date_countral["Patn_s"] = time.strftime("%Y%m%d%H%M%S", time.localtime())
        Date_countral["times"] = 1
        Date_countral["vedio"] = True
        self.__ui.label.setVisible(True)

    def tingzhi(self):
        Date_countral["vedio"] = False
        self.__ui.label.setVisible(False)


    def movewhile(self):
        Date_send["staus"] = self.__ui.verticalScrollBar.value()
        print(Date_send["staus"])
        sent_msg(Date_send)
    def set_fft(self):
        Date_countral["ffp_time"] = int(1000/self.__ui.spinBox.value())
将按键事件的触发执行相关动作

效果图

PYqt5编制电脑客户端控制树莓派小车并通过摄像头获取视频显示并保存到电脑本地_第2张图片

客户端

import json

import RPi.GPIO as GPIO
import time
import datetime,socket
from multiprocessing import Process,Pool
import threading
from threading import Lock,Thread


IPhost = '192.168.2.17'



#############################






PWMA = 18
AIN1 = 22
AIN2 = 27

PWMB = 23
BIN1 = 25
BIN2 = 24
Date = {"staus": "1" }

def Update():
    global Date

    host = IPhost
    port = 6666
    serversocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
    serversocket.bind((host, port))
    serversocket.listen(5)
    while True:
        try:
            clientsocket, addr = serversocket.accept()
            rec_msg = clientsocket.recv(1024).decode('utf-8')
            Date = json.loads(rec_msg)
        except:
            #Date =  {'car':'stop','camero':'off','arm':'stop'}
            Date['staus'] = '1'




def t_up(speed):
    L_Motor.ChangeDutyCycle(speed)
    GPIO.output(AIN2, False)  # AIN2
    GPIO.output(AIN1, True)  # AIN1

    R_Motor.ChangeDutyCycle(speed)
    GPIO.output(BIN2, False)  # BIN2
    GPIO.output(BIN1, True)  # BIN1
 


def t_stop():
    L_Motor.ChangeDutyCycle(0)
    GPIO.output(AIN2, False)  # AIN2
    GPIO.output(AIN1, False)  # AIN1

    R_Motor.ChangeDutyCycle(0)
    GPIO.output(BIN2, False)  # BIN2
    GPIO.output(BIN1, False)  # BIN1
 


def t_down(speed):
    L_Motor.ChangeDutyCycle(speed)
    GPIO.output(AIN2, True)  # AIN2
    GPIO.output(AIN1, False)  # AIN1

    R_Motor.ChangeDutyCycle(speed)
    GPIO.output(BIN2, True)  # BIN2
    GPIO.output(BIN1, False)  # BIN1
 




GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(AIN2, GPIO.OUT)
GPIO.setup(AIN1, GPIO.OUT)
GPIO.setup(PWMA, GPIO.OUT)

GPIO.setup(BIN1, GPIO.OUT)
GPIO.setup(BIN2, GPIO.OUT)
GPIO.setup(PWMB, GPIO.OUT)

L_Motor = GPIO.PWM(PWMA, 100)
L_Motor.start(0)

R_Motor = GPIO.PWM(PWMB, 100)
R_Motor.start(0)





def Run_car():
    global Date
    print("kaishi")
    while True:

        rec_msg = Date['staus']
        print(rec_msg)
        if rec_msg == 1:
            t_stop()

        elif rec_msg == 2:
            t_down(50)

        elif rec_msg == 0:
            t_up(50)
        else :
            t_stop()
        
        

            
        #clientsocket.close()

if __name__ == "__main__":
    print("project is running")
    t1 = threading.Thread(target=Update)
    t2 = threading.Thread(target=Run_car)
    t1.setDaemon(True)
    t2.setDaemon(True)
    t1.start()
    t2.start()
    print("end")
    

讲解

此段程序较为简单,暂无介绍

你可能感兴趣的:(单片机,计算机视觉,学习笔记,qt,ui,python)