赞
踩
博主介绍:✌全网粉丝10W+,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久,选择我们就是选择放心、选择安心毕业✌感兴趣的可以先收藏起来,点赞、关注不迷路✌
毕业设计:2023-2024年计算机毕业设计1000套(建议收藏)
毕业设计:2023-2024年最新最全计算机专业毕业设计选题汇总
技术栈:
Python3.8 YOLOv8 深度学习 LPRNet算法 pytorch
(1)上传图片进行车牌识别
(2)上传图片进行车牌识别2
(3)多车牌号码进行车牌识别
(4)上传视频进行车牌识别实时检测
(5)连接摄像头进行车牌识别
(6)连接摄像头进行车牌识别2
(7)车牌识别检测
项目介绍:
基于YOLOv8+LPRNet进行车牌检测及识别,包括对车辆的车牌区域精确定位,利用校正探测器对定位的车牌进行边框校正处理,使用增强神经网络模型对车牌区域进行超分辨率技术处理和光学字符识别。经过多次试验测试,可以对视频中的车辆车牌实时识别以及图片中的车辆车牌进行准确定位和识别,识别速度快,准确率高,比那些传统车牌识别方法效果好很多。
LPRNet由轻量级的卷积神经网络组成,所以它可以采用端到端的方法来进行训练。据我们所知,LPRNet是第一个没有采用RNNs的实时车牌识别系统。因此,LPRNet算法可以为LPR创建嵌入式部署的解决方案,即便是在具有较高挑战性的中文车牌识别上。
from ultralytics.yolo.engine.predictor import BasePredictor from ultralytics.yolo.engine.results import Results from ultralytics.yolo.utils import DEFAULT_CFG, LOGGER, SETTINGS, callbacks, ops from ultralytics.yolo.utils.plotting import Annotator, colors, save_one_box from ultralytics.yolo.utils.torch_utils import smart_inference_mode from ultralytics.yolo.utils.files import increment_path from ultralytics.yolo.utils.checks import check_imshow from ultralytics.yolo.cfg import get_cfg from PySide6.QtWidgets import QApplication, QMainWindow, QFileDialog, QMenu from PySide6.QtGui import QImage, QPixmap, QColor from PySide6.QtCore import QTimer, QThread, Signal, QObject, QPoint, Qt from ui.CustomMessageBox import MessageBox from ui.home import Ui_MainWindow from UIFunctions import * from collections import defaultdict from pathlib import Path from utils.capnums import Camera from utils.rtsp_win import Window import numpy as np import time import json import torch import sys import cv2 import os from yoloPre import YoloPredictor class MainWindow(QMainWindow, Ui_MainWindow): # 这是一个 PySide6 的信号(Signal)对象, # 用于在应用程序中传递消息。在这个场景中,它被用于在主窗口和 YOLO 实例之间传递消息。 main2yolo_begin_sgl = Signal() # The main window sends an execution signal to the yolo instance def __init__(self, parent=None): super(MainWindow, self).__init__(parent) # basic interface 【UI初始化!】 self.setupUi(self) self.setAttribute(Qt.WA_TranslucentBackground) # rounded transparent self.setWindowFlags(Qt.FramelessWindowHint) # Set window flag: hide window borders UIFuncitons.uiDefinitions(self) # Show module shadows UIFuncitons.shadow_style(self, self.Class_QF, QColor(162,129,247)) UIFuncitons.shadow_style(self, self.Target_QF, QColor(251, 157, 139)) UIFuncitons.shadow_style(self, self.Fps_QF, QColor(170, 128, 213)) UIFuncitons.shadow_style(self, self.Model_QF, QColor(64, 186, 193)) # read model folder 加载模型 self.pt_list = os.listdir('./models') self.pt_list = [file for file in self.pt_list if file.endswith('.pt')] self.pt_list.sort(key=lambda x: os.path.getsize('./models/' + x)) # sort by file size self.model_box.clear() self.model_box.addItems(self.pt_list) self.Qtimer_ModelBox = QTimer(self) # Timer: Monitor model file changes every 2 seconds self.Qtimer_ModelBox.timeout.connect(self.ModelBoxRefre) self.Qtimer_ModelBox.start(2000) # Yolo-v8 thread 初始化 self.yolo_predict = YoloPredictor() # Create a Yolo instance self.select_model = self.model_box.currentText() # default model self.yolo_predict.new_model_name = "./models/%s" % self.select_model self.yolo_thread = QThread() # Create yolo thread # 将 Yolo 类中的信号绑定到主线程的槽函数上 self.yolo_predict.yolo2main_pre_img.connect(lambda x: self.show_image(x, self.pre_video)) self.yolo_predict.yolo2main_res_img.connect(lambda x: self.show_image(x, self.res_video)) self.yolo_predict.yolo2main_status_msg.connect(lambda x: self.show_status(x)) self.yolo_predict.yolo2main_fps.connect(lambda x: self.fps_label.setText(x)) # self.yolo_predict.yolo2main_labels.connect(self.show_labels) self.yolo_predict.yolo2main_class_num.connect(lambda x:self.Class_num.setText(str(x))) self.yolo_predict.yolo2main_target_num.connect(lambda x:self.Target_num.setText(str(x))) self.yolo_predict.yolo2main_progress.connect(lambda x: self.progress_bar.setValue(x)) # 将主线程的信号绑定到 Yolo 类的槽函数上,并启动 Yolo 线程 self.main2yolo_begin_sgl.connect(self.yolo_predict.run) self.yolo_predict.moveToThread(self.yolo_thread) # Model parameters self.model_box.currentTextChanged.connect(self.change_model) self.iou_spinbox.valueChanged.connect(lambda x:self.change_val(x, 'iou_spinbox')) # iou box self.iou_slider.valueChanged.connect(lambda x:self.change_val(x, 'iou_slider')) # iou scroll bar self.conf_spinbox.valueChanged.connect(lambda x:self.change_val(x, 'conf_spinbox')) # conf box self.conf_slider.valueChanged.connect(lambda x:self.change_val(x, 'conf_slider')) # conf scroll bar self.speed_spinbox.valueChanged.connect(lambda x:self.change_val(x, 'speed_spinbox'))# speed box self.speed_slider.valueChanged.connect(lambda x:self.change_val(x, 'speed_slider')) # speed scroll bar # Prompt window initialization self.Class_num.setText('--') self.Target_num.setText('--') self.fps_label.setText('--') self.Model_name.setText(self.select_model) # Select detection source self.src_file_button.clicked.connect(self.open_src_file) # select local file self.src_cam_button.clicked.connect(self.chose_cam) #chose_camera # self.src_rtsp_button.clicked.connect(self.show_status("The function has not yet been implemented."))#chose_rtsp # start testing button self.run_button.clicked.connect(self.run_or_continue) # pause/start self.stop_button.clicked.connect(self.stop) # termination # Other function buttons self.save_res_button.toggled.connect(self.is_save_res) # save image option self.save_txt_button.toggled.connect(self.is_save_txt) # Save label option self.ToggleBotton.clicked.connect(lambda: UIFuncitons.toggleMenu(self, True)) # left navigation button self.settings_button.clicked.connect(lambda: UIFuncitons.settingBox(self, True)) # top right settings button # initialization self.load_config() # The main window displays the original image and detection results @staticmethod def show_image(img_src, label): try: ih, iw, _ = img_src.shape # 获取原始图像的高度和宽度 w = label.geometry().width() # 获取 QLabel 组件的当前宽度 h = label.geometry().height() # 获取 QLabel 组件的当前高度 # 根据原始图像和 QLabel 组件的大小,等比例缩放原始图像 if iw / w > ih / h: # 如果原始图像的宽度比高度大,按照宽度比例缩放 scal = w / iw nw = w nh = int(scal * ih) img_src_ = cv2.resize(img_src, (nw, nh)) else: # 如果原始图像的高度比宽度大,按照高度比例缩放 scal = h / ih nw = int(scal * iw) nh = h img_src_ = cv2.resize(img_src, (nw, nh)) # 将 OpenCV 图像转换为 QImage 对象,并将其显示在 QLabel 组件中 frame = cv2.cvtColor(img_src_, cv2.COLOR_BGR2RGB) # 将图像的颜色空间从 BGR 转换为 RGB img = QImage(frame.data, frame.shape[1], frame.shape[0], frame.shape[2] * frame.shape[1], QImage.Format_RGB888) # 创建 QImage 对象 label.setPixmap(QPixmap.fromImage(img)) # 将 QImage 对象转换为 QPixmap 对象,并将其显示在 QLabel 组件中 except Exception as e: print(repr(e)) # Control start/pause def run_or_continue(self): if self.yolo_predict.source == '': print('Please select a video source') self.show_status('Please select a video source before starting detection...') self.run_button.setChecked(False) else: self.yolo_predict.stop_dtc = False print('start') if self.run_button.isChecked(): self.run_button.setChecked(True) # start button self.save_txt_button.setEnabled(False) # It is forbidden to check and save after starting the detection self.save_res_button.setEnabled(False) self.show_status('Detecting...') self.yolo_predict.continue_dtc = True # Control whether Yolo is paused if not self.yolo_thread.isRunning(): self.yolo_thread.start() self.main2yolo_begin_sgl.emit() else: self.yolo_predict.continue_dtc = False self.show_status("Pause...") self.run_button.setChecked(False) # start button # bottom status bar information def show_status(self, msg): self.status_bar.setText(msg) print(msg) if msg == 'Detection completed' or msg == '检测完成': self.save_res_button.setEnabled(True) self.save_txt_button.setEnabled(True) self.run_button.setChecked(False) self.progress_bar.setValue(0) if self.yolo_thread.isRunning(): self.yolo_thread.quit() # end process elif msg == 'Detection terminated!' or msg == '检测终止': self.save_res_button.setEnabled(True) self.save_txt_button.setEnabled(True) self.run_button.setChecked(False) self.progress_bar.setValue(0) if self.yolo_thread.isRunning(): self.yolo_thread.quit() # end process self.pre_video.clear() # clear image display self.res_video.clear() self.Class_num.setText('--') self.Target_num.setText('--') self.fps_label.setText('--') # select local file def open_src_file(self): print('local file') config_file = 'config/fold.json' config = json.load(open(config_file, 'r', encoding='utf-8')) open_fold = config['open_fold'] if not os.path.exists(open_fold): open_fold = os.getcwd() name, _ = QFileDialog.getOpenFileName(self, 'Video/image', open_fold, "Pic File(*.mp4 *.mkv *.avi *.flv *.jpg *.png)") if name: self.yolo_predict.source = name self.show_status('Load File:{}'.format(os.path.basename(name))) config['open_fold'] = os.path.dirname(name) config_json = json.dumps(config, ensure_ascii=False, indent=2) with open(config_file, 'w', encoding='utf-8') as f: f.write(config_json) self.stop() # Select camera source---- have one bug def chose_cam(self): try: print('open camera') # self.stop() # MessageBox( # self.close_button, title='Note', text='loading camera...', time=2000, auto=True).exec() # get the number of local cameras # _, cams = Camera().get_cam_num() # self.viewer = CameraViewer() # 创建新的 CameraViewer 类的对象 # self.viewer.show() # 显示 CameraViewer 类的 GUI 界面 self.yolo_predict.camera_run() except Exception as e: print(e) self.show_status('%s' % e) # select network source def chose_rtsp(self): self.rtsp_window = Window() config_file = 'config/ip.json' if not os.path.exists(config_file): ip = "rtsp://admin:admin888@192.168.1.2:555" new_config = {"ip": ip} new_json = json.dumps(new_config, ensure_ascii=False, indent=2) with open(config_file, 'w', encoding='utf-8') as f: f.write(new_json) else: config = json.load(open(config_file, 'r', encoding='utf-8')) ip = config['ip'] self.rtsp_window.rtspEdit.setText(ip) self.rtsp_window.show() self.rtsp_window.rtspButton.clicked.connect(lambda: self.load_rtsp(self.rtsp_window.rtspEdit.text())) # load network sources def load_rtsp(self, ip): try: self.stop() MessageBox( self.close_button, title='提示', text='加载 rtsp...', time=1000, auto=True).exec() self.yolo_predict.source = ip new_config = {"ip": ip} new_json = json.dumps(new_config, ensure_ascii=False, indent=2) with open('config/ip.json', 'w', encoding='utf-8') as f: f.write(new_json) self.show_status('Loading rtsp:{}'.format(ip)) self.rtsp_window.close() except Exception as e: self.show_status('%s' % e) # Save test result button--picture/video def is_save_res(self): if self.save_res_button.checkState() == Qt.CheckState.Unchecked: self.show_status('NOTE: Run image results are not saved.') self.yolo_predict.save_res = False elif self.save_res_button.checkState() == Qt.CheckState.Checked: self.show_status('NOTE: Run image results will be saved.') self.yolo_predict.save_res = True # Save test result button -- label (txt) def is_save_txt(self): if self.save_txt_button.checkState() == Qt.CheckState.Unchecked: self.show_status('NOTE: Labels results are not saved.') self.yolo_predict.save_txt = False elif self.save_txt_button.checkState() == Qt.CheckState.Checked: self.show_status('NOTE: Labels results will be saved.') self.yolo_predict.save_txt = True # Configuration initialization ~~~wait to change~~~ def load_config(self): config_file = 'config/setting.json' if not os.path.exists(config_file): iou = 0.26 conf = 0.33 rate = 10 save_res = 0 save_txt = 0 new_config = {"iou": iou, "conf": conf, "rate": rate, "save_res": save_res, "save_txt": save_txt } new_json = json.dumps(new_config, ensure_ascii=False, indent=2) with open(config_file, 'w', encoding='utf-8') as f: f.write(new_json) else: config = json.load(open(config_file, 'r', encoding='utf-8')) if len(config) != 5: iou = 0.26 conf = 0.33 rate = 10 save_res = 0 save_txt = 0 else: iou = config['iou'] conf = config['conf'] rate = config['rate'] save_res = config['save_res'] save_txt = config['save_txt'] self.save_res_button.setCheckState(Qt.CheckState(save_res)) self.yolo_predict.save_res = (False if save_res==0 else True ) self.save_txt_button.setCheckState(Qt.CheckState(save_txt)) self.yolo_predict.save_txt = (False if save_txt==0 else True ) self.run_button.setChecked(False) self.show_status("Welcome~") # Terminate button and associated state def stop(self): print('stop') if self.yolo_thread.isRunning(): self.yolo_thread.quit() # end thread self.yolo_predict.stop_dtc = True self.run_button.setChecked(False) # start key recovery self.save_res_button.setEnabled(True) # Ability to use the save button self.save_txt_button.setEnabled(True) # Ability to use the save button self.pre_video.clear() # clear image display self.res_video.clear() # clear image display self.progress_bar.setValue(0) self.Class_num.setText('--') self.Target_num.setText('--') self.fps_label.setText('--') # Change detection parameters def change_val(self, x, flag): if flag == 'iou_spinbox': self.iou_slider.setValue(int(x*100)) # The box value changes, changing the slider elif flag == 'iou_slider': self.iou_spinbox.setValue(x/100) # The slider value changes, changing the box self.show_status('IOU Threshold: %s' % str(x/100)) self.yolo_predict.iou_thres = x/100 elif flag == 'conf_spinbox': self.conf_slider.setValue(int(x*100)) elif flag == 'conf_slider': self.conf_spinbox.setValue(x/100) self.show_status('Conf Threshold: %s' % str(x/100)) self.yolo_predict.conf_thres = x/100 elif flag == 'speed_spinbox': self.speed_slider.setValue(x) elif flag == 'speed_slider': self.speed_spinbox.setValue(x) self.show_status('Delay: %s ms' % str(x)) self.yolo_predict.speed_thres = x # ms # change model 【更换模型】 def change_model(self,x): self.select_model = self.model_box.currentText() self.yolo_predict.new_model_name = "./models/%s" % self.select_model self.show_status('Change Model:%s' % self.select_model) self.Model_name.setText(self.select_model) # label result # def show_labels(self, labels_dic): # try: # self.result_label.clear() # labels_dic = sorted(labels_dic.items(), key=lambda x: x[1], reverse=True) # labels_dic = [i for i in labels_dic if i[1]>0] # result = [' '+str(i[0]) + ':' + str(i[1]) for i in labels_dic] # self.result_label.addItems(result) # except Exception as e: # self.show_status(e) # Cycle monitoring model file changes def ModelBoxRefre(self): pt_list = os.listdir('./models') pt_list = [file for file in pt_list if file.endswith('.pt')] pt_list.sort(key=lambda x: os.path.getsize('./models/' + x)) # It must be sorted before comparing, otherwise the list will be refreshed all the time if pt_list != self.pt_list: self.pt_list = pt_list self.model_box.clear() self.model_box.addItems(self.pt_list) # Get the mouse position (used to hold down the title bar and drag the window) def mousePressEvent(self, event): p = event.globalPosition() globalPos = p.toPoint() self.dragPos = globalPos # Optimize the adjustment when dragging the bottom and right edges of the window size def resizeEvent(self, event): # Update Size Grips UIFuncitons.resize_grips(self) # Exit Exit thread, save settings def closeEvent(self, event): config_file = 'config/setting.json' config = dict() config['iou'] = self.iou_spinbox.value() config['conf'] = self.conf_spinbox.value() config['rate'] = self.speed_spinbox.value() config['save_res'] = (0 if self.save_res_button.checkState()==Qt.Unchecked else 2) config['save_txt'] = (0 if self.save_txt_button.checkState()==Qt.Unchecked else 2) config_json = json.dumps(config, ensure_ascii=False, indent=2) with open(config_file, 'w', encoding='utf-8') as f: f.write(config_json) # Exit the process before closing if self.yolo_thread.isRunning(): self.yolo_predict.stop_dtc = True self.yolo_thread.quit() MessageBox( self.close_button, title='Note', text='Exiting, please wait...', time=3000, auto=True).exec() sys.exit(0) else: sys.exit(0) if __name__ == "__main__": app = QApplication(sys.argv) Home = MainWindow() Home.show() sys.exit(app.exec())
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。