尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于YOLO与PyQt5的蜜蜂目标检测系统开发实战

基于YOLO与PyQt5的蜜蜂目标检测系统开发实战 大家好我是专注于计算机视觉与深度学习应用开发的博主。在农业监测、生态研究或智能蜂箱管理等项目中对蜜蜂进行精准、实时的目标检测是一个常见且具有挑战性的需求。网上关于YOLO模型训练的教程很多但如何将其与一个完整的桌面应用结合并实现检测数据的持久化管理形成一套闭环的解决方案资料往往比较零散。本文将手把手带你实现一个蜜蜂目标检测系统核心内容包括使用YOLOv5/v8等主流模型训练蜜蜂数据集利用PyQt5构建一个功能完善的图形用户界面GUI并通过MySQL数据库对检测结果如数量、位置、时间进行存储、查询与分析。无论你是想学习完整的AI应用开发流程还是需要为特定项目搭建原型这篇文章都能提供从模型训练到软件部署的一站式指南。1. 项目背景与核心概念1.1 为什么需要蜜蜂目标检测系统在现代化农业和生态研究中蜜蜂作为重要的授粉昆虫其种群数量、活动规律是评估生态环境健康与否的关键指标。传统的人工观测方法效率低下、主观性强且难以进行大规模持续监测。因此利用计算机视觉技术对蜜蜂进行自动化目标检测与计数具有重要的应用价值。例如可以应用于智能蜂箱监控实时统计进出蜂箱的蜜蜂数量分析蜂群活跃度。野外生态调查通过部署在野外的摄像头自动统计特定区域内的蜜蜂数量。病虫害预警通过检测蜜蜂行为异常如大量死亡、活动减少辅助判断蜂群健康状况。1.2 技术栈选型与角色本项目是一个典型的“AI模型 桌面应用 数据后端”的综合体涉及多个技术领域YOLO系列模型作为目标检测的核心引擎。YOLOYou Only Look Once以其速度快、精度高著称非常适合实时检测任务。我们将探讨v5、v8、v11等版本的选择与训练。PyQt5用于构建桌面应用程序的Python GUI框架。它功能强大、跨平台能够方便地集成OpenCV进行视频/图像显示并调用训练好的YOLO模型。MySQL关系型数据库。用于结构化存储每次检测的元数据如检测时间、图片路径和结果数据如蜜蜂数量、边界框坐标、置信度便于后续的数据分析与可视化。这三个组件的协作关系是PyQt5 GUI作为用户交互前端接收图像/视频输入调用本地部署的YOLO模型进行推理然后将检测结果和相关信息写入MySQL数据库。2. 环境准备与版本说明在开始编码前我们需要搭建一个统一的开发环境。为了避免版本冲突强烈建议使用虚拟环境如conda或venv。2.1 基础环境配置操作系统Windows 10/11, Ubuntu 20.04/22.04 或 macOS本文以Windows为例Linux/macOS命令略有不同。Python版本3.8 或 3.9与PyTorch、PyQt5兼容性较好。不推荐使用Python 3.10可能遇到某些库的兼容性问题。集成开发环境PyCharm, VSCode 或 Jupyter Notebook用于模型训练部分均可。2.2 关键库安装我们将分模块安装所需的Python包。请打开终端命令行依次执行以下命令。1. 深度学习与计算机视觉基础# 安装PyTorch请根据你的CUDA版本前往PyTorch官网获取对应命令 # 例如对于CUDA 11.8 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 安装OpenCV用于图像处理 pip install opencv-python opencv-python-headless # 安装Ultralytics YOLOv8官方库也支持导出为其他格式 pip install ultralytics # 如果还需要使用YOLOv5可以克隆其官方仓库并安装依赖 # git clone https://github.com/ultralytics/yolov5 # cd yolov5 # pip install -r requirements.txt2. 图形界面开发# 安装PyQt5及其常用工具 pip install PyQt5 PyQt5-tools3. 数据库连接# 安装MySQL Python驱动 pip install mysql-connector-python # 或者使用pymysql # pip install pymysql4. 其他工具库pip install numpy pandas matplotlib seaborn # 数据处理与可视化 pip install pillow # 图像处理2.3 MySQL数据库安装与配置下载与安装从MySQL官网下载MySQL Community Server安装包按照向导完成安装。记住你设置的root用户密码。启动服务在Windows服务中确保MySQL80或类似名称服务处于运行状态。创建数据库使用MySQL命令行客户端或MySQL Workbench图形工具执行以下SQL语句创建本项目专用的数据库。CREATE DATABASE bee_detection_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE bee_detection_db; CREATE TABLE detection_records ( id INT AUTO_INCREMENT PRIMARY KEY, image_path VARCHAR(500) NOT NULL COMMENT 原始图片路径, detection_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 检测时间, bee_count INT NOT NULL COMMENT 检测到的蜜蜂数量, confidence_avg FLOAT COMMENT 平均置信度, bbox_info TEXT COMMENT 所有边界框的坐标信息(JSON格式), note TEXT COMMENT 备注 ) COMMENT 蜜蜂检测记录表;这张表将记录每一次检测的核心信息。bbox_info字段我们计划用JSON格式存储所有检测框的[x1, y1, x2, y2, conf, cls]信息便于后续回查。3. YOLO蜜蜂检测模型训练拥有一个高精度的检测模型是整个系统的基石。这里我们以当前最活跃的YOLOv8为例详细讲解从数据准备到模型训练的全过程。YOLOv5的训练流程也高度相似。3.1 数据集准备与标注数据收集收集包含蜜蜂的图片。可以从公开数据集如Roboflow、Kaggle获取或使用自己拍摄的图片。确保图片在光照、背景、蜜蜂密度上有多样性。数据标注使用标注工具如LabelImg、CVAT、Roboflow Annotate对图片中的每只蜜蜂进行标注标注格式选择YOLO格式.txt文件。每个.txt文件与图片同名每行代表一个目标class_id x_center y_center width height坐标是归一化后的值0-1之间。class_id对于单类检测蜜蜂就是0。数据集划分将标注好的数据按比例如7:2:1划分为train训练集、val验证集和test测试集文件夹。每个文件夹内包含images和labels子文件夹。bee_dataset/ ├── train/ │ ├── images/ (存放.jpg图片) │ └── labels/ (存放.txt标注文件) ├── val/ │ ├── images/ │ └── labels/ └── test/ ├── images/ └── labels/创建数据集配置文件在项目根目录创建一个bee.yaml文件。# bee.yaml path: /path/to/your/bee_dataset # 数据集根目录 train: train/images # 训练集图片路径相对path val: val/images # 验证集图片路径 test: test/images # 测试集图片路径可选 # 类别数目和名称 nc: 1 # number of classes names: [bee] # class names3.2 模型训练YOLOv8提供了极其简洁的API进行训练。创建一个Python脚本train_bee_yolov8.py。# train_bee_yolov8.py from ultralytics import YOLO def main(): # 加载一个预训练模型例如YOLOv8n是nano版本速度快 model YOLO(yolov8n.pt) # 开始训练 results model.train( databee.yaml, # 数据集配置文件路径 epochs100, # 训练轮数 imgsz640, # 输入图像大小 batch16, # 批次大小根据GPU内存调整 namebee_yolov8n, # 实验名称结果会保存在runs/detect/bee_yolov8n device0, # 使用GPU如果是CPU则设为cpu workers4, # 数据加载线程数 patience20, # 早停耐心值 saveTrue, save_period10, pretrainedTrue ) # 训练完成后在验证集上评估模型 metrics model.val() print(fmAP50-95: {metrics.box.map}) # 打印平均精度 if __name__ __main__: main()运行此脚本训练过程、日志和最终模型权重best.pt将保存在runs/detect/bee_yolov8n/目录下。你可以尝试更换模型为yolov8s.pt小模型、yolov8m.pt中模型以获得更好的精度但速度会变慢。3.3 模型导出与测试训练完成后我们需要将模型导出为适合部署的格式如ONNX并编写一个简单的推理脚本进行测试。# export_and_test.py from ultralytics import YOLO import cv2 # 1. 导出模型为ONNX格式便于跨平台部署 model YOLO(runs/detect/bee_yolov8n/weights/best.pt) success model.export(formatonnx, imgsz640, simplifyTrue) print(fExport to ONNX: {success}) # 2. 使用导出的模型或原始模型进行测试 def test_image(image_path): # 加载模型可以是.pt或.onnx model YOLO(runs/detect/bee_yolov8n/weights/best.onnx) # 进行预测 results model(image_path) # 可视化结果 for r in results: im_array r.plot() # 绘制边界框和标签的numpy数组 cv2.imshow(Detection Result, im_array) cv2.waitKey(0) cv2.destroyAllWindows() # 打印检测信息 print(fDetected {len(r.boxes)} bees.) if len(r.boxes) 0: print(fConfidences: {r.boxes.conf}) print(fBox coordinates (xyxy): {r.boxes.xyxy}) if __name__ __main__: test_image(bee_dataset/test/images/bee_test_01.jpg)4. PyQt5图形界面开发现在我们将构建一个用户友好的桌面应用程序集成训练好的YOLO模型并提供图像/视频输入、实时检测、结果展示和数据保存功能。4.1 主窗口设计与布局规划我们将创建一个主窗口包含以下区域菜单栏/工具栏提供打开文件、开始/停止检测、连接数据库等操作。图像显示区域用于显示原始图像和检测结果。控制面板包含模型选择、置信度阈值调节、开始/停止按钮等。信息显示区域显示检测结果数量、耗时和系统状态。底部状态栏显示临时信息。使用Qt Designer可以快速拖拽出界面但为了代码清晰这里我们直接使用代码创建。创建文件bee_detection_gui.py。4.2 核心GUI代码实现# bee_detection_gui.py import sys import os import cv2 import numpy as np from datetime import datetime from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QFileDialog, QComboBox, QSlider, QSpinBox, QTextEdit, QMessageBox, QAction, QStatusBar) from PyQt5.QtCore import Qt, QTimer, pyqtSignal, QThread from PyQt5.QtGui import QImage, QPixmap from ultralytics import YOLO import mysql.connector class DetectionThread(QThread): 用于执行检测任务的线程避免阻塞GUI主线程 finished pyqtSignal(np.ndarray, list, float) # 信号发送处理后的图像、检测结果列表、耗时 def __init__(self, model, frame, conf_threshold): super().__init__() self.model model self.frame frame self.conf_threshold conf_threshold def run(self): import time start_time time.time() # 执行YOLO推理 results self.model(self.frame, confself.conf_threshold, verboseFalse) end_time time.time() inference_time end_time - start_time # 获取第一个结果因为只传了一张图 r results[0] # 绘制检测框 annotated_frame r.plot() # 提取检测信息 [xyxy, conf, cls] detections [] if len(r.boxes) 0: for box in r.boxes: xyxy box.xyxy[0].cpu().numpy().tolist() conf box.conf[0].cpu().numpy().item() cls int(box.cls[0].cpu().numpy().item()) detections.append([xyxy, conf, cls]) self.finished.emit(annotated_frame, detections, inference_time) class BeeDetectionApp(QMainWindow): def __init__(self): super().__init__() self.model None self.current_image_path None self.cap None # 视频捕获对象 self.timer QTimer() # 用于视频流的定时器 self.detection_thread None self.db_connection None self.init_ui() self.init_model() self.init_database() def init_ui(self): self.setWindowTitle(蜜蜂目标检测系统 v1.0) self.setGeometry(100, 100, 1200, 800) # 中心部件 central_widget QWidget() self.setCentralWidget(central_widget) main_layout QHBoxLayout(central_widget) # 左侧图像显示区域 left_panel QVBoxLayout() self.image_label QLabel(图像显示区域) self.image_label.setAlignment(Qt.AlignCenter) self.image_label.setStyleSheet(border: 2px solid gray; background-color: black;) self.image_label.setMinimumSize(640, 480) left_panel.addWidget(self.image_label) # 图像信息 self.info_text QTextEdit() self.info_text.setMaximumHeight(100) self.info_text.setReadOnly(True) left_panel.addWidget(self.info_text) main_layout.addLayout(left_panel, 3) # 左侧占3份宽度 # 右侧控制面板 right_panel QVBoxLayout() # 模型选择 right_panel.addWidget(QLabel(模型选择:)) self.model_combo QComboBox() self.model_combo.addItems([YOLOv8n, YOLOv8s, YOLOv5s, YOLOv5m]) self.model_combo.currentTextChanged.connect(self.on_model_changed) right_panel.addWidget(self.model_combo) # 置信度阈值 right_panel.addWidget(QLabel(置信度阈值:)) self.conf_slider QSlider(Qt.Horizontal) self.conf_slider.setRange(10, 90) # 10% 到 90% self.conf_slider.setValue(25) # 默认25% self.conf_slider.valueChanged.connect(self.on_conf_changed) right_panel.addWidget(self.conf_slider) self.conf_label QLabel(0.25) right_panel.addWidget(self.conf_label) # 控制按钮 self.btn_open_image QPushButton(打开图片) self.btn_open_image.clicked.connect(self.open_image) right_panel.addWidget(self.btn_open_image) self.btn_open_video QPushButton(打开视频) self.btn_open_video.clicked.connect(self.open_video) right_panel.addWidget(self.btn_open_video) self.btn_start_cam QPushButton(开启摄像头) self.btn_start_cam.clicked.connect(self.start_camera) right_panel.addWidget(self.btn_start_cam) self.btn_detect QPushButton(开始检测) self.btn_detect.clicked.connect(self.start_detection) self.btn_detect.setEnabled(False) right_panel.addWidget(self.btn_detect) self.btn_stop QPushButton(停止) self.btn_stop.clicked.connect(self.stop_detection) self.btn_stop.setEnabled(False) right_panel.addWidget(self.btn_stop) self.btn_save_db QPushButton(保存到数据库) self.btn_save_db.clicked.connect(self.save_to_database) self.btn_save_db.setEnabled(False) right_panel.addWidget(self.btn_save_db) right_panel.addStretch() # 添加弹性空间 main_layout.addLayout(right_panel, 1) # 右侧占1份宽度 # 状态栏 self.status_bar QStatusBar() self.setStatusBar(self.status_bar) self.status_bar.showMessage(就绪) # 菜单栏 menubar self.menuBar() file_menu menubar.addMenu(文件) open_action QAction(打开, self) open_action.triggered.connect(self.open_image) file_menu.addAction(open_action) exit_action QAction(退出, self) exit_action.triggered.connect(self.close) file_menu.addAction(exit_action) db_menu menubar.addMenu(数据库) connect_action QAction(连接数据库, self) connect_action.triggered.connect(self.connect_database) db_menu.addAction(connect_action) def init_model(self): 初始化默认模型 try: # 默认加载一个轻量级模型 self.model YOLO(yolov8n.pt) # 或者使用你训练好的 best.pt self.status_bar.showMessage(模型加载成功: YOLOv8n) except Exception as e: QMessageBox.critical(self, 错误, f模型加载失败: {e}) self.model None def init_database(self): 初始化数据库连接 try: self.db_connection mysql.connector.connect( hostlocalhost, userroot, # 替换为你的用户名 passwordyour_password, # 替换为你的密码 databasebee_detection_db ) self.status_bar.showMessage(数据库连接成功) except mysql.connector.Error as err: self.status_bar.showMessage(f数据库连接失败: {err}) self.db_connection None # 后续将补充各个按钮的槽函数如 open_image, start_detection等和图像显示逻辑 # 由于篇幅限制此处先省略下一节将详细展开。 if __name__ __main__: app QApplication(sys.argv) window BeeDetectionApp() window.show() sys.exit(app.exec_())以上代码搭建了应用程序的基本骨架。接下来我们需要实现最核心的功能图像/视频的打开、检测、显示以及数据保存。4.3 核心功能实现在BeeDetectionApp类中继续添加以下方法# 在 BeeDetectionApp 类中继续添加方法 def open_image(self): 打开图片文件 file_path, _ QFileDialog.getOpenFileName( self, 选择图片, , Image Files (*.jpg *.jpeg *.png *.bmp)) if file_path: self.current_image_path file_path # 使用OpenCV读取图片 frame cv2.imread(file_path) if frame is not None: # 转换颜色空间 BGR - RGB frame_rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 调整大小以适应显示区域保持宽高比 h, w, ch frame_rgb.shape target_width self.image_label.width() scale target_width / w new_h, new_w int(h * scale), int(w * scale) frame_resized cv2.resize(frame_rgb, (new_w, new_h)) # 转换为QImage并显示 bytes_per_line ch * new_w q_img QImage(frame_resized.data, new_w, new_h, bytes_per_line, QImage.Format_RGB888) self.image_label.setPixmap(QPixmap.fromImage(q_img)) self.original_frame frame.copy() # 保存原始帧用于检测 self.btn_detect.setEnabled(True) self.btn_save_db.setEnabled(False) self.status_bar.showMessage(f已加载图片: {os.path.basename(file_path)}) else: QMessageBox.warning(self, 警告, 无法读取图片文件。) def open_video(self): 打开视频文件 file_path, _ QFileDialog.getOpenFileName( self, 选择视频, , Video Files (*.mp4 *.avi *.mov)) if file_path: self.stop_detection() # 先停止之前的视频流 self.cap cv2.VideoCapture(file_path) if not self.cap.isOpened(): QMessageBox.warning(self, 警告, 无法打开视频文件。) return self.timer.timeout.connect(self.update_video_frame) self.timer.start(30) # 约33 FPS self.btn_detect.setEnabled(True) self.btn_stop.setEnabled(True) self.btn_start_cam.setEnabled(False) self.btn_open_video.setEnabled(False) self.status_bar.showMessage(f正在播放视频: {os.path.basename(file_path)}) def start_camera(self): 开启摄像头 self.stop_detection() self.cap cv2.VideoCapture(0) # 0 表示默认摄像头 if not self.cap.isOpened(): QMessageBox.warning(self, 警告, 无法打开摄像头。) return self.timer.timeout.connect(self.update_video_frame) self.timer.start(30) self.btn_detect.setEnabled(True) self.btn_stop.setEnabled(True) self.btn_start_cam.setEnabled(False) self.btn_open_video.setEnabled(False) self.status_bar.showMessage(摄像头已开启) def update_video_frame(self): 定时器槽函数从视频/摄像头读取并显示帧 if self.cap is None: return ret, frame self.cap.read() if ret: self.original_frame frame.copy() # 显示原始帧不检测 frame_rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch frame_rgb.shape target_width self.image_label.width() scale target_width / w new_h, new_w int(h * scale), int(w * scale) frame_resized cv2.resize(frame_rgb, (new_w, new_h)) bytes_per_line ch * new_w q_img QImage(frame_resized.data, new_w, new_h, bytes_per_line, QImage.Format_RGB888) self.image_label.setPixmap(QPixmap.fromImage(q_img)) else: self.timer.stop() if self.cap: self.cap.release() self.cap None self.status_bar.showMessage(视频播放完毕或摄像头断开) def start_detection(self): 开始检测单张图片或视频流中的当前帧 if not hasattr(self, original_frame) or self.original_frame is None: QMessageBox.information(self, 提示, 请先打开图片或视频。) return if self.model is None: QMessageBox.warning(self, 警告, 模型未加载。) return # 获取当前置信度阈值 conf_threshold self.conf_slider.value() / 100.0 # 在独立线程中执行检测防止界面卡顿 self.detection_thread DetectionThread(self.model, self.original_frame, conf_threshold) self.detection_thread.finished.connect(self.on_detection_finished) self.detection_thread.start() self.btn_detect.setEnabled(False) self.status_bar.showMessage(检测中...) def on_detection_finished(self, annotated_frame, detections, inference_time): 检测线程完成后的回调 # 显示带检测框的图像 annotated_frame_rgb cv2.cvtColor(annotated_frame, cv2.COLOR_BGR2RGB) h, w, ch annotated_frame_rgb.shape target_width self.image_label.width() scale target_width / w new_h, new_w int(h * scale), int(w * scale) frame_resized cv2.resize(annotated_frame_rgb, (new_w, new_h)) bytes_per_line ch * new_w q_img QImage(frame_resized.data, new_w, new_h, bytes_per_line, QImage.Format_RGB888) self.image_label.setPixmap(QPixmap.fromImage(q_img)) # 更新信息面板 bee_count len(detections) info f检测完成 蜜蜂数量: {bee_count} 推理耗时: {inference_time:.3f} 秒 平均置信度: {np.mean([d[1] for d in detections]):.3f if detections else 0} self.info_text.setText(info) self.current_detections detections # 保存检测结果用于保存到数据库 self.btn_detect.setEnabled(True) self.btn_save_db.setEnabled(True) self.status_bar.showMessage(f检测完成发现 {bee_count} 只蜜蜂) def stop_detection(self): 停止视频流或摄像头 if self.timer.isActive(): self.timer.stop() if self.cap: self.cap.release() self.cap None self.btn_start_cam.setEnabled(True) self.btn_open_video.setEnabled(True) self.btn_stop.setEnabled(False) self.status_bar.showMessage(已停止) def save_to_database(self): 将当前检测结果保存到MySQL数据库 if not hasattr(self, current_detections): QMessageBox.warning(self, 警告, 没有可保存的检测结果。) return if self.db_connection is None: QMessageBox.warning(self, 警告, 数据库未连接。) return try: cursor self.db_connection.cursor() # 准备数据 image_path self.current_image_path if hasattr(self, current_image_path) else Camera/Video Frame bee_count len(self.current_detections) conf_avg np.mean([d[1] for d in self.current_detections]) if self.current_detections else 0 # 将边界框信息转换为JSON字符串存储 import json bbox_list [] for bbox, conf, cls in self.current_detections: bbox_list.append({ x1: float(bbox[0]), y1: float(bbox[1]), x2: float(bbox[2]), y2: float(bbox[3]), confidence: float(conf), class: cls }) bbox_json json.dumps(bbox_list) sql INSERT INTO detection_records (image_path, bee_count, confidence_avg, bbox_info) VALUES (%s, %s, %s, %s) val (image_path, bee_count, conf_avg, bbox_json) cursor.execute(sql, val) self.db_connection.commit() cursor.close() QMessageBox.information(self, 成功, f检测记录已保存到数据库ID: {cursor.lastrowid}) self.status_bar.showMessage(数据保存成功) except Exception as e: QMessageBox.critical(self, 数据库错误, f保存失败: {e}) def on_model_changed(self, text): 切换模型 model_map { YOLOv8n: yolov8n.pt, YOLOv8s: yolov8s.pt, YOLOv5s: yolov5s.pt, # 需要提前下载好权重文件 YOLOv5m: yolov5m.pt } model_file model_map.get(text) if model_file and os.path.exists(model_file): try: self.model YOLO(model_file) self.status_bar.showMessage(f模型已切换为: {text}) except Exception as e: QMessageBox.warning(self, 警告, f模型加载失败: {e}) def on_conf_changed(self, value): 更新置信度阈值显示 self.conf_label.setText(f{value/100:.2f}) def connect_database(self): 手动连接数据库 self.init_database() def closeEvent(self, event): 关闭窗口时释放资源 self.stop_detection() if self.db_connection and self.db_connection.is_connected(): self.db_connection.close() event.accept()至此一个功能完整的蜜蜂目标检测GUI应用程序就完成了。它支持图片、视频和摄像头输入能够实时显示检测结果并将结构化数据保存到MySQL数据库。5. 系统集成与运行测试5.1 项目文件结构在运行前请确保你的项目目录结构如下bee_detection_project/ ├── bee_detection_gui.py # PyQt5主程序 ├── train_bee_yolov8.py # 模型训练脚本 ├── bee.yaml # 数据集配置文件 ├── yolov8n.pt # 预训练模型权重或你的best.pt ├── bee_dataset/ # 你的蜜蜂数据集 │ ├── train/ │ ├── val/ │ └── test/ └── requirements.txt # 项目依赖可选5.2 运行应用程序确保MySQL服务已启动并且bee_detection_db数据库和detection_records表已创建。在bee_detection_gui.py中修改init_database方法里的数据库连接参数主机、用户名、密码。在终端中运行python bee_detection_gui.py程序启动后你可以点击“打开图片”选择一张蜜蜂图片。点击“开始检测”程序会调用YOLO模型进行推理并在界面显示带框的结果和数量。点击“保存到数据库”将本次检测的记录写入MySQL。尝试“打开视频”或“开启摄像头”进行实时检测。5.3 验证数据存储打开MySQL客户端查询数据是否成功插入USE bee_detection_db; SELECT * FROM detection_records ORDER BY detection_time DESC LIMIT 5;你应该能看到类似下面的记录------------------------------------------------------------------------------------------------------------------------------------------ | id | image_path | detection_time | bee_count | confidence_avg | bbox_info | note | ------------------------------------------------------------------------------------------------------------------------------------------ | 1 | /path/to/bee_image.jpg | 2024-05-20 10:30:25| 5 | 0.87 | [{x1:100,y1:50,...}, ...] | NULL | ------------------------------------------------------------------------------------------------------------------------------------------6. 常见问题与排查思路在开发和运行本系统时你可能会遇到以下问题问题现象可能原因解决思路导入ultralytics报错未安装ultralytics包或PyTorch版本不兼容。1. 确认已执行pip install ultralytics。2. 检查PyTorch是否安装正确python -c import torch; print(torch.__version__)。运行GUI时提示No module named PyQt5PyQt5未安装或安装失败。1. 使用pip install PyQt5 PyQt5-tools重新安装。2. 如果使用conda尝试conda install pyqt。模型加载失败或检测无结果模型权重文件路径错误或损坏图片尺寸与训练时差异过大。1. 检查model YOLO(path/to/model.pt)中的路径是否正确。2. 尝试用训练时相同的尺寸如640x640预处理图片。摄像头无法打开摄像头被其他程序占用摄像头索引错误。1. 关闭其他可能使用摄像头的软件如微信、Zoom。2. 尝试将cv2.VideoCapture(0)中的0改为1或其他索引。数据库连接失败MySQL服务未启动用户名/密码错误数据库不存在。1. 在服务中确认MySQL服务正在运行。2. 使用命令行或Workbench测试连接参数。3. 确认bee_detection_db数据库和表已创建。检测速度非常慢使用了过大的模型如YOLOv8x在CPU上运行。1. 对于实时应用选择YOLOv8n或YOLOv5s等轻量模型。2. 确保PyTorch使用了GPUdevice0。检查CUDA和cuDNN安装。保存到数据库时程序卡死或无响应数据库操作在主线程中进行耗时过长阻塞了GUI事件循环。1. 我们的代码已通过线程处理检测但保存操作仍在主线程。对于大量数据也应将保存操作放入线程。本文示例为简化未做此处理。7. 最佳实践与工程建议将原型系统转化为一个健壮、可维护的项目还需要考虑以下几点7.1 模型部署优化模型格式生产环境建议使用TorchScript或ONNX格式它们对部署更友好且可以利用TensorRT、OpenVINO等推理引擎加速。推理优化使用half半精度推理可以显著提升速度并减少显存占用只需在推理时设置model.half()。批处理如果处理的是视频流可以考虑积累几帧后进行批处理推理能提升GPU利用率。7.2 应用程序健壮性异常处理对所有文件I/O、数据库操作、模型推理都进行try-except包装并给用户友好的提示而不是让程序崩溃。配置管理将模型路径、数据库连接参数、置信度阈值等配置项提取到外部的config.ini或config.yaml文件中便于管理和部署。日志记录使用Python的logging模块记录程序运行状态、错误信息和检测统计便于后期排查问题。资源管理确保在程序退出或停止时正确释放摄像头、数据库连接等资源如我们在closeEvent和stop_detection中所做。7.3 数据库设计扩展当前的单表设计适用于基础功能。随着数据量增长和需求复杂化可以考虑分表按时间如每月一张表或设备ID分表提升查询性能。索引优化在detection_time和bee_count字段上建立索引加速按时间和数量的查询。关联信息增加device_id、location字段以支持多设备、多位置的监测网络。结果快照除了存储边界框JSON还可以将检测后的标注图片以BLOB或文件路径形式存储便于回溯。7.4 前端功能增强历史记录查询在GUI中增加一个标签页或对话框用于查询和展示数据库中的历史检测记录并支持按时间、数量筛选。数据可视化集成matplotlib在界面中绘制蜜蜂数量随时间的变化曲线图。模型性能评估增加一个功能使用预留的测试集对当前加载的模型进行mAP、Recall等指标的计算和显示。参数调优界面提供IOU阈值、图像尺寸等更多模型参数的实时调节滑块。7.5 部署与打包环境封装使用conda env export environment.yml导出环境或在requirements.txt中精确固定所有库的版本。打包成可执行文件使用PyInstaller或cx_Freeze将整个项目打包成.exeWindows或可执行文件方便在没有Python环境的电脑上运行。# 使用PyInstaller打包示例 pyinstaller --onefile --windowed --add-data yolov8n.pt;. bee_detection_gui.py通过以上步骤你不仅完成了一个功能完整的蜜蜂目标检测系统更掌握了一套将AI模型、桌面应用和数据库结合起来的通用开发流程。这套流程可以轻松迁移到其他目标检测任务中例如车辆计数、安全帽检测、野生动物监测等。
返回列表