☰
基于YOLOv12的鸡检测系统:从数据标注到部署的完整实践
2026/10/17 4:25:03 网站建设 项目流程

养鸡场每天早晚盘点数量,人工数鸡数到眼花,光照差一点就看漏;想观察鸡群有没有异常聚集,靠人盯监控又盯不住。这些问题做养殖的人基本都遇到过。我做的这个“基于YOLOv12的鸡检测系统”,就是用深度学习模型YOLOv12配合YOLO格式数据集,把图片和视频里的鸡自动识别出来,标出位置、统计数量,再套上一个带登录注册功能的UI界面,打包成一套完整的Python项目源码加训练好的模型。简单说,它解决的是“鸡在哪、有多少、状态正不正常”这三个最核心的问题。这套东西既适合拿来落地用,也适合做智慧养殖方向的项目练习。

系统本身的代码结构并不复杂,真正花时间的是数据准备和模型训练。为了让你少走弯路,我会把从需求拆解、数据标注、模型训练,到界面开发和部署运行的整个流程都捋一遍,包括踩过的坑和排查方法。

1. 项目需求与技术选型

1.1 鸡检测场景的真实痛点

鸡检测和通用目标检测最大的区别在于:鸡是密集目标,而且姿态千奇百怪。白天在养殖场里,鸡群经常扎堆,一只叠一只;到了晚上,散养鸡会飞上栖架,监控视角变得很刁钻。你用通用模型直接硬套,往往会出现漏检、重检、框不准这类毛病。

养殖场景的检测需求也不只是“认出鸡”这么简单。最常见的是数量统计:出栏时清点鸡数,或者定期抽样评估存活率。还有行为分析:鸡群如果长时间聚集不动,很可能是疫病或者温度异常的前兆;通过检测每只鸡的位置分布,可以算出活动区域密度,辅助判断鸡群状态。再有就是个体识别衍生需求,比如和体尺测量结合,评估生长均匀度。这些场景决定了系统不只是调用一个模型做检测,还得有图片上传、批量处理、结果统计、记录回看这些配套功能。

我最初想直接用现成的检测接口来做,但实际试下来并不好用。通用接口对“鸡”这种类别的细化程度不够,更没有针对密集小目标的调优,漏检率偏高。自己训练一个专用模型,看似要投入数据标注的时间,但整套流程走通之后,无论精度还是可控性都明显优于通用方案。

1.2 为什么选择YOLOv12

YOLO系列走到现在,版本很多。不少人有疑问:都出到v12了,为什么不用更成熟的v8?YOLOv12最大的改进点在于引入了新的注意力机制和多尺度特征融合策略,在保持实时检测速度的同时,对中小目标的召回率比前代有明显提升。

养鸡场景里,摄像头距离鸡群往往比较远,单只鸡在画面里占的像素很少,属于典型的“小目标”。YOLOv8虽然也能做小目标检测,但密集遮挡情况下容易出现边界框漂移。YOLOv9、v10解决了一部分问题,可模型结构偏重,如果后续要在低算力设备上部署,压力比较大。YOLOv12在精度和速度之间找到了更好的平衡点,这也是我最终选它的原因。

另一个实际原因是部署兼容性。YOLOv12基于PyTorch框架,训练和导出流程与主流YOLO生态保持一致。不管是导出ONNX格式接入服务端,还是直接保留PyTorch模型走界面推理,都方便。对于以Python为主的技术栈来说,接入成本很低,不需要额外搞一套C++推理框架。

1.3 系统架构与模块划分

整个系统按功能可以拆成三条线:

  • 数据线:图片采集、标注、数据集划分、数据增强。这条线主要负责生成高质量训练素材。
  • 模型线:YOLOv12训练、验证、导出。这条线产出的是最终可用的权重文件。
  • 业务线:用户登录注册、检测界面、图片/视频/实时画面接入、检测结果展示与记录。

界面我用的是PyQt5,没有用Tkinter。原因很直接:Tkinter做简单工具够用,但做这种带登录页、检测主页、结果列表的系统,界面会非常粗糙,后期调整布局也很费劲。PyQt5的控件丰富度、样式定制能力、信号槽机制都更适合做完整可交付的项目。

数据库用了SQLite。搭建登录注册功能时只需要存用户名、密码哈希、注册时间这几个字段,SQLite单文件部署最省事,不需要安装数据库服务。数据量增长到几十万条用户记录之前,SQLite完全扛得住。

2. 数据集准备:决定模型上限的关键环节

2.1 图像采集与场景覆盖

模型的精度上限在数据阶段就已经定死了,训练只是逼近这个上限。养鸡检测的数据采集,第一原则是“场景要和实际使用一致”。如果模型训练用的大多是干净、明亮、单只鸡的特写图,部署到养殖场昏暗、杂乱的监控画面里,效果一定会崩。

所以我采集图像时会有意识地覆盖这几类变化:

  • 光线变化:白天强光、阴天、傍晚昏暗、夜间补光。
  • 姿态变化:站立、低头啄食、展翅、卧伏、飞上栖架。
  • 密度变化:单只、三五只、几十只密集扎堆。
  • 遮挡情况:被料槽挡住、被其他鸡挡住、被围栏局部遮挡。
  • 拍摄视角:平视、俯视、斜上方监控视角。

每类变化都尽量多收集图片。有人觉得“数量够多就行”,其实在数量拍租的前提下,分布是否均衡更关键。如果傍晚暗光图片很少,模型对夜间场景的适应能力就特别差。我建议至少保证每个场景类别占比不低于总量的10%。

2.2 标注工具与YOLO格式细节

标注工具我用的是LabelImg,界面直观,导出YOLO格式很方便。安装时会连带安装Qt界面库,日常标注操作就是画框、选类别、保存、切下一张。

YOLO格式的标注文件是txt文本,每行对应一个目标框,结构是:

类别ID 中心点x 中心点y 框宽 框高

注意这里的四个坐标值全部做了归一化,范围是0到1。中心点坐标除以图片宽高得到归一化坐标,框宽高也对应除以图片宽高。标注时最容易出的问题是用成了像素坐标,或者忘了归一化,导致训练时loss异常大,检测结果一片乱。

举个例子。一张1280x720的图片,某个标注框左上角是(300, 200),右下角是(500, 400)。那么框宽是200,高是200,中心点x是400,中心点y是300。归一化之后:

class_id 400/1280 300/720 200/1280 200/720

算出来就是:

0 0.3125 0.4167 0.15625 0.2778

标注顺序必须严格对应,类别ID从0开始。训练时配置的类别名列表也要和标注ID对得上。

标注小技巧:密集场景下不要强行标那些被遮挡超过70%的个体,标出来反而会引入大量模糊标签,给训练增加噪声。一般原则是能看到明显轮廓的鸡才标。

2.3 数据增强与划分策略

数据增强我并没有依赖在线增强跑完就完事,而是在训练前先做了一轮离线增强,把原始数据集扩充到原来的3倍。离线增强的主要手段包括:

  • 水平翻转,因为鸡出现的方向没有固定朝向。
  • 亮度对比度调整,模拟不同光线环境。
  • 裁剪缩放,模拟摄像头距离变化。
  • 高斯噪声,提升对监控画质的鲁棒性。

离线增强之后再做数据集划分,划分比例我用的是训练集:验证集:测试集=7:2:1。这里有一个新手容易犯的错误:增强后的图片如果来自同一张原图,很可能被同时分进训练集和测试集,导致验证指标虚高。划分必须先按原始图片分组,保证同源增强图片进同一个集合,不能随机打散。

数据量不大的情况下,标注质量比数据量更关键。一帧画面上几十只鸡,漏标几只看起来是小问题,但模型会把这些漏标区域当成负样本学习,相当于给模型灌输了“这里没有鸡”的错误信息。我标注时宁可慢一点,也要保证每张图都完整覆盖。

3. 模型训练与调优

3.1 环境搭建与训练参数配置

训练阶段我用的环境是Python 3.9 + PyTorch 2.0版本,显卡是单块中高端消费级显卡。显存大小决定了batch size上限,batch太小时BatchNorm统计不稳定,训练容易震荡;batch太大又容易OOM。以YOLOv12默认模型规模为例,输入尺寸640x640时,显存8GB可以开到batch 16,16GB可以开到batch 32。

超参数这块,我直接给出实际跑通的一组配置:

参数推荐值说明
输入尺寸640x640精度和速度的平衡点
初始学习率0.01配合预热机制快速收敛
权重衰减0.0005防止过拟合
动量0.937SGD优化器常规设置
训练轮数150配合早停机制使用
Batch Size16按显存调整
热身轮数3前3轮学习率逐步上升

训练命令长这样:

python train.py --data data.yaml --weights yolo12n.pt --img 640 --batch 16 --epochs 150 --project runs/train

data.yaml里要写清数据集路径、类别数和类别名。类别名必须是英文,比如chicken,不要直接写中文,否则部分环境会引发编码问题。

3.2 训练过程观察与评估指标

训练不是启动完就等着收模型。前几十轮要经常看训练曲线,尤其是loss曲线。正常情况box_loss和cls_loss应该是平滑下降的。如果loss出现剧烈震荡,通常原因有三个:学习率过大、数据集中存在大量标注异常、batch size太小。

验证集指标主要看mAP@0.5和mAP@0.5:0.95。对于鸡检测这种类别单一的任务,mAP@0.5达到0.95以上才算合格。我实际跑下来,数据充足时mAP@0.5能到0.96到0.98,mAP@0.5:0.95大概在0.82到0.87。如果后者明显偏低,一般是边界框定位不够精细,可以回查标注框有没有贴合鸡的身体轮廓。

训练产物里有best.pt和last.pt。best.pt是验证集上表现最好的权重,部署就选它。last.pt是最后一轮权重,用来判断模型有没有过拟合——如果best明显优于last,说明后期训练已经过拟合,可以提前停止。

3.3 模型轻量化与导出

训练好的PyTorch模型文件,体积从几十MB到一百多MB不等。直接在界面里用没问题,但要做成更通用的服务端部署,建议导出ONNX格式:

python export.py --weights runs/train/exp/best.pt --img 640 --include onnx

导出ONNX之后有两个好处。一是可以用ONNX Runtime加速推理,摆脱PyTorch环境依赖;二是后续如果要把检测服务做成HTTP接口,或者嵌到其他语言的项目里,ONNX格式兼容性更好。

模型轻量化方面,如果追求速度,可以在训练时直接选YOLOv12的轻量版本参数量更小的预训练权重作为起点。轻量版精度会有所下降,但在养殖场这类检测目标比较单一的场景里,下降幅度完全可以接受,换来的是更快的推理速度。如果设备有GPU,优先保留原模型;如果只用CPU部署,建议导出FP16或INT8量化版本。

实测经验:白天场景和夜间补光场景差异很大,条件允许时分别准备两份训练数据,比单纯把两类图混在一起训练效果更稳定。

4. 从模型到系统:UI界面与业务闭环

4.1 系统界面与登录注册设计

整个系统界面分两层:登录注册窗口和主检测窗口。登录窗口承担用户身份验证,主检测窗口承担核心功能。

登录注册功能用SQLite存用户信息,密码不能明文保存。我用了加盐哈希方案:注册时生成一个随机盐值,再通过hashlib做多次迭代哈希,把盐值和哈希结果一起存进数据库。每次登录校验时,取出盐值重新计算比对。明文存储密码是非常严重的失误,一旦数据库泄露,所有用户的密码在外部字典攻击面前不堪一击。

用户表结构大概是:

id INTEGER PRIMARY KEY AUTOINCREMENT username TEXT UNIQUE NOT NULL password TEXT NOT NULL salt TEXT NOT NULL created_at TEXT DEFAULT (datetime('now','localtime'))

注册时除了密码强度检查之外,还需要做用户名重复校验。登录成功后跳转到主界面,登录失败则给出提示并记录失败次数,防止暴力破解。

4.2 检测主界面功能拆解

主检测界面按功能分四个区域:

  • 顶部工具栏:打开图片、打开视频、切换摄像头信号源、退出程序。
  • 左侧操作区:检测参数调节选项,如置信度阈值、IoU阈值。
  • 中间显示区:原图和检测结果图的切换展示。
  • 右侧信息区:检测数量统计、每只鸡的置信度列表、历史检测记录。

置信度阈值和IoU阈值这两个参数做成了可调节控件,而不是写死。置信度阈值决定了“多像鸡才算鸡”,调高可以减少误检,调低可以降低漏检。IoU阈值决定重叠框的合并程度,密集场景下适当调高可以让挨在一起的鸡被分得更开。实战中置信度设为0.3到0.35,IoU设为0.45到0.5,表现比较均衡。

4.3 模型对接与结果展示

界面加载模型的核心逻辑是:程序启动后用PyTorch加载best.pt权重,推理时把传入的图片处理成640x640,经过模型前向传播得到检测结果,再解析预测框坐标映射回原始图片尺寸,用OpenCV绘制边界框和标签,同时把检测数量更新到统计区域。

关键代码片段大概是这个样子:

import cv2 import torch model = torch.load("best.pt", map_location="cpu") model.eval() def detect_image(img): results = model(img) boxes = results.xyxy[0].cpu().numpy() # x1, y1, x2, y2, conf, cls count = 0 for box in boxes: x1, y1, x2, y2, conf, cls_id = box if conf >= 0.30: count += 1 cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) cv2.putText(img, f"chicken {conf:.2f}", (int(x1), int(y1)-5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) return img, count

如果你用的是新版YOLO的Python接口,推理逻辑会简化成一行results = model(img)。但底层思路一样,都是取xyxy坐标、置信度、类别ID,然后绘制。

视频和实时画面的处理逻辑是逐帧循环。这里要特别留意内存回收,逐帧推理如果处理速度跟不上帧率,画面会越积越卡。我实际测下来,CPU上纯Python循环处理640x640视频,每秒大概能跑3到5帧,GPU上可以到每秒几十帧。实时显示场景建议显示画面时不保存检测结果帧,否则内存很快被耗光。

5. 实战中的常见问题与排查技巧

5.1 典型问题速查表

做这个项目的过程中,我积累了一些典型的问题和排查经验,罗列如下:

现象可能原因排查与解决
训练loss不下降学习率过高、标注数据错误降低初始学习率,抽查标注框位置
检测框偏移严重数据集场景单一、图像尺寸比例失衡增加多视角数据,统一输入尺寸
小目标漏检多输入分辨率低、小目标样本不足训练时升级到更大输入尺寸,补充密集场景图
白天效果好夜间差夜间样本不足单独采集夜间数据或使用离线亮度增强
UI界面启动慢模型加载耗时初始化时显示加载状态,或使用异步方式加载模型
登录后无法进入主界面数据库路径或登录跳转逻辑错误检查数据库初始化代码,确认用户表已创建
摄像头画面卡顿推理速度低于采集帧率跳帧处理,降低推理分辨率,开启多线程采集
导出ONNX后精度下降动态尺寸导致转换误差固定导出尺寸,使用静态输入shape

第一条训练loss不下降,是出现频率最高的问题。很多新手要么疯狂调学习率,要么反复加大训练轮数,结果都没用。我的建议是先检查前100张训练图片的标注,如果标注框有大量偏移或类别标错,那loss怎么调都降不下来。模型不背这个锅,数据背。

小目标漏检的问题,跟输入尺寸关系很大。同样的模型,在640x640下检测,和在1280x1280下检测,小目标召回率差距非常明显。代价是推理时间成倍增加。养殖场场景如果对实时性要求不高,我建议用960x960输入来换精度。

5.2 性能优化与部署建议

整个项目要做扎实,不能只停留在“能跑”的层面。我最后总结几个提升系统可用性的优化方向。

第一,模型推理建议封装成独立的检测服务线程。UI界面的主线程只做界面刷新和交互响应,检测任务放到后台线程执行。否则视频检测时界面会直接卡死,用户体验非常差。用PyQt5的QThread就可以实现,逻辑不复杂。

第二,批量检测场景用Python的多进程或者线程池并发处理图片,能明显缩短大量图片的总耗时。单张图片推理时间不变,但整体吞吐量上去了。

第三,日志记录要重视。每一次检测的图片名、检测数量、检测耗时、置信度分布都记录下来,后续做系统调优或问题回溯时,这些日志能提供关键线索。我用的是Python标准库logging模块,按天写入文件。

第四,如果未来要部署到嵌入式设备或者养殖场现场的边缘盒子,建议优先走ONNX加量化路线。GPU不是每家养殖场都愿意配的,CPU边缘设备跑轻量量化模型,能保证基本可用。

部署完成后可以加一个扩展点:检测结果接入定时任务,每天生成养殖日报,统计鸡只数量变化趋势。这一步其实不用改多少代码,就是多读一次检测输出文件,汇总成表格而已,但价值会高很多。

写在最后的几条心得

这个项目做下来,我最大的体会是:目标检测系统的难点通常不在模型本身,而在数据质量和工程细节。数据标注做好,训练的坑就少了一大半;工程细节做好,界面和模型之间的衔接就顺滑。YOLOv12的框架成熟度很高,已经帮你把算法层面的很多棘手问题处理掉了,剩下的活儿更多是认真准备数据、仔细调试参数,再把代码写得干净一点。

另外分享一个我自己常用的调试方式:训练完不要急着看指标报表,先挑几十张有代表性的测试图片,把检测结果可视化出来,一张一张用眼睛过一遍。有些问题数据指标体现不出来,但图一看就能发现,比如某个固定位置的漏检、某种姿态下的误检。可视化的直觉反馈,比任何数字都直观。

如果你正准备做类似的检测系统,建议先把数据集质量和标注规范放在第一位,然后再去纠结具体用什么网络结构。结构上的差异顶多是把95分提到98分,而一份烂数据能把模型直接拖到及格线以下。先把基础打牢,后面的一切都会顺畅很多。

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

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

立即咨询