基于YOLOv8的老鼠检测:从数据集训练到PyQt界面部署实战
2026/9/10 2:29:13 网站建设 项目流程

简介:面向需要训练老鼠目标检测模型的开发者与研究人员,这一YOLOv8算法老鼠动物检测权重资源整合了5000多张标注好的老鼠检测数据集,已按train、val、test三个子集划分完毕,目录结构清晰,并附带可直接调用的data.yaml配置,免去自行整理数据集的繁琐工作。压缩包共2000个文件,其中1991个为xml标签文件,包含txt与VOC两种标注格式,另有md说明文档、pdf环境配置教程以及py脚本工具,整体约287.8MB。数据集兼容YOLOv5、YOLOv7、YOLOv8、YOLOv9等主流检测算法,拿到后即可直接训练、验证与评估,也可用于算法对比与模型调优。学习人数已有197人。除检测权重外,压缩包还提供pyqt界面相关脚本与环境配置手册,能够快速搭建带图形界面的检测演示系统,方便展示检测效果。整体来看,适合作为毕业设计、课程项目或智能监控场景的基础数据集与参考实现,既能帮助入门者快速跑通流程,也能为进阶者提供标注规范与工程化思路。

1. 老鼠检测的痛点与YOLOv8权重包的选择

在养殖场、食品仓储、实验室动物房这些场景里,老鼠检测的难点不是“识别老鼠”本身,而是要在杂乱背景、弱光线和快速移动下保持低误报。用通用COCO训练出的YOLOv8权重虽然能认出“mouse”类别,但对家鼠、褐家鼠、小白鼠这种小目标会出现大量漏检,因为COCO里老鼠样本太少,且目标尺寸分布与监控画面相差悬殊。我这边的做法是放弃通用权重,直接用一份包含5000多张标注图片的老鼠数据集重新训练YOLOv8模型,再配合PyQt界面,让没有深度学习背景的现场人员也能双击打开程序完成检测。这套资源的价值在于:数据集目录已经划分好train/val/test,data.yaml写好了类别配置,YOLOv5/7/8/9都能直接开始训练,避免了自己从零标注和处理格式转换的琐碎工作。

2. 数据集结构复盘:5000多张老鼠图片的标签组织与data.yaml解析

2.1 目录划分与VOC/TXT双标签的共存逻辑

拿到资源后,我先把目录整体看了一遍。img_0651_3791.xml这类文件说明数据集同时给出了VOC格式的XML和YOLO格式的TXT标签。VOC格式适合用LabelImg或者Roboflow做二次审核,YOLO格式直接喂给训练脚本。目录结构大致如下:

dataset/ ├─ images/ │ ├─ train/ │ ├─ val/ │ └─ test/ ├─ labels/ │ ├─ train/ │ ├─ val/ │ └─ test/ ├─ annotations/ │ ├─ ...xml └─ data.yaml

注意看,imageslabels下的子目录一一对应。很多教程文档会写一个train.txt列出图片路径,而这里直接用目录划分,YOLO训练时只需在data.yaml里指向images目录,labels目录会自动匹配同名TXT文件。这里有个容易踩的坑:YOLO系列的标签文件名必须和图片名完全一致,后缀不同没关系,但名字错一个字符都训练不到。XML文件则是另一套体系,它服务于PyQt界面里的二次标注展示,或者你想把数据集导回VOC格式重新清洗时使用。

2.2 data.yaml的配置含义与路径补齐

data.yaml是YOLOv5/8/9训练时读取的配置入口。资源里的内容很短:

nc: 1 names: - mouse

nc表示类别数为1,names列表顺序对应类别ID。这里只写了mouse,意味着训练时目标框会被编码为class_id = 0。如果你想把“大老鼠”和“小老鼠”分开检测,就要改成nc: 2并把names扩展成两项,同时所有标签文件里的类别ID也要跟着改,不然训练阶段会报Label class exceeds nc错误。另外,这份yaml没有显式写train/val/test路径。我一般会在同一个yaml里补上显式路径,避免在不同机器上反复改参数:

train: D:/datasets/mouse/images/train val: D:/datasets/mouse/images/val test: D:/datasets/mouse/images/test nc: 1 names: - mouse

这样写的逻辑是:YOLO源码读取train字段后,会拼接labels目录的对应子目录。如果你用相对路径,程序默认工作目录必须是配置文件的上级目录,否则会报找不到图片。用绝对路径最省事,但换机器要改,所以我更推荐在训练脚本里用os.path.abspath动态拼接当前目录,而不是把手写死。

2.3 标签格式转换与分布检查

在开始训练之前,我还习惯做一次标签分布检查,用来判断这个数据集够不够练出一个稳定的权重。YOLO的TXT标签每一行是class_id x_center y_center width height,所有坐标都是归一化到图片宽高的比例值。比如某个样本的XML里是<xmin>300</xmin> <xmax>500</xmax> <ymin>200</ymin> <ymax>400</ymax>,图片宽608高480,换算后就是:

x_center = (300 + 500) / 2 / 608 # 0.6579 y_center = (200 + 400) / 2 / 480 # 0.625 width = (500 - 300) / 608 # 0.3289 height = (400 - 200) / 480 # 0.4167

用脚本批量解析所有标签,可以统计每个类别和尺寸的分布:

import os, glob label_paths = glob.glob('dataset/labels/train/*.txt') for p in label_paths[:5]: with open(p) as f: lines = f.read().strip().split('\n') print(os.path.basename(p), len(lines))

这段代码的作用是确认每张图片的标注数量。正常情况老鼠框是单个目标,但如果一张图里有四五只老鼠,len(lines)会大于1,这也是训练数据里应该存在的复杂样本。重点是检查那些widthheight接近0的标签——它们往往是把标注框压成一条线了,训练时会拉低回归精度。XML和TXT字段对照关系可以整理成下表:

XML字段YOLO TXT字段换算关系
xminx_center - width/2图像左边界
xmaxx_center + width/2图像右边界
yminy_center - height/2图像上边界
ymaxy_center + height/2图像下边界

检查时发现异常标签,我直接写一个小函数从XML重新生成TXT,而不是手动改,避免漏改导致训练时读到越界坐标。

3. YOLOv8训练老鼠权重:C2F结构、环境配置与训练监控

3.1 模型结构里C2F如何影响老鼠检测

YOLOv8用C2F模块替代了YOLOv5的C3模块。C2F把输入特征图分成两个分支,一支经过多个Bottleneck堆叠,另一支直连,最后在输出层concat,这样梯度可以同时从深层和浅层回传,对老鼠这种纹理匮乏的小目标更友好。但在实际训练时,C2F不是决定性因素,backbone在浅层保留的细节特征才是,所以训练时输入尺寸不要一上来就设640,可以考虑768甚至960,因为老鼠相对整张监控画面可能只占几十个像素。

我拿这套资源在本地跑过一次。显存只有6G的GTX1660 Ti,用默认的yolov8n结构训练,batch size设8,输入尺寸640,能跑,但峰值显存到了5.6G。如果换成yolov8s,batch size要降到4。yolov8nyolov8s这些预训练权重的差别在depth和width倍数上,yolov8n速度快但特征层通道数少,对极小目标容易丢;yolov8m精度高,但6G卡就吃力了。各预设模型的取舍可以看下表:

模型depth_multiplewidth_multiple6G显存下的batch建议适用场景
yolov8n0.330.258实时性优先,CPU可跑
yolov8s0.330.504常规项目平衡点
yolov8m0.670.752精度优先,需更大显存

3.2 环境配置要点

根据资源附带的环境配置教程,核心步骤就是装对CUDA、PyTorch和Ultralytics的版本。我用的是:

conda create -n yolov8 python=3.9 -y conda activate yolov8 pip install torch==2.1.2 torchvision==0.16.2 --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics==8.2.0 opencv-python pyqt5

这里有个容易混淆的地方:ultralytics包本身就包含YOLOv8的实现,不需要单独clone仓库。安装完验证一下:

python -c "from ultralytics import YOLO; print(YOLO.__name__)"

如果不报错,再跑默认推理,确认能够正常调用GPU。如果用的是20系以下显卡或者核显,pip安装时可以把cu118换成cpu版本,免得装一个用不上的CUDA依赖。训练数据只有单一类别时,ultralytics会自动忽略类别不平衡问题,但如果你后续要扩展成多类别,就要关注每个类别的样本量。

3.3 训练命令与参数调整

准备好数据集路径后,训练老鼠权重的命令是:

yolo detect train \ data=D:/datasets/mouse/data.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=8 \ device=0 \ project=runs/mouse_detect \ name=exp_mouse

解释一下各参数的含义:model=yolov8n.pt这里用的不是随机初始化,而是COCO预训练权重,它会把backbone的特征提取能力迁移过来,只重新训练head部分,这比从零训练快约三分之一。epochs在数据集有5000多张且只有1个类别的情况下,50到100足够了,再多容易过拟合。imgsz决定训练时resize的尺寸,如果你统计发现标签框普遍小于图片面积的1%,建议提升到768或960,代价是训练时间和显存上升。device=0表示第一块GPU,没有GPU就填cpu

训练过程中可以随时查看损失曲线。YOLOv8的训练日志会输出train/box_losstrain/cls_lossval/box_loss等。我一般看两点:一是val/box_loss下降趋势是否与train/box_loss同步,如果train降、val不降,就是过拟合了;二是metrics/mAP50(B)在最后20个epoch有没有继续提升,如果曲线已经平了,训练就停了,不需要等epochs跑完。

3.4 数据增强对老鼠检测的影响

YOLOv8默认开启mosaic增强,把四张图拼在一起训练,对提高目标周围背景多样性有帮助。但对老鼠这种小目标,mosaic会让目标变得更小,可能某些窗口内连一个完整目标都没有。我通常这样调整:

mosaic: 0.5 # 从默认1.0降低到0.5 close_mosaic: 10 # 最后10个epoch关闭mosaic,消除增强和真实分布的差异 mixup: 0.2

这些参数放在data.yaml同级或者写在训练命令里,都可以被Ultralytics的配置解析。降低mosaic之后,训练出来的权重在实拍夜间监控画面上的漏检率,会比全mosaic低一些,这是我在项目里实际对比过的结果。如果数据集拍摄环境比较单一,比如都是在同一个仓库拍的,建议同时关掉hsv_h的颜色扰动,只保留轻微旋转和翻转,否则模型会学着忽略颜色变化,但真实场景里老鼠和地板的颜色差异恰恰是区分线索之一。

4. PyQt识别界面设计:模型加载、线程分离与画面刷新

4.1 界面框架与线程分离

win.py是主程序,基于PyQt5构建。界面主要包含三个区域:图像显示区、检测结果列表区、操作按钮区(打开图片、打开摄像头、加载权重)。最容易被忽视的是推理线程与UI线程的分离。如果直接在按钮的槽函数里跑model.predict(),检测一帧需要几百毫秒,界面会卡死,鼠标无法拖动窗口,看起来像崩溃了。我用的是QThread加信号槽的模式:

import cv2 from PyQt5.QtCore import QThread, pyqtSignal from ultralytics import YOLO class DetectThread(QThread): frame_signal = pyqtSignal(object, list) def __init__(self, model_path): super().__init__() self.model = YOLO(model_path) self.running = True def run(self): cap = cv2.VideoCapture(0) while self.running: ret, frame = cap.read() if not ret: break results = self.model.predict(frame, conf=0.45, imgsz=640, verbose=False) boxes = results[0].boxes.xyxy.cpu().numpy() self.frame_signal.emit(frame, boxes)

这段代码的逻辑是:新开一个线程循环读取摄像头帧,执行检测,并透过frame_signal把图像和框坐标传回主线程。注意predict里有verbose=False,否则每次推理都会往终端刷进度条,与PyQt的日志控件混在一起很难看。conf=0.45是比较保守的置信度,老鼠检测场景机器误报成本高,我会把conf提到0.5以上,宁可漏检一次,也不要连续误报十次。

4.2 界面刷新与边框绘制

主线程收到信号后,用cv2.rectangle画框再转成QPixmap展示。这里有个细节:摄像头传进来的是BGR格式,QLabel显示时需要转成RGB才能保证颜色正常,否则老鼠毛色会偏蓝。绘制好的图像要用setPixmap更新,而不是每次重新创建QLabel。

def on_frame(self, frame, boxes): for x1, y1, x2, y2 in boxes: cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch = rgb.shape bytes_per_line = ch * w qimg = QImage(rgb.data, w, h, bytes_per_line, QImage.Format_RGB888) self.label.setPixmap(QPixmap.fromImage(qimg).scaled( self.label.width(), self.label.height(), Qt.KeepAspectRatio))

这里的scaled会按QLabel尺寸等比缩放,但边框坐标是基于原始分辨率的,所以绘制时用的是原始坐标,显示时才缩放。如果检测目标很多,cv2.rectangle循环画框没问题,但如果还要画类别名称,注意字体大小要随缩放比例换算,不然在QLabel缩放后文字会糊成一团。我一般同时把检测数量更新到状态栏,方便现场人员确认程序是否在正常处理。

4.3 模型加载的耗时优化

我第一次双击运行win.py,模型加载等了大概2秒,因为YOLO('best.pt')要初始化网络结构。如果用户只是打开图片检测,这个等待可以接受;但如果做成实时监控程序,我建议在启动时先加载模型,而不是按需加载。apprcc_rc.py是PyQt的资源文件,里面打包了图标和样式,PyInstaller打包时要把win.pybest.ptapprcc_rc.py放在同一目录。PyInstaller的坑在于模型文件默认不会被打进exe,我用--add-data手动指定:

pyinstaller -F -w --add-data "best.pt;." --add-data "apprcc_rc.py;." win.py

注意Windows下--add-data用分号分隔,Linux用冒号,混了会导致打包出来的exe找不到模型,提示Model 'best.pt' not found。打包完成后最好换一台没有安装Python的机器测试,因为-w隐藏控制台后,如果模型路径异常,用户只看到程序闪退,没有任何错误提示。为了避免这种情况,我在win.py启动时加了try-catch,把异常写入本地日志文件,方便远程排查。

4.4 视频流处理的丢帧策略

摄像头实时检测时,如果推理速度跟不上帧率,视频会出现闪烁。常见做法是每3帧取1帧做检测,检测结果缓存下来,其余帧直接使用缓存的框。这种丢帧策略在实测中让界面流畅度提升很多,也降低了小目标因运动拖影而产生的误检。不过要注意,缓存的框在画面快速转动时会明显滞后,所以缓存时间不能超过200毫秒,或者手动加一个“检测间隔”滑块,让用户根据现场情况调节。另一个细节是VideoCapture的缓冲区,默认情况下摄像头驱动会堆积旧帧,导致推理的总是几十毫秒前的画面,设置cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)可以让推理画面更接近当前时刻。

5. 验证与进阶:mAP评估、C2F结构优化和布控技巧

5.1 用测试集评估权重的真实表现

训练完成的best.pt不能只看loss,要拿images/test跑一遍指标。命令:

yolo detect val \ model=runs/mouse_detect/exp_mouse/weights/best.pt \ data=data.yaml \ split=test \ imgsz=640

输出会显示mAP50(B)mAP50-95(B)。单类老鼠检测,mAP50跑到0.9以上算正常,mAP50-95一般比mAP50低10到20个百分点,因为后者对边框贴合更严格。如果发现mAP50有0.95,但mAP50-95只有0.7,说明框的位置偏了,或者标签本身有大量标注误差。可以用前面写过的检查脚本,把训练样本里面积较大的标签挑出来,人工对照原图,看看XML里的框是不是比老鼠实际轮廓明显大一圈。

5.2 对YOLOv8 C2F结构做轻量改造

如果你不需要GPU加速,而是想在纯CPU工控机上运行,可以考虑把模型导出为ONNX再转OpenVINO。Ultralytics自带导出:

yolo export model=best.pt format=onnx imgsz=640 opset=13

导出ONNX之后,可以对C2F结构做一步轻量化:有些Bottleneck在导出时会产生大量Reshape和Transpose节点,小目标检测时这些节点在CPU上很慢。我的经验是用onnxsimplifier做一次常量折叠和重参数化,把结构压平。替换后老鼠框的检测速度在i5-8500 CPU上能从单帧1.2秒降到0.7秒左右,这是比较实用的一步。如果还要进一步提速,可以将输入尺寸固定为320的倍数并关闭动态轴,但代价是小目标漏检率可能升高,需要自己在速度与精度之间测试。

5.3 夜间布控与灰度预处理技巧

最后讲一个实际布控技巧。老鼠习惯夜间活动,仓库监控常常是红外图像。训练数据里如果只有白天的照片,夜间检测性能会明显下降。解决方式不只是加夜视训练图,而是在界面里加一个灰度预处理开关:如果画面整体亮度低于阈值,就把当前帧转成灰度再做检测,让模型识别的是纹理而不是颜色,对红外场景的鲁棒性会好一些。

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) frame = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR) # 保持三通道输入

这个开关放在PyQt界面里就是一个QCheckBox,亮度阈值取像素均值即可,代码改动不超过十行。灰度化后YOLO输入通道数仍然是3,不需要重新训练,但如果你发现灰度图检测结果比彩色图差,说明训练数据里的颜色信息确实对老鼠区域有帮助,那就不要开这个开关。反过来,如果彩色图在红外场景下频繁漏检,这个预处理可以从根本上绕开颜色偏移分布带来的干扰。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询