一个识别闯红灯的项目(修改Detect.py文件,搭建Yolov5识别GUI)

 识别效果视频

Yolov5-5.0行人闯红灯检测+简易GUI

 目录结构

本文程序目录结构如图,在Yolov5根目录下创建GUI文件夹用于存储GUI界面相关代码文件。下面左图为源代码根目录,右图为GUI文件目录,在GUI文件夹下只有红色方框框选的文件有用,其他文件是前期摸索的实验性代码。本文将一一列举框选的Py文件。

  1.Yolov5版本选择

本文Github下载Yolov5-5.0版本,下载网址:GitHub - ultralytics/yolov5: YOLOv5 🚀 in PyTorch > ONNX > CoreML > TFLite

相信诸位来学习的道友应该都知道如何使用Github,小的就不赘述了。 

 2.PT模型推理(detect_pt.py)

本文将Detect.py文件当作模块调用,删除了Detect中的计时代码、预测结果保存代码摄像头调用代码:保留了置信度与重合度阈值设定和指定预测类别参数class,所以本文代码目前只能用于预测视频。另外为了不让文件每次调用时都加载一次模型,本文将模型加载部分放在GUI主程序里面,将加载后的模型当作参数进行传递。

import logging
import time
import torch.backends.cudnn as cudnn
import cv2
import numpy as np
from pathlib import Path
from utils.general import check_imshow,check_img_size,non_max_suppression,increment_path\
                        ,scale_coords
from utils.plots import plot_one_box
from utils.datasets import LoadStreams,LoadImages
from utils.torch_utils import select_device,time_synchronized,load_classifier
import torch
from models.experimental import attempt_load,Ensemble
from utils.datasets import letterbox
logger = logging.getLogger(__name__)#日志
def pred_image(model,im0s,save_img,imgsz,conf_thres, iou_thres, classes, agnostic_nms,stride,names,color,half,device):
    t0 = time.time()#计时
    img = letterbox(im0s, imgsz, stride=stride)[0]# 图片调整大小填充
    img = img[:, :, ::-1].transpose(2, 0, 1)  # BGR to RGB, to 3x416x416
    img = np.ascontiguousarray(img)
    img = torch.from_numpy(img).to(device)
    img = img.half() if 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)
    pred = model(img)[0] #输入填充调整后的图片推理
    pred = non_max_suppression(pred, conf_thres, iou_thres, classes=classes, agnostic=agnostic_nms)
    s, img0 = '', im0s
    classes_dict = {'person':"0", '红灯':"0", '绿灯':"0", '闯红灯':"0", '黄灯':"0", 'car':"0", 'bicycle':"0", 'motorcycle':"0"}
'''classes_dict是用来统计预测结果中的类别个数的,这里可以修改为诸位模型的预测类别'''
    for i, det in enumerate(pred):  # 枚举每个图像目标检测结果
        s += '%gx%g ' % img.shape[2:]  # 打印字符串
        if len(det):
            det[:, :4] = scale_coords(img.shape[2:], det[:, :4], img0.shape).round()
            # 统计整理检测结果
            for c in det[:, -1].unique():
                n = (det[:, -1] == c).sum()  # 每个类的检测数
                classes_dict[names[int(c)]] = f"{n}"
            for *xyxy, conf, cls in reversed(det):   #reversed() 函数用于将结果反转,以便按照从高到低的置信度顺序遍历。
                # print(*xyxy)
                if save_img :  # 添加检测框到图片
                    color_class = color[names[int(cls)]]
                    label = f'{names[int(cls)]} {conf:.2f}'
                    img0 = plot_one_box(xyxy, img0, label=label, color=color_class, line_thickness=1)
    return img0,classes_dict
def pt_detection(opencv_imread_image,model,classes,device,names,stride,imgsz,color,half):#GUI预测使用
    conf_thres, iou_thres = 0.25, 0.45
    # classes = [0, 1, 2, 3, 4, 5, 6, 7]
    agnostic_nms = False  # 进行NMS去除不同类别之间的框, 默认False
    project = './Gui_file'  # 保存到文件夹
    name = "run_detect"  # 保存名字
    save_txt = False  # 是否保存预测txt文件,默认False
    exist_ok = True  # 是否重新创建日志文件, False时重新创建文件,默认Ture
    save_conf = False  # 保存置信度到TXT文件
    save_img = True  # 保存bundingbox到图像
    img0,classes_dict=pred_image(model, opencv_imread_image, save_img, imgsz, conf_thres, iou_thres, classes, agnostic_nms, stride, names, color, half,
               device)
    return img0,classes_dict

3.ONNX模型推理(detect_onnx.py)

 本文还进行ONNX模型推理可视化,本部分代码使用了大佬的文章,下面是链接:

详细介绍 Yolov5 转 ONNX模型 + 使用ONNX Runtime 的 Python 部署(包含官方文档的介绍)_yolov5转onnx-CSDN博客目前在做模型部署的工作,使用YOLO开始学起,先学会ONNX以后在学习各种边缘平台的部署。https://blog.csdn.net/qq_22487889/article/details/128011883

import random
import sys
import time

import matplotlib
import onnx
import onnxruntime
import cv2
import numpy as np
import torch
import torchvision
from PIL import Image, ImageDraw, ImageFont
from matplotlib import pyplot as plt

# Settings
matplotlib.rc('font', **{'size': 11})
matplotlib.use('Agg')  # for writing to files only
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

CLASSES = ['person', '红灯', '绿灯', '闯红灯','黄灯','car','bicycle','motorcycle']
'''CLASSES列表用于存储需要进行预测的类别'''

class Yolov5ONNX(object):
    def __init__(self, onnxpath):
        self.onnx_session = onnxruntime.InferenceSession(onnxpath)
        self.input_name = self.get_input_name()
        self.output_name = self.get_output_name()
    def get_input_name(self):
        input_name = []
        for node in self.onnx_session.get_inputs():
            input_name.append(node.name)
        return input_name
    def get_output_name(self):
        output_name = []
        for node in self.onnx_session.get_outputs():
            output_name.append(node.name)
        return output_name
    def get_input_feed(self, img_tensor):
        input_feed = {}
        for name in self.input_name:
            input_feed[name] = img_tensor
        return input_feed
    def inference(self, img,input_image_size):
        if type(img)==str:
            img = cv2.imread(img)
        else:
            img = img
        or_img = cv2.resize(img, input_image_size)
        img = or_img[:, :, ::-1].transpose(2, 0, 1)  # BGR2RGB和HWC2CHW
        img = img.astype(dtype=np.float32)
        img /= 255.0
        img = np.expand_dims(img, axis=0)
        input_feed = self.get_input_feed(img)
        pred = self.onnx_session.run(None, input_feed)[0]
        return pred, or_img
def nms(dets, thresh):
    x1 = dets[:, 0]
    y1 = dets[:, 1]
    x2 = dets[:, 2]
    y2 = dets[:, 3]
    areas = (y2 - y1 + 1) * (x2 - x1 + 1)
    scores = dets[:, 4]
    keep = []
    index = scores.argsort()[::-1]

    while index.size > 0:
        i = index[0]
        keep.append(i)
        x11 = np.maximum(x1[i], x1[index[1:]])
        y11 = np.maximum(y1[i], y1[index[1:]])
        x22 = np.minimum(x2[i], x2[index[1:]])
        y22 = np.minimum(y2[i], y2[index[1:]])
        w = np.maximum(0, x22 - x11 + 1)
        h = np.maximum(0, y22 - y11 + 1)
        overlaps = w * h
        ious = overlaps / (areas[i] + areas[index[1:]] - overlaps)
        idx = np.where(ious <= thresh)[0]
        index = index[idx + 1]
    return keep
def xywh2xyxy(x):
    # [x, y, w, h] to [x1, y1, x2, y2]
    y = np.copy(x)
    y[:, 0] = x[:, 0] - x[:, 2] / 2
    y[:, 1] = x[:, 1] - x[:, 3] / 2
    y[:, 2] = x[:, 0] + x[:, 2] / 2
    y[:, 3] = x[:, 1] + x[:, 3] / 2
    return y
def filter_box(org_box, conf_thres, iou_thres):  # 过滤掉无用的框
    org_box = np.squeeze(org_box)
    conf = org_box[..., 4] > conf_thres
    box = org_box[conf == True]
    cls_cinf = box[..., 5:]  # 左闭右开(5 6 7 8),就只剩下了每个grid cell中各类别的概率
    cls = []
    for i in range(len(cls_cinf)):
        cls.append(int(np.argmax(cls_cinf[i])))  # 剩下的objecctness score比较大的grid cell,分别对应的预测类别列表
    all_cls = list(set(cls))  # 去重,找出图中都有哪些类别
    output = []
    for i in range(len(all_cls)):
        curr_cls = all_cls[i]
        curr_cls_box = []
        curr_out_box = []
        for j in range(len(cls)):
            if cls[j] == curr_cls:
                box[j][5] = curr_cls
                curr_cls_box.append(box[j][:6])
        curr_cls_box = np.array(curr_cls_box)
        # curr_cls_box_old = np.copy(curr_cls_box)
        curr_cls_box = xywh2xyxy(curr_cls_box)
        curr_out_box = nms(curr_cls_box, iou_thres)
        for k in curr_out_box:
            output.append(curr_cls_box[k])
    output = np.array(output)
    return output


def draw(image, box_data):
    boxes = box_data[..., :4].astype(np.int32)  # x1 x2 y1 y2
    scores = box_data[..., 4]#置信度
    classes = box_data[..., 5].astype(np.int32)#classfy
    for box, score, cl in zip(boxes, scores, classes):
        label = CLASSES[int(cl)]
        color = color_bounding_box(label,cl)
        plot_one_box(box,image,color=color,label=label,line_thickness=1)
    return image
def color_bounding_box(names,cls):
   color= {
            'person':[255, 255, 255], '红灯':[0, 0, 255], '绿灯':[0, 255, 0],
           '闯红灯':[0, 0, 255], '黄灯':[0, 255, 255], 'car':[0, 255, 0],
           'bicycle':[0, 255, 0], 'motorcycle':[0, 255, 0]
           }

   return color[names]

def plot_one_box(x, img, color=None, label=None, line_thickness=3):
    tl = line_thickness or round(0.002 * (img.shape[0] + img.shape[1]) / 2) + 1  # line/font thickness
    if color not in [[0,255,0],[0,0,255],[255,255,255],[0,0,255],[0,255,255]]:
        color = color or [random.randint(0, 255) for _ in range(3)]

    c1, c2 = (int(x[0]), int(x[1])), (int(x[2]), int(x[3]))
    cv2.rectangle(img, c1, c2, color, thickness=tl, lineType=cv2.LINE_AA)
    if label:
        tf = max(tl - 1, 1)  # font thickness
        t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]
        font_size = t_size[1]
        font = ImageFont.truetype(r'.\font_ttf\SimHei.ttf', font_size)
        t_size = font.getsize(label)
        c2 = c1[0] + t_size[0], c1[1] - t_size[1]
        cv2.rectangle(img, c1, c2, color, -1, cv2.LINE_AA)  # filled
        img_PIL = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
        draw = ImageDraw.Draw(img_PIL)
        draw.text((c1[0], c2[1] - 2), label, fill=(255, 255, 255), font=font)

        return cv2.cvtColor(np.array(img_PIL), cv2.COLOR_RGB2BGR)

def box_iou(box1, box2):
    # https://github.com/pytorch/vision/blob/master/torchvision/ops/boxes.py
    """
    Return intersection-over-union (Jaccard index) of boxes.
    Both sets of boxes are expected to be in (x1, y1, x2, y2) format.
    Arguments:
        box1 (Tensor[N, 4])
        box2 (Tensor[M, 4])
    Returns:
        iou (Tensor[N, M]): the NxM matrix containing the pairwise
            IoU values for every element in boxes1 and boxes2
    """

    def box_area(box):
        # box = 4xn
        return (box[2] - box[0]) * (box[3] - box[1])

    area1 = box_area(box1.T)
    area2 = box_area(box2.T)

    # inter(N,M) = (rb(N,M,2) - lt(N,M,2)).clamp(0).prod(2)
    inter = (torch.min(box1[:, None, 2:], box2[:, 2:]) - torch.max(box1[:, None, :2], box2[:, :2])).clamp(0).prod(2)
    return inter / (area1[:, None] + area2 - inter)  # iou = inter / (area1 + area2 - inter)
def detect_image(onnx_path,image):
    # onnx_path = 'weights/sim_best20221027.onnx'
    # onnx_path_file = r'D:\yolov5-5.0\runs\train\2023-3-16 epoch 300 15000\weight\best-cpu.onnx'
    model = Yolov5ONNX(onnx_path)

    input_image_size = (640,384)
    # output, or_img = model.inference('data/images/img.png')
    output, or_img = model.inference(image,input_image_size)
    conf_thres, iou_thres = 0.5,0.5
    outbox = filter_box(output, conf_thres, iou_thres )

    if len(outbox) == 0:
        print('没有发现物体')
        sys.exit(0)
    or_img = draw(or_img, outbox)
    or_img=cv2.resize(or_img,(640,360))
    return or_img,outbox

4.使用PYQT5搭建GUI

本文使用QT产品Pyqt5搭建GUI,界面效果如下:

 本课题搭建的GUI界面,功能较为简单,左侧只有Open Video按钮可以使用,右侧Open Model用于加载ONNX模型或者PT模型。

 4.GUI主程序代码(GUI_main.py)

# -*- coding: utf-8 -*-
import cv2
import numpy as np
from utils.torch_utils import select_device
from utils.general import check_img_size
from detect_pt import pt_detection
import torch
import torch.backends.cudnn as cudnn
from models.experimental import attempt_load
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QCoreApplication, QThread, pyqtSignal
from PyQt5.QtGui import QPixmap, QImage, QFont,QMovie
from PyQt5.QtWidgets import QFileDialog,QProgressDialog,QDialog,QLabel,QVBoxLayout
from PyQt5.QtCore import QSettings
from detect_onnx import detect_image
import time
class LoadingDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowModality(Qt.WindowModal)
        self.setFixedSize(200, 100)
        self.label = QLabel(self)
        self.movie = QMovie("loading.gif")
        self.label.setMovie(self.movie)
        self.movie.start()
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.label)
        self.setLayout(self.layout)
    def closeEvent(self, event):
        Ui_MainWindow.closeCat()
        super().closeEvent(event)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1038, 765)
        MainWindow.setStyleSheet("""
                               MainWindow {                                
                                    padding: 10px;
                                    border-radius: 5px;
                                }
                            """)

        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.start_button = QtWidgets.QPushButton(self.centralwidget)
        self.start_button.setObjectName("start_button")
        self.start_button.setDisabled(True)
        self.gridLayout.addWidget(self.start_button, 0, 9, 1, 1)
        self.open_onnx_button = QtWidgets.QPushButton(self.centralwidget)
        self.open_onnx_button.setObjectName("open_onnx_button")
        self.gridLayout.addWidget(self.open_onnx_button, 0, 10, 1, 1)

        self.person_button = QtWidgets.QPushButton(self.centralwidget)
        self.person_button.setObjectName("person_button")
        self.gridLayout.addWidget(self.person_button, 3, 3, 1, 1)
        self.open_camera_button = QtWidgets.QPushButton(self.centralwidget)
        self.open_camera_button.setObjectName("open_camera_button")
        self.gridLayout.addWidget(self.open_camera_button, 0, 3, 1, 1)
        self.Open_Video_button = QtWidgets.QPushButton(self.centralwidget)
        self.Open_Video_button.setObjectName("Open_Video_button")
        self.gridLayout.addWidget(self.Open_Video_button, 0, 2, 1, 1)
        #左右图片投放区域
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.left_video = QtWidgets.QLabel(self.centralwidget)
        self.left_video.setText("")
        # self.size = self.left_video.size()

        self.left_video.setObjectName("left_video")
        self.horizontalLayout.addWidget(self.left_video)
        self.right_video = QtWidgets.QLabel(self.centralwidget)
        self.right_video.setText("")
        self.right_video.setObjectName("right_video")
        # self.right_video.resize(self.size)
        # 设置两个控件的尺寸相同
        self.horizontalLayout.addWidget(self.right_video)
        self.gridLayout.addLayout(self.horizontalLayout, 1, 1, 1, 10)
        # self.horizontalLayout.setStretchFactor(self.left_video, 10)
        # self.horizontalLayout.setStretchFactor(self.right_video, 10)

        #建立按钮
        self.open_image_button = QtWidgets.QPushButton(self.centralwidget)
        self.open_image_button.setObjectName("open_image_button")
        self.gridLayout.addWidget(self.open_image_button, 0, 1, 1, 1)
        self.red_person_button = QtWidgets.QPushButton(self.centralwidget)
        self.red_person_button.setObjectName("red_person_button")
        self.gridLayout.addWidget(self.red_person_button, 3, 1, 1, 1)
        self.Bicycle_button = QtWidgets.QPushButton(self.centralwidget)
        self.Bicycle_button.setObjectName("Bicycle_button")
        self.gridLayout.addWidget(self.Bicycle_button, 3, 7, 1, 1)
        self.truffick_button = QtWidgets.QPushButton(self.centralwidget)
        self.truffick_button.setObjectName("truffick_button")
        self.gridLayout.addWidget(self.truffick_button, 0, 6, 1, 1)

        self.Motorcycle_button = QtWidgets.QPushButton(self.centralwidget)
        self.Motorcycle_button.setObjectName("Motorcycle_button")
        self.gridLayout.addWidget(self.Motorcycle_button, 3, 5, 1, 1)
        self.car_button = QtWidgets.QPushButton(self.centralwidget)
        self.car_button.setObjectName("car_button")
        self.gridLayout.addWidget(self.car_button, 3, 9, 1, 1)
        self.red_green_label = QtWidgets.QLabel(self.centralwidget)
        self.red_green_label.setText("")
        self.red_green_label.setObjectName("red_green_label")
        self.gridLayout.addWidget(self.red_green_label, 0, 7, 1, 1)

        #预测类显示标签
        self.label_Motorcycle = QtWidgets.QLabel(self.centralwidget)
        self.label_Motorcycle.setText("0")
        self.label_Motorcycle.setObjectName("label_Motorcycle")
        self.gridLayout.addWidget(self.label_Motorcycle, 3, 6, 1, 1)
        self.label_Car = QtWidgets.QLabel(self.centralwidget)
        self.label_Car.setText("0")
        self.label_Car.setObjectName("label_Car")
        self.gridLayout.addWidget(self.label_Car, 3, 10, 1, 1)
        self.label_Person = QtWidgets.QLabel(self.centralwidget)
        self.label_Person.setText("0")
        self.label_Person.setObjectName("label_Person")
        self.gridLayout.addWidget(self.label_Person, 3, 4, 1, 1)
        self.label_Bicycle = QtWidgets.QLabel(self.centralwidget)
        self.label_Bicycle.setText("0")
        self.label_Bicycle.setObjectName("label_Bicycle")
        self.gridLayout.addWidget(self.label_Bicycle, 3, 8, 1, 1)
        self.label_red_person = QtWidgets.QLabel(self.centralwidget)
        self.label_red_person.setText("0")
        self.label_red_person.setObjectName("label_red_person")
        self.gridLayout.addWidget(self.label_red_person, 3, 2, 1, 1)
        #应用label显示样式
        self.qlabel(self.label_red_person,self.label_Person,self.label_Bicycle,self.label_Motorcycle,self.label_Car)

        MainWindow.setCentralWidget(self.centralwidget)

        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1038, 26))
        self.menubar.setObjectName("menubar")
        self.menu = QtWidgets.QMenu(self.menubar)
        self.menu.setObjectName("menu")
        self.menuAuto_labels = QtWidgets.QMenu(self.menubar)
        self.menuAuto_labels.setObjectName("menuAuto_labels")
        self.menuLabel_Tools = QtWidgets.QMenu(self.menubar)
        self.menuLabel_Tools.setObjectName("menuLabel_Tools")
        self.menu_4 = QtWidgets.QMenu(self.menubar)
        font = QtGui.QFont()
        font.setFamily("黑体")
        self.menu_4.setFont(font)
        self.menu_4.setObjectName("menu_4")
        self.menu_2 = QtWidgets.QMenu(self.menu_4)
        font = QtGui.QFont()
        font.setFamily("黑体")
        self.menu_2.setFont(font)
        self.menu_2.setObjectName("menu_2")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.actionOpen_Video = QtWidgets.QAction(MainWindow)
        font = QtGui.QFont()
        font.setFamily("黑体")
        self.actionOpen_Video.setFont(font)
        self.actionOpen_Video.setObjectName("actionOpen_Video")
        self.actionQuit = QtWidgets.QAction(MainWindow)
        self.actionQuit.setObjectName("actionQuit")
        self.actionLabel_Image = QtWidgets.QAction(MainWindow)
        self.actionLabel_Image.setObjectName("actionLabel_Image")
        self.actionVoTT = QtWidgets.QAction(MainWindow)
        self.actionVoTT.setObjectName("actionVoTT")
        self.actionLabelme = QtWidgets.QAction(MainWindow)
        self.actionLabelme.setObjectName("actionLabelme")
        self.actionLabel_sprites = QtWidgets.QAction(MainWindow)
        self.actionLabel_sprites.setObjectName("actionLabel_sprites")
        self.actionData_resource = QtWidgets.QAction(MainWindow)
        font = QtGui.QFont()
        font.setFamily("黑体")
        self.actionData_resource.setFont(font)
        self.actionData_resource.setObjectName("actionData_resource")
        self.actionData_Resource = QtWidgets.QAction(MainWindow)
        self.actionData_Resource.setObjectName("actionData_Resource")
        self.actionChange_image_size = QtWidgets.QAction(MainWindow)
        font = QtGui.QFont()
        font.setFamily("黑体")
        self.actionChange_image_size.setFont(font)
        self.actionChange_image_size.setObjectName("actionChange_image_size")
        self.actionAug_image = QtWidgets.QAction(MainWindow)
        font = QtGui.QFont()
        font.setFamily("黑体")
        self.actionAug_image.setFont(font)
        self.actionAug_image.setObjectName("actionAug_image")
        self.actionXML_TXT = QtWidgets.QAction(MainWindow)
        font = QtGui.QFont()
        font.setFamily("黑体")
        self.actionXML_TXT.setFont(font)
        self.actionXML_TXT.setObjectName("actionXML_TXT")
        self.actionTXT_XML = QtWidgets.QAction(MainWindow)
        font = QtGui.QFont()
        font.setFamily("黑体")
        self.actionTXT_XML.setFont(font)
        self.actionTXT_XML.setObjectName("actionTXT_XML")
        self.actionTrain_test_val = QtWidgets.QAction(MainWindow)
        font = QtGui.QFont()
        font.setFamily("黑体")
        self.actionTrain_test_val.setFont(font)
        self.actionTrain_test_val.setObjectName("actionTrain_test_val")
        self.actionchoose_model = QtWidgets.QAction(MainWindow)
        font = QtGui.QFont()
        font.setFamily("黑体")
        self.actionchoose_model.setFont(font)
        self.actionchoose_model.setObjectName("actionchoose_model")
        self.menu.addAction(self.actionOpen_Video)
        self.menu.addSeparator()
        self.menu.addAction(self.actionQuit)
        self.menuAuto_labels.addAction(self.actionchoose_model)
        self.menuLabel_Tools.addAction(self.actionLabel_Image)
        self.menuLabel_Tools.addAction(self.actionLabelme)
        self.menuLabel_Tools.addAction(self.actionVoTT)
        self.menuLabel_Tools.addAction(self.actionLabel_sprites)
        self.menu_2.addAction(self.actionXML_TXT)
        self.menu_2.addAction(self.actionTXT_XML)
        self.menu_4.addAction(self.actionChange_image_size)
        self.menu_4.addAction(self.actionAug_image)
        self.menu_4.addAction(self.menu_2.menuAction())
        self.menu_4.addAction(self.actionTrain_test_val)
        self.menubar.addAction(self.menu.menuAction())
        self.menubar.addAction(self.menuAuto_labels.menuAction())
        self.menubar.addAction(self.menuLabel_Tools.menuAction())
        self.menubar.addAction(self.menu_4.menuAction())


        # self.finished_signal = pyqtSignal()#设置pt模型加载初始化信号
        # self.loading_dialog = LoadingDialog()
        # self.finished_signal.connect(self.loading_dialog.close)
        #创建文件浏览记录
        self.settings = QSettings('MyCompany', 'MyApp')
        self.open_onnx_button_clicked =False
        self.Open_Video_button_clicked =False

        self.retranslateUi(MainWindow)
        self.actionOpen_Video.triggered.connect(self.open_video)
        self.actionQuit.triggered.connect(QCoreApplication.quit)#退出按钮
        # self.truffick_button.clicked.connect(self.show_light)
        self.actionQuit.setShortcut('Ctrl+Q')
        self.Open_Video_button.clicked.connect(self.open_video)
        self.start_button.clicked.connect(self.start_video)
        self.open_image_button.clicked.connect(self.open_image)
        self.open_onnx_button.clicked.connect(self.open_model)
        self.car_button.clicked.connect(self.detection_car)
        self.person_button.clicked.connect(self.detection_person)
        self.Bicycle_button.clicked.connect(self.detection_bicycle)
        self.Motorcycle_button.clicked.connect(self.detection_motorcycle)
        self.red_person_button.clicked.connect(self.detection_runlight)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        # 定时器
        # self.timer = QTimer()
        # self.timer.timeout.connect(self.show_left_image)
        # # 是否暂停
        # self.paused = False
        # classes_dict = {'person': "0", '红灯': "0", '绿灯': "0", '闯红灯': "0", '黄灯': "0", 'car': "0", 'bicycle': "0",
                        # 'motorcycle': "0"}
    def closeCat(self):
        if self.video_cap:
            self.video_cap.release()

    def detection_car(self):
        self.classes = [1,2,4,5]
    def detection_person(self):
        self.classes = [0,1,2,3,4]
    def detection_runlight(self):
        self.classes = [1,2,3,4]
    def detection_bicycle(self):
        self.classes = [1,2,4,6]
    def detection_motorcycle(self):
        self.classes = [1,2,4,7]
    def open_model(self):
        # 获取上一次保存的目录
        # last_dir = self.settings.value('last_dir', '.')
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        # if last_dir:
        #     filename, _ = QFileDialog.getOpenFileName(self.centralwidget, 'Open model', '', 'Model files (*.onnx)',
        #                                             options=options)
        filename, _ = QFileDialog.getOpenFileName(self.centralwidget, 'Open model', '', 'Model files (*.onnx *.pt)',
                                                  options=options)
        if filename:
            self.end_name =filename.split('/')[-1].split('.')[-1]
            self.open_onnx_button_clicked = True
            if self.open_onnx_button_clicked and self.Open_Video_button_clicked:
                self.start_button.setDisabled(False)
            elif self.end_name == "onnx":
                self.model_path = filename
                # self.settings.setValue('last_dir', filename)
            elif self.end_name == "pt":
                self.model_path = filename
                self.agument_pt = self.pt_model_init(self.model_path)#pt模型初始化


    def qlabel(self,*labels):#标签样式
        # # label标签样式设置
        for label in labels:
            label.setStyleSheet("""
                        QLabel {
                            font-size: 40px;
                            color: #00FF00;
                            background-color: black;
                            padding: 10px;
                            border-radius: 5px;
                        }
                    """)
            label.setAlignment(Qt.AlignCenter)#居中
            # font = QFont()
            # font.setPointSize(20)
            # label.setFont(font)  # 字体
        # QtWidgets.QLabel(self.centralwidget).setStyleSheet('background-color : black; color: #00FF00;;')  # 颜色
        # QtWidgets.QLabel(self.centralwidget).setAlignment(Qt.AlignCenter)  # 居中

    def show_light(self,red_green):  # 显示交通灯状态
        if red_green == "红灯":
            image = cv2.imread(r'.\image\red.png')
        else:
            image = cv2.imread(r'.\image\green.png')
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        height, width, channel = image.shape
        bytes_per_line = 3 * width
        q_image = QImage(image.data, width, height, bytes_per_line, QImage.Format_RGB888)
        # 计算缩放比例
        width_ratio = self.red_green_label.width() / q_image.width()
        height_ratio = self.red_green_label.height() / q_image.height()
        ratio = min(width_ratio, height_ratio)
        # 缩放图片
        scaled_image = q_image.scaled(q_image.width() * ratio, q_image.height() * ratio, Qt.KeepAspectRatio)
        # jpg = QtGui.QPixmap(q_image).scaled(self.left_video.width(),
        #                                     self.left_video.height())  # 通过文件路径获取图片文件,并设置图片长宽为label控件的长宽
        self.red_green_label.setPixmap(QPixmap.fromImage(scaled_image))


    def open_image(self):  # 打开图片
        filename, _ = QFileDialog.getOpenFileName(self.centralwidget, 'Open Image', '',
                                                  'Image files (*.jpg *.png *.jpeg)')
        if filename:
            # self.start_button.setDisabled(False)
            frame = cv2.imread(filename)

            self.show_left_image(frame)


    def open_video(self):  # 打开文件
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        # QFileDialog.setDirectory(r"\detect-images")
        filename, _ = QFileDialog.getOpenFileName(self.centralwidget, 'Open Video', '', 'Video files (*.mp4 *.avi)',
                                                  options=options)
        if filename:
            self.Open_Video_button_clicked = True
            if self.open_onnx_button_clicked and self.Open_Video_button_clicked:
                self.start_button.setDisabled(False)
            # self.start_button.setDisabled(False)
            self.video_cap = cv2.VideoCapture(filename)
            ret, frame = self.video_cap.read()
            if ret:
                self.show_left_image(frame)
    def start_video(self):  # 开始按钮,开始预测
        while True:
            ret, frame = self.video_cap.read()
            if ret:

                self.frame = frame         #用于预测
                self.show_left_image(frame)
                if self.end_name == "onnx":
                    self.detect_onnx_model()
                else:
                    self.detect_pt_model()
                    cv2.waitKey(0)
            else:
                break
    def detect_pt_model(self):
        show_image, locate_data = pt_detection(model=self.model,opencv_imread_image=self.frame,classes = self.classes,device=self.device,
                                               names=self.names,stride=self.stride,imgsz=self.imgsz,color=self.color,half=self.half)  # 预测
        self.show_right_image(show_image)
        self.display_num_label(locate_data)  # onnx显示数字
    def detect_onnx_model(self):
        show_image, locate_data = detect_image(self.model_path, self.frame)  # 预测
        self.show_right_image(show_image)
        self.display_num_label(locate_data)  # onnx显示数字

    def show_left_image(self, image):  # 显示原始图片
        # if  self.paused:
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) #BGR->RGB
        height, width, channel = image.shape
        bytes_per_line = 3 * width
        #将array转化成Qlabel能显示的数据格式
        q_image = QImage(image.data, width, height, bytes_per_line, QImage.Format_RGB888)
        # 计算缩放比例
        width_ratio = self.left_video.width() / q_image.width()
        height_ratio = self.left_video.height() / q_image.height()
        self.width_ratio = q_image.width() *min(width_ratio, height_ratio)
        self.height_ratio = q_image.height() * min(width_ratio, height_ratio)
        # 缩放图片
        scaled_image = q_image.scaled(self.width_ratio, self.height_ratio, Qt.KeepAspectRatio)
        # jpg = QtGui.QPixmap(q_image).scaled(self.left_video.width(),
        #                                     self.left_video.height())  # 通过文件路径获取图片文件,并设置图片长宽为label控件的长宽
        self.left_video.setPixmap(QPixmap.fromImage(scaled_image))

        # else:
        #
        #     pass

    def show_right_image(self, show_image):  # 显示预测图片
        # if self.model_path.split("/")[-1].split(".")[-1] == "onnx":
        #转换图片数据格式
        show_image = cv2.cvtColor(show_image, cv2.COLOR_BGR2RGB)  # BGR->RGB
        height, width, channel = show_image.shape
        bytes_per_line = 3 * width
        # 将array转化成Qlabel能显示的数据格式
        show_image = QImage(show_image.data, width, height, bytes_per_line, QImage.Format_RGB888)
        # 缩放图片
        scaled_image = show_image.scaled(self.width_ratio, self.height_ratio, Qt.KeepAspectRatio)

        self.right_video.setPixmap(QPixmap.fromImage(scaled_image))

    def display_num_label(self,label_data):  # LCD显示数字
        # print(label_data)
        if self.end_name == "onnx":
            labels = list(label_data[..., 5].astype(np.int32))
            # print(labels)
            self.label_Car.setText(str(labels.count(5)))
            self.label_Person.setText(str(labels.count(0)))
            self.label_Bicycle.setText(str(labels.count(6)))
            self.label_Motorcycle.setText(str(labels.count(7)))
            self.label_red_person.setText(str(labels.count(3)))
        else:
            # classes_dict = {'person': 0, '红灯': 0, '绿灯': 0, '闯红灯': 0, '黄灯': 0, 'car': 0, 'bicycle': 0, 'motorcycle': 0}
            self.label_Car.setText(label_data["car"])
            self.label_Person.setText(label_data["person"])
            self.label_Bicycle.setText(label_data["bicycle"])
            self.label_Motorcycle.setText(label_data["motorcycle"])
            self.label_red_person.setText(label_data["闯红灯"])
            if label_data["红灯"] != "0":
                self.show_light(red_green="红灯")
            else:
                self.show_light(red_green="绿灯")
        # pass
    def label_image(self, label):
        print(label)
    def pt_model_init(self,path):

        imgsz = 640
        self.classes = [0, 1, 2, 3, 4, 5, 6, 7]
        self.device = select_device("")  # 选择设备GPU,CPU
        weights_path = path
        self.half = self.device.type != 'cpu'  # 仅在 CUDA 上支持半精度
        self.model = attempt_load(weights_path, map_location=self.device)  # load FP32 model
        if self.half:
            self.model.half()  # to FP16
        cudnn.benchmark = True  # 设置 True 以加快恒定图像大小推理
        # 通过claee设置颜色
        self.names = self.model.module.names if hasattr(self.model, 'module') else self.model.names
        # print(names)
        # colors = [[random.randint(0, 255) for _ in range(3)] for _ in names]
        self.color = {'person': [255, 191, 0], '红灯': [0, 0, 255], '绿灯': [0, 255, 0],
                 '闯红灯': [0, 0, 255], '黄灯': [0, 255, 255], 'car': [180, 105, 255],
                 'bicycle': [255, 0, 255], 'motorcycle': [0, 100, 255]
                 }
        self.stride = int(self.model.stride.max())  # model stride模型步幅

        self.imgsz = check_img_size(imgsz, s=self.stride)  # check img_size
        if self.device.type != 'cpu':
            self.model(torch.zeros(1, 3, self.imgsz, self.imgsz).to(self.device).type_as(next(self.model.parameters())))  # run once

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.start_button.setText(_translate("MainWindow", "开始"))
        self.open_onnx_button.setText(_translate("MainWindow", "open model"))
        self.person_button.setText(_translate("MainWindow", "Person"))
        self.open_camera_button.setText(_translate("MainWindow", "Open camera"))
        self.Open_Video_button.setText(_translate("MainWindow", "Open Video"))
        self.open_image_button.setText(_translate("MainWindow", "Open image"))
        self.red_person_button.setText(_translate("MainWindow", "闯红灯"))
        self.Bicycle_button.setText(_translate("MainWindow", "Bicycle"))
        self.truffick_button.setText(_translate("MainWindow", "交通状态"))
        self.Motorcycle_button.setText(_translate("MainWindow", "Motorcycle"))
        self.car_button.setText(_translate("MainWindow", "Car"))
        self.menu.setTitle(_translate("MainWindow", "菜单"))
        self.menuAuto_labels.setTitle(_translate("MainWindow", "半自动标注"))
        self.menuLabel_Tools.setTitle(_translate("MainWindow", "标注工具"))
        self.menu_4.setTitle(_translate("MainWindow", "数据集预处理"))
        self.menu_2.setTitle(_translate("MainWindow", "标注文件转换"))
        self.actionOpen_Video.setText(_translate("MainWindow", "打开文件"))
        self.actionQuit.setText(_translate("MainWindow", "Quit"))
        self.actionLabel_Image.setText(_translate("MainWindow", "Label Image"))
        self.actionVoTT.setText(_translate("MainWindow", "VoTT"))
        self.actionLabelme.setText(_translate("MainWindow", "Labelme"))
        self.actionLabel_sprites.setText(_translate("MainWindow", "Label Sprites"))
        self.actionData_resource.setText(_translate("MainWindow", "打开数据集文件"))
        self.actionData_Resource.setText(_translate("MainWindow", "Data Resource"))
        self.actionChange_image_size.setText(_translate("MainWindow", "图片尺寸归一"))
        self.actionAug_image.setText(_translate("MainWindow", "数据增强"))
        self.actionXML_TXT.setText(_translate("MainWindow", "XML->TXT"))
        self.actionTXT_XML.setText(_translate("MainWindow", "TXT->XML"))
        self.actionTrain_test_val.setText(_translate("MainWindow", "数据集Train Val Test划分"))
        self.actionchoose_model.setText(_translate("MainWindow", "选择已有模型"))

 5.GUI启动程序(main.py)

import sys

import pyqt5_plugins.examplebutton

from GUI_main import Ui_MainWindow
from PyQt5.QtWidgets import *
if __name__ == '__main__':
        app = QApplication(sys.argv)
        MainWindow = QMainWindow()
        ui = Ui_MainWindow()  # 这是类函数的名称
        ui.setupUi(MainWindow)  # 运行类函数里的setupUi
        # ui.show_light()
        MainWindow.show()  # 显示窗口
        sys.exit(app.exec())
  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值