YOLOV5 + PYQT5双目测距(一)

news/2024/7/11 0:47:21 标签: YOLO, qt, 三维测距

YOLOV5 + PYQT5双目测距

  • 1. 测距源码
  • 2. 测距原理
  • 3. PYQT环境配置
  • 4. 实验结果
    • 4.1 界面1(简洁版)
    • 4.2 界面2(改进版)

1. 测距源码

详见文章 YOLOV5 + 双目测距(python)

2. 测距原理

如果想了解双目测距原理,请移步该文章 双目三维测距(python)

3. PYQT环境配置

首先安装一下pyqt5

pip install PyQt5
pip install PyQt5-tools

接着再pycharm设置里配置一下
请添加图片描述
添加下面两个工具:
工具1:Qt Designer

Program D:\Anaconda3\Lib\site-packages\qt5_applications\Qt\bin\designer.exe#代码所用环境路径
Arauments : $FileName$
Working directory :$FileDir$

请添加图片描述
工具2:PyUIC

Program D:\Anaconda3\Scripts\pyuic5.exe 
Arguments : $FileName$ -o $FileNameWithoutExtension$.py
Working directory :$FileDir$

请添加图片描述

4. 实验结果

4.1 界面1(简洁版)

在文件目录下创建一个main.py文件,将以下代码写入

import sys
import os
from PIL import Image
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class filedialogdemo(QWidget):
    def __init__(self, parent=None):
        super(filedialogdemo, self).__init__(parent)
        self.resize(500,500)
        layout = QVBoxLayout()
        self.btn = QPushButton("加载图片")
        self.btn.clicked.connect(self.getfile)
        layout.addWidget(self.btn)


        self.le = QLabel(" csdn:积极向上的mr.d")
        self.btn1 = QPushButton("加载本地摄像头")
        self.btn1.clicked.connect(self.getfiles)
        layout.addWidget(self.btn1)
        layout.addWidget(self.le)

        self.setLayout(layout)
        self.setWindowTitle("双目测距系统")

    def getfile(self):
        '''
        getOpenFileName():返回用户所选择文件的名称,并打开该文件
        第一个参数用于指定父组件
        第二个参数指定对话框标题
        第三个参数指定目录
        第四个参数是文件扩展名过滤器
        '''

        self.fname, _  = QFileDialog.getOpenFileName(self, 'Open file',r'C:\Users\hp\Desktop\sale\yolov5_ceju_pro\data\images',"Image files (*.jpg *.gif *.mp4)")
        self.le.setPixmap(QPixmap(self.fname))
        import shutil
        shutil.rmtree('./runs/detect/exp')
        str=(r'python C:\Users\hp\Desktop\sale\yolov5_ceju_pro\detect_01.py --source ' + self.fname+ ' --exist-ok ')
        os.system(str)  # 运行图片识别文件
        path = os.listdir(r'C:\Users\hp\Desktop\sale\yolov5_ceju_pro\runs\detect\exp')
        s = path[0]
        pathend = r'C:\Users\hp\Desktop\sale\yolov5_ceju_pro\runs\detect\exp'+ '\\'+ s
        I = Image.open(pathend)
        I.show()

    def getfiles(self):   # 加载摄像头
        str=(r'python C:\Users\hp\Desktop\sale\yolov5_ceju_pro\detect_01.py ')   # python命令 + B.py + 参数:IC.txt'
        os.environ['CUDA_LAUNCH_BLOCKING'] = '1' # 不加这个可能会报错
        os.system(str)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = filedialogdemo()
    ex.show()
    sys.exit(app.exec_())

运行main.py即可实现检测
请添加图片描述

4.2 界面2(改进版)

创建一个main1.py文件,将以下代码写入

# Form implementation generated from reading ui file '.\project.ui'
# Created by: PyQt5 UI code generator 5.9.2

import sys
import cv2
import argparse
import random
import torch
import numpy as np
import torch.backends.cudnn as cudnn

from PyQt5 import QtCore, QtGui, QtWidgets
from utils.torch_utils import select_device
from models.experimental import attempt_load
from utils.general import check_img_size, non_max_suppression, scale_coords
from utils.datasets import letterbox
from utils.plots import plot_one_box

from stereo.dianyuntu_yolo import preprocess, undistortion, getRectifyTransform, draw_line, rectifyImage, \
    stereoMatchSGBM
from stereo import stereoconfig
class Ui_MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(Ui_MainWindow, self).__init__(parent)
        self.timer_video = QtCore.QTimer()
        self.setupUi(self)
        self.init_logo()
        self.init_slots()
        self.cap = cv2.VideoCapture()
        self.out = None
        # self.out = cv2.VideoWriter('prediction.avi', cv2.VideoWriter_fourcc(*'XVID'), 20.0, (640, 480))

        parser = argparse.ArgumentParser()
        parser.add_argument('--weights', nargs='+', type=str,
                            default='yolov5s.pt', help='model.pt path(s)')
        # file/folder, 0 for webcam
        parser.add_argument('--source', type=str,
                            default='data/images', help='source')
        parser.add_argument('--img-size', type=int,
                            default=640, help='inference size (pixels)')
        parser.add_argument('--conf-thres', type=float,
                            default=0.25, help='object confidence threshold')
        parser.add_argument('--iou-thres', type=float,
                            default=0.45, help='IOU threshold for NMS')
        parser.add_argument('--device', default='',
                            help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
        parser.add_argument(
            '--view-img', action='store_true', help='display results')
        parser.add_argument('--save-txt', action='store_true',
                            help='save results to *.txt')
        parser.add_argument('--save-conf', action='store_true',
                            help='save confidences in --save-txt labels')
        parser.add_argument('--nosave', action='store_true',
                            help='do not save images/videos')
        parser.add_argument('--classes', nargs='+', type=int,
                            help='filter by class: --class 0, or --class 0 2 3')
        parser.add_argument(
            '--agnostic-nms', action='store_true', help='class-agnostic NMS')
        parser.add_argument('--augment', action='store_true',
                            help='augmented inference')
        parser.add_argument('--update', action='store_true',
                            help='update all models')
        parser.add_argument('--project', default='runs/detect',
                            help='save results to project/name')
        parser.add_argument('--name', default='exp',
                            help='save results to project/name')
        parser.add_argument('--exist-ok', action='store_true',
                            help='existing project/name ok, do not increment')
        self.opt = parser.parse_args()
        print(self.opt)

        source, weights, view_img, save_txt, imgsz = self.opt.source, self.opt.weights, self.opt.view_img, self.opt.save_txt, self.opt.img_size

        self.device = select_device(self.opt.device)
        self.half = self.device.type != 'cpu'  # half precision only supported on CUDA

        cudnn.benchmark = True

        # Load model
        self.model = attempt_load(
            weights, map_location=self.device)  # load FP32 model
        stride = int(self.model.stride.max())  # model stride
        self.imgsz = check_img_size(imgsz, s=stride)  # check img_size
        if self.half:
            self.model.half()  # to FP16

        # Get names and colors
        self.names = self.model.module.names if hasattr(
            self.model, 'module') else self.model.names
        self.colors = [[random.randint(0, 255)
                        for _ in range(3)] for _ in self.names]

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(20, 130, 112, 34))
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(20, 220, 112, 34))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_3.setGeometry(QtCore.QRect(20, 300, 112, 34))
        self.pushButton_3.setObjectName("pushButton_3")
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(160, 90, 611, 411))
        self.groupBox.setObjectName("groupBox")
        self.label = QtWidgets.QLabel(self.groupBox)
        self.label.setGeometry(QtCore.QRect(10, 40, 561, 331))
        self.label.setObjectName("label")
        self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
        self.textEdit.setGeometry(QtCore.QRect(150, 10, 471, 51))
        self.textEdit.setObjectName("textEdit")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 30))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "双目测距系统"))
        self.pushButton.setText(_translate("MainWindow", "图片检测"))
        self.pushButton_2.setText(_translate("MainWindow", "摄像头检测"))
        self.pushButton_3.setText(_translate("MainWindow", "视频检测"))
        self.groupBox.setTitle(_translate("MainWindow", "检测结果"))
        self.label.setText(_translate("MainWindow", "TextLabel"))
        self.textEdit.setHtml(_translate("MainWindow",
                                         "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
                                         "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
                                         "p, li { white-space: pre-wrap; }\n"
                                         "</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
                                         "<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:18pt; font-weight:600;\">双目测距系统</span></p></body></html>"))

    def init_slots(self):
        self.pushButton.clicked.connect(self.button_image_open)
        self.pushButton_3.clicked.connect(self.button_video_open)
        self.pushButton_2.clicked.connect(self.button_camera_open)
        self.timer_video.timeout.connect(self.show_video_frame)

    def init_logo(self):
        pix = QtGui.QPixmap('wechat.jpg')
        self.label.setScaledContents(True)
        self.label.setPixmap(pix)

    def button_image_open(self):
        print('button_image_open')
        name_list = []

        img_name, _ = QtWidgets.QFileDialog.getOpenFileName(
            self, "打开图片", "", "*.jpg;;*.png;;All Files(*)")
        if not img_name:
            return

        img = cv2.imread(img_name)
        print(img_name)
        showimg = img
        with torch.no_grad():
            img = letterbox(img, new_shape=self.opt.img_size)[0]
            # Convert
            # BGR to RGB, to 3x416x416
            img = img[:, :, ::-1].transpose(2, 0, 1)
            img = np.ascontiguousarray(img)
            img = torch.from_numpy(img).to(self.device)
            img = img.half() if self.half else img.float()  # uint8 to fp16/32
            img /= 255.0  # 0 - 255 to 0.0 - 1.0
            if img.ndimension() == 3:
                img = img.unsqueeze(0)
            # Inference
            pred = self.model(img, augment=self.opt.augment)[0]
            # Apply NMS
            pred = non_max_suppression(pred, self.opt.conf_thres, self.opt.iou_thres, classes=self.opt.classes,
                                       agnostic=self.opt.agnostic_nms)
            print(pred)
            # Process detections
            for i, det in enumerate(pred):
                if det is not None and len(det):
                    # Rescale boxes from img_size to im0 size
                    det[:, :4] = scale_coords(
                        img.shape[2:], det[:, :4], showimg.shape).round()

                    for *xyxy, conf, cls in reversed(det):
                        label = '%s %.2f' % (self.names[int(cls)], conf)
                        name_list.append(self.names[int(cls)])
                        plot_one_box(xyxy, showimg, label=label,
                                     color=self.colors[int(cls)], line_thickness=2)

        cv2.imwrite('prediction.jpg', showimg)
        self.result = cv2.cvtColor(showimg, cv2.COLOR_BGR2BGRA)
        self.result = cv2.resize(
            self.result, (640, 480), interpolation=cv2.INTER_AREA)
        self.QtImg = QtGui.QImage(
            self.result.data, self.result.shape[1], self.result.shape[0], QtGui.QImage.Format_RGB32)
        self.label.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))

    def button_video_open(self):
        video_name, _ = QtWidgets.QFileDialog.getOpenFileName(
            self, "打开视频", "", "*.mp4;;*.avi;;All Files(*)")

        if not video_name:
            return

        flag = self.cap.open(video_name)
        if flag == False:
            QtWidgets.QMessageBox.warning(
                self, u"Warning", u"打开视频失败", buttons=QtWidgets.QMessageBox.Ok, defaultButton=QtWidgets.QMessageBox.Ok)
        else:
            self.out = cv2.VideoWriter('prediction.avi', cv2.VideoWriter_fourcc(
                *'MJPG'), 20, (int(self.cap.get(3)), int(self.cap.get(4))))
            self.timer_video.start(30)
            self.pushButton_3.setDisabled(True)
            self.pushButton.setDisabled(True)
            self.pushButton_2.setDisabled(True)

    def button_camera_open(self):
        if not self.timer_video.isActive():
            # 默认使用第一个本地camera
            flag = self.cap.open(0)
            if flag == False:
                QtWidgets.QMessageBox.warning(
                    self, u"Warning", u"打开摄像头失败", buttons=QtWidgets.QMessageBox.Ok,
                    defaultButton=QtWidgets.QMessageBox.Ok)
            else:
                self.out = cv2.VideoWriter('prediction.avi', cv2.VideoWriter_fourcc(
                    *'MJPG'), 20, (int(self.cap.get(3)), int(self.cap.get(4))))
                self.timer_video.start(30)
                self.pushButton_3.setDisabled(True)
                self.pushButton.setDisabled(True)
                self.pushButton_2.setText(u"关闭摄像头")
        else:
            self.timer_video.stop()
            self.cap.release()
            self.out.release()
            self.label.clear()
            self.init_logo()
            self.pushButton_3.setDisabled(False)
            self.pushButton.setDisabled(False)
            self.pushButton_2.setText(u"摄像头检测")

    def show_video_frame(self):
        name_list = []

        flag, img = self.cap.read()
        config = stereoconfig.stereoCamera()
        map1x, map1y, map2x, map2y, Q = getRectifyTransform(720, 1280, config)
        if img is not None:
            showimg = img
            with torch.no_grad():
                img = letterbox(img, new_shape=self.opt.img_size)[0]
                # Convert
                # BGR to RGB, to 3x416x416
                img = img[:, :, ::-1].transpose(2, 0, 1)
                img = np.ascontiguousarray(img)
                img = torch.from_numpy(img).to(self.device)
                img = img.half() if self.half else img.float()  # uint8 to fp16/32
                img /= 255.0  # 0 - 255 to 0.0 - 1.0
                if img.ndimension() == 3:
                    img = img.unsqueeze(0)
                # Inference
                pred = self.model(img, augment=self.opt.augment)[0]

                # Apply NMS
                pred = non_max_suppression(pred, self.opt.conf_thres, self.opt.iou_thres, classes=self.opt.classes,
                                           agnostic=self.opt.agnostic_nms)
                # Process detections
                for i, det in enumerate(pred):  # detections per image
                    if det is not None and len(det):
                        # Rescale boxes from img_size to im0 size
                        det[:, :4] = scale_coords(
                            img.shape[2:], det[:, :4], showimg.shape).round()
                        # Write results
                        for *xyxy, conf, cls in reversed(det):
                            x = (xyxy[0] + xyxy[2]) / 2
                            y = (xyxy[1] + xyxy[3]) / 2
                            if (0 < x <= 1280):

                                height_0, width_0 = showimg.shape[0:2]
                                iml = showimg[0:int(height_0), 0:int(width_0 / 2)]
                                imr = showimg[0:int(height_0), int(width_0 / 2):int(width_0)]

                                height, width = iml.shape[0:2]
                                config = stereoconfig.stereoCamera()
                                map1x, map1y, map2x, map2y, Q = getRectifyTransform(720, 1280, config)
                                iml_rectified, imr_rectified = rectifyImage(iml, imr, map1x, map1y, map2x,
                                                                            map2y)
                                line = draw_line(iml_rectified, imr_rectified)
                                iml = undistortion(iml, config.cam_matrix_left, config.distortion_l)
                                imr = undistortion(imr, config.cam_matrix_right, config.distortion_r)
                                iml_, imr_ = preprocess(iml, imr)
                                iml_rectified_l, imr_rectified_r = rectifyImage(iml_, imr_, map1x, map1y, map2x,map2y)
                                disp, _ = stereoMatchSGBM(iml_rectified_l, imr_rectified_r, True)
                                points_3d = cv2.reprojectImageTo3D(disp, Q)


                                distance = ((points_3d[int(y), int(x), 0] ** 2 + points_3d[int(y), int(x), 1] ** 2 +
                                        points_3d[int(y), int(x), 2] ** 2) ** 0.5) / 10
                                distance = '%.2f' % distance

                                label = '%s %.2f' % (self.names[int(cls)], conf)
                                label = label +  "  " + "dis:" + str(distance) + "m"
                                name_list.append(self.names[int(cls)])
                                print(label)
                                plot_one_box(
                                    xyxy, showimg, label=label, color=self.colors[int(cls)], line_thickness=2)

            self.out.write(showimg)
            show = cv2.resize(showimg, (640, 480))
            self.result = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)
            showImage = QtGui.QImage(self.result.data, self.result.shape[1], self.result.shape[0],
                                     QtGui.QImage.Format_RGB888)
            self.label.setPixmap(QtGui.QPixmap.fromImage(showImage))

        else:
            self.timer_video.stop()
            self.cap.release()
            self.out.release()
            self.label.clear()
            self.pushButton_3.setDisabled(False)
            self.pushButton.setDisabled(False)
            self.pushButton_2.setDisabled(False)
            self.init_logo()


if __name__ == '__main__':
  
    app = QtWidgets.QApplication(sys.argv)
    ui = Ui_MainWindow()
    ui.show()
    sys.exit(app.exec_())

请添加图片描述
对 if name == ‘main’: 改写添加背景图片

if __name__ == '__main__':
    stylesheet = """
                Ui_MainWindow {
                    background-image: url("01.jpg");
                    background-repeat: no-repeat;
                    background-position: center;
                }
            """
    app = QtWidgets.QApplication(sys.argv)
    app.setStyleSheet(stylesheet)
    ui = Ui_MainWindow()
    ui.show()
    sys.exit(app.exec_())

请添加图片描述
视频展示:

工程源码下载:https://github.com/up-up-up-up/yolov5_ceju-pyqt/tree/main

文章内容后续会慢慢完善…


http://www.niftyadmin.cn/n/390704.html

相关文章

华为OD机试真题 Java 实现【求小球落地5次后所经历的路程和第5次反弹的高度】【牛客练习题 HJ38】

一、题目描述 假设一个球从任意高度自由落下,每次落地后反跳回原高度的一半; 再落下, 求它在第5次落地时,共经历多少米?第5次反弹多高? 数据范围:输入的小球初始高度满足 1 \le n \le 1000 \1≤n≤1000 ,且保证是一个整数 二、输入描述 输入起始高度,int型。 三、输…

chatgpt赋能python:Python创建一个Person类

Python 创建一个 Person 类 Python 是一种高级编程语言&#xff0c;因为它易于学习和使用&#xff0c;并且可以用于多种用途。使用 Python&#xff0c;您可以轻松创建各种程序&#xff0c;从简单的脚本到完整的应用程序。Python 的一个重要特点是它的面向对象编程能力&#xf…

M F C(七)对话框

概念 与用户进行交互的窗口&#xff0c;它的顶级父类为CWND&#xff0c;对话框上面可以有各种控件&#xff0c;控件也是继承自CWND 基本控件功能对应的类静态文本框显示文本&#xff0c;一般不能接收输入信息CStatic图像控件显示图标、方框、和图元文件CStatic编辑器编辑正文…

day10 -- table create /update /delete

brief 记录了 表的创建、更改和删除 表的创建 一般有两种创建表的方法&#xff1a; 使用具有交互式创建和管理表的工具&#xff08;如MySQL workbench&#xff09;&#xff1b;表也可以直接用MySQL语句操纵。 为了用程序创建表&#xff0c;可使用SQL的CREATE TABLE语句。 …

Android Studio搭建Xposed项目

添加依赖 settings.gradle 在dependencyResolutionManagement添加 dependencyResolutionManagement {repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)repositories {google()mavenCentral()// **maven { url https://maven.aliyun.com/nexus/content/groups/…

名著《MySQL必知必会》讲了个啥

文章目录 第一章 了解SQL第二章 检索数据第三章 排序第四章 过滤数据第五章 高级数据过滤第六章 多表查询内连接&#xff08;交集&#xff09;外连接多表连接UNIONUNION ALL 第七章 单行函数日期和时间函数获取日期、时间日期与时间戳的转换获取月份、星期、星期数、天数等函数…

Java编程实现函数相加:写一个函数 add,接受两个整数作为参数,返回这两个整数的和;在 main 函数中调用并打印

public class Main { public static void main(String[] args) { int a 1;int b 3;int sum add(a, b);System.out.println(sum); } public static int add(int a ,int b){int sum a b;System.out.println(sum);return sum; } }

双域多尺度融合深度神经网络的PPG生物特征识别研究

目录 前言概述研究背景PPG存在的问题本文的创新点数据处理数据预处理数据分割特征提取 模型结构LSTM网络多尺度特征提取模块双域注意模块识别与验证 实验部分数据集识别指标 前言 本文是根据一篇论文总结写的。 论文英文名为&#xff1a;Dual-domain and Multiscale Fusion D…