YOLO11目標檢測運行推理簡約GUI界面

YOLO11推理簡約GUI界面

使用方法:

支持pt和onnx格式模型,并且自動檢測設備,選擇推理設備

選擇推理圖片所在的文件夾
選擇推理后的結果保存地址

選擇所需要的置信度閾值

點擊開始推理,程序自動運行 并在下方實時顯示推理進度

非常方便不用每次都改代碼來推理了

界面如下所示:

代碼如下:

# -*- coding: utf-8 -*-
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import os, sys, threading, subprocess
from pathlib import Path
import cv2
import torch
from ultralytics import YOLOclass App(tk.Tk):def __init__(self):super().__init__()self.title("YOLOv11 批量推理 (支持 .pt / .onnx)")self.geometry("540x480")self.resizable(False, False)# 設備信息顯示self.device_info = self.get_device_info()tk.Label(self, text=f"檢測到的設備: {self.device_info}", fg="blue").place(x=20, y=5)# ---- 權重文件 ----tk.Label(self, text="權重文件 (.pt / .onnx):").place(x=20, y=40)self.ent_w = tk.Entry(self, width=45)self.ent_w.place(x=180, y=40)tk.Button(self, text="瀏覽", command=lambda: self.browse_file(self.ent_w, [("模型文件", "*.pt *.onnx")])).place(x=460, y=36)# ---- 圖片文件夾 ----tk.Label(self, text="圖片文件夾:").place(x=20, y=80)self.ent_i = tk.Entry(self, width=45)self.ent_i.place(x=180, y=80)tk.Button(self, text="瀏覽", command=lambda: self.browse_directory(self.ent_i)).place(x=460, y=76)# ---- 輸出文件夾 ----tk.Label(self, text="結果保存到:").place(x=20, y=120)self.ent_o = tk.Entry(self, width=45)self.ent_o.place(x=180, y=120)tk.Button(self, text="瀏覽", command=lambda: self.browse_directory(self.ent_o)).place(x=460, y=116)# ---- 置信度 ----tk.Label(self, text="置信度閾值:").place(x=20, y=160)self.scale_conf = tk.Scale(self, from_=0.01, to=1.0, resolution=0.01,orient=tk.HORIZONTAL, length=300)self.scale_conf.set(0.35)self.scale_conf.place(x=180, y=140)# ---- 設備選擇 ----tk.Label(self, text="推理設備:").place(x=20, y=200)self.device_var = tk.StringVar(value="auto")devices = self.get_available_devices()self.device_combo = ttk.Combobox(self, textvariable=self.device_var, values=devices, width=15, state="readonly")self.device_combo.place(x=180, y=200)# ---- 復選框 ----self.var_empty = tk.BooleanVar(value=True)self.var_box = tk.BooleanVar(value=True)self.var_recursive = tk.BooleanVar(value=False)tk.Checkbutton(self, text="保存無目標的圖片", variable=self.var_empty).place(x=20, y=240)tk.Checkbutton(self, text="在結果圖片上畫框", variable=self.var_box).place(x=220, y=240)tk.Checkbutton(self, text="遞歸子文件夾", variable=self.var_recursive).place(x=20, y=270)# ---- 運行按鈕 / 進度條 ----self.btn_run = tk.Button(self, text="開始推理", width=15, command=self.run_thread)self.btn_run.place(x=20, y=310)self.pb = ttk.Progressbar(self, length=480, mode='determinate')self.pb.place(x=20, y=350)# ---- 日志 ----self.txt = tk.Text(self, height=6, width=70, state="disabled")self.txt.place(x=20, y=380)def get_device_info(self):"""獲取設備信息"""if torch.cuda.is_available():gpu_count = torch.cuda.device_count()gpu_name = torch.cuda.get_device_name(0)return f"GPU: {gpu_name} ({gpu_count}個)"else:return "CPU only"def get_available_devices(self):"""獲取可用設備列表"""devices = ["auto"]if torch.cuda.is_available():for i in range(torch.cuda.device_count()):devices.append(f"cuda:{i}")devices.append("cpu")return devicesdef browse_file(self, entry, filetypes):"""瀏覽文件"""f = filedialog.askopenfilename(filetypes=filetypes)if f:entry.delete(0, tk.END)entry.insert(0, f)def browse_directory(self, entry):"""瀏覽目錄"""f = filedialog.askdirectory()if f:entry.delete(0, tk.END)entry.insert(0, f)def log(self, msg):"""日志輸出"""self.txt.configure(state="normal")self.txt.insert(tk.END, msg + "\n")self.txt.see(tk.END)self.txt.configure(state="disabled")self.update()# ---------- 推理 ----------def run_thread(self):"""啟動推理線程"""if not self.validate():returnself.btn_run.config(state="disabled")self.pb["value"] = 0threading.Thread(target=self.infer, daemon=True).start()def validate(self):"""驗證輸入"""for e in (self.ent_w, self.ent_i, self.ent_o):if not e.get():messagebox.showerror("提示", "請完整填寫路徑!")return Falsew_path = Path(self.ent_w.get())if not w_path.exists():messagebox.showerror("錯誤", "權重文件不存在!")return Falseif w_path.suffix.lower() not in ['.pt', '.onnx']:messagebox.showerror("錯誤", "只支持 .pt 或 .onnx 格式的權重文件!")return Falsei_path = Path(self.ent_i.get())if not i_path.exists():messagebox.showerror("錯誤", "圖片文件夾不存在!")return Falsereturn Truedef infer(self):"""執行推理"""try:# 獲取設備設置device_choice = self.device_var.get()if device_choice == "auto":device = "0" if torch.cuda.is_available() else "cpu"else:device = device_choicew_path = self.ent_w.get()ext = Path(w_path).suffix.lower()self.log(f"正在加載模型,使用設備: {device}...")# 關鍵修改:初始化時不傳遞device參數[1,3,4](@ref)model = YOLO(w_path)# 對于PyTorch模型,使用.to()方法遷移到指定設備[6,7](@ref)if ext == '.pt' and device != 'cpu':model.to(device)self.log(f"PyTorch模型已遷移到設備: {device}")elif ext == '.onnx':self.log("注意: ONNX模型當前使用CPU推理,如需GPU加速請使用TensorRT轉換")device = 'cpu'in_dir = Path(self.ent_i.get())out_dir = Path(self.ent_o.get())out_dir.mkdir(parents=True, exist_ok=True)# 收集圖片文件pattern = '?**?/*' if self.var_recursive.get() else '*'img_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.tiff'}imgs = [p for p in in_dir.glob(pattern)if p.suffix.lower() in img_extensions and p.is_file()]total = len(imgs)if total == 0:messagebox.showwarning("警告", "未找到任何圖片!")returnself.pb["maximum"] = totalself.log(f"找到 {total} 張圖片,開始推理...")# 批量推理for idx, img_p in enumerate(imgs, 1):rel_path = img_p.relative_to(in_dir) if in_dir in img_p.parents else Path()save_dir = out_dir / rel_path.parentsave_dir.mkdir(parents=True, exist_ok=True)save_img = save_dir / f"{img_p.stem}_result.jpg"# 執行推理,在predict方法中指定設備[1,3,4](@ref)results = model.predict(source=str(img_p),conf=self.scale_conf.get(),save=False,verbose=False,device=device  # 在這里指定設備)result = results[0]if len(result.boxes) == 0 and not self.var_empty.get():continue# 處理結果圖像img_out = result.plot() if self.var_box.get() else result.orig_imgcv2.imwrite(str(save_img), img_out)# 更新進度self.pb["value"] = idxself.log(f"[{idx:03d}/{total:03d}] {img_p.name}")# 完成后打開結果文件夾subprocess.Popen(f'explorer "{out_dir}"')messagebox.showinfo("完成", f"推理完成!處理了 {total} 張圖片。")except Exception as e:error_msg = f"推理錯誤: {str(e)}"self.log(error_msg)messagebox.showerror("錯誤", error_msg)finally:self.btn_run.config(state="normal")self.pb["value"] = 0if __name__ == "__main__":# 在打包環境下調整路徑if getattr(sys, 'frozen', False):os.chdir(os.path.dirname(sys.executable))app = App()app.mainloop()

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/96817.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/96817.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/96817.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

集值優化問題:理論、應用與前沿進展

本文由「大千AI助手」原創發布,專注用真話講AI,回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我,一起撕掉過度包裝,學習真實的AI技術! 1. 📚 集值優化問題概述 集值優化問題主要研究目標函數為…

提示工程架構師分享:如何用提示詞升級職業教育的實操案例教學?(萬字長文來襲,高能預警!!!)

引言:實操案例教學的“困境”,終于有了破局思路? 晚上10點,汽修專業的王強老師還在電腦前修改《汽車發動機異響故障排查案例》——這已經是他本周第四次調整方案了: 第一次授課時,學生反饋“案例太理想化&a…

「日拱一碼」087 機器學習——SPARROW

目錄 SPARROW 介紹 核心思想:稀疏掩碼訓練 與 Lottery Ticket Hypothesis (LTH) 的關系 代碼示例 代碼關鍵點解釋: 在機器學習領域,"SPARROW" 并不是一個像 Scikit-learn、TensorFlow 或 PyTorch 那樣廣為人知的通用框架或算法…

18、決策樹與集成學習 - 從單一智慧到群體決策

學習目標:理解決策樹的構建原理和分裂標準,掌握信息增益、基尼系數等概念,學會決策樹的剪枝方法,深入理解集成學習的思想,掌握隨機森林和梯度提升的基本原理。 > 從第17章到第18章:從概率模型到規則模型 在第17章中,我們學習了邏輯回歸——一個基于概率的線性分類器…

王道計算機組成原理 學習筆記

第一章計算機系統概述1.1計算機的發展歷程1.2計算機系統層次結構1.2.11.2.2 計算機硬件的基本組成1.2.2 各個硬件的工作原理1.2.3 計算機軟件1.2.4 計算機系統的層次結1.2.5 計算機系統的工作原理1.3計算機的性能指標第二章數據的表示和運算第三章存儲系統第四章指令系統第五章…

Oracle 筆記1 表空間及用戶

Oracle 筆記1 表空間及用戶1 安裝Oracle2 創建表空間3 創建表空間用戶1. 核心管理用戶2. 示例與工具用戶3. 系統與服務用戶4. 創建表空間用戶5. 修改表空間用戶特性OracleMySQL開發商Oracle 公司最初由 MySQL AB 開發,后被 Sun 收購,現屬 Oracle 公司數據…

MyBatis主鍵返回機制解析

關于 MyBatis 主鍵返回的深入解釋 核心問題:信息隔離 數據庫和應用程序是兩個獨立的系統: 數據庫在服務器上執行 INSERT 操作并生成主鍵應用程序在另一個進程或甚至另一臺機器上運行如果沒有明確的機制,應用程序無法自動知道數據庫生成了什么…

【Python】Python內置函數大全解析(附源碼)

目錄專欄導讀前言🚀 功能特性1. 全面的函數覆蓋2. 多種查詢工具3. 完整的測試驗證🛠? 使用方法基本使用交互式查詢運行測試📚 支持的內置函數分類數學運算 (13個)類型轉換 (8個)序列操作 (8個)迭代器 (6個)輸入輸出 (3個)對象操作 (31個)&am…

每日算法題推送

題目1:快樂數 我們先來結合實例看一下判斷快樂數的整個過程: 結合題目可以知道,如果一個數是快樂數,那么這個數最終就會變成1,如果一個數不是快樂數,那么變化序列最終就會陷入循環。想一下,如果…

Oracle體系結構-數據文件(Data Files)

一、 數據文件的本質與原理 物理存儲的基石: 數據文件是 Oracle 數據庫在操作系統層面最核心、最基礎的物理存儲單元。它們是存儲在服務器硬盤(或存儲陣列)上的操作系統文件(如 .dbf, .ora 擴展名常見,但非強制&#x…

【C++練習】18.C++求兩個整數的最小公倍數(LCM)

目錄C求兩個整數的最小公倍數(LCM)的方法方法一:利用最大公約數(GCD)計算代碼實現方法二:逐次增加法代碼實現方法三:質因數分解法代碼實現方法比較處理大數和特殊情況改進版GCD方法實現 C求兩個整數的最小公倍數(LCM)的方法 最小公倍數(LCM)是…

Linux網絡:應用層協議http

前言 雖然我們說,應用層協議是我們程序猿自己定的。但實際上,已經有大佬們定義了一些現成的,又非常好用的應用層協議,供我們直接參考使用.HTTP(超文本傳輸協議)就是其中之一。 我們之前已經學了UDP與TCP套接字的簡單使用,以及講解了進程間的各種關系&a…

ffmpeg推流測試

提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔 文章目錄前言一、操作步驟1.測試12.測試2總結前言 提示:這里可以添加本文要記錄的大概內容: 環境信息: 攝像頭:usb攝像頭 &a…

Docker的使用及核心命令

文章目錄Docker基礎概念鏡像管理命令鏡像查看和搜索鏡像下載和刪除鏡像構建容器生命周期管理創建和啟動容器容器控制命令容器清理容器交互和調試進入容器文件操作日志和監控數據管理數據卷(Volume)綁定掛載網絡管理網絡基礎操作端口映射Dockerfile和Dock…

考研408計算機網絡第36題真題解析(2021-2023)

(2023.36)在使用 CSMA/CD 協議的環境中,使用截斷二進制指數退避算法,來選擇重傳時機,算法 有如下規定: (1)基本的退避時間為爭用期 2τ,假設某網絡具體的爭用期為 51.2us…

Asio C++ Library是用來做什么的

hriskohlhoff/asio 是由 Chris Kohlhoff 主導維護的開源 C 庫,專注于提供高效、跨平臺的異步 I/O 支持,廣泛應用于網絡編程、并發控制和高性能系統開發。 📘 項目概述 項目名稱:Asio C Library 下載地址:https://down…

ac791的按鍵ad_channel

每次ad_channel這個參數都要給我一定的迷惑性,讓我以為這是通道的數量

機器人巡檢與巡邏的區別進行詳細講解和對比

機器人巡檢與巡邏的區別進行詳細講解和對比 盡管這兩個詞經常被混用,但在技術和應用層面上,它們有著本質的區別。核心區別在于:巡檢是“深度體檢”,而巡邏是“治安巡查”。 以下將從多個維度進行詳細講解和對比。 一、核心概念與目…

先進電機拓撲及控制算法介紹(3)——以“數據”驅動電機實現真正的無模型

1. 背景介紹 之前已經介紹過“無模型預測控制(Model-Free Predictive Control/MFPC)”中的“無模型預測電流控制(Model-Free Predictive Current Control/MFPCC)”,可參考下面知乎。 https://zhuanlan.zhihu.com/p/6…

C primer plus (第六版)第十一章 編程練習第5,6題

題目:5.設計并測試?個函數,搜索第1個函數形參指定的字符串,在其中查找第2個函數形參指定的字符?次出現的位置。如果成功,該函數返指向該字符的指針,如果在字符串中未找到指定字符,則返回空指針…