简介本资源为面向本科毕业设计场景的蜜蜂行为分析系统完整项目包适合计算机视觉、智慧农业方向的学生与研究人员参考。项目将YOLOv8目标检测与ByteTrack多目标跟踪相结合通过优化特征金字塔P2层提升对蜜蜂细微特征的捕捉能力实现活动轨迹记录与行为模式分析可服务于农业生态研究与智能蜂箱监控。压缩包共20个文件约10.85MB以13个Python脚本为核心涵盖训练、跟踪、预测、数据格式转换与视频处理等模块另含3个yaml配置、说明文档、演示动图及README结构清晰便于复现。目前已有80人学习下载。读者可据此获得一套可运行的检测跟踪代码框架、P2层优化配置思路与数据处理脚本快速搭建实验环境并理解多目标跟踪在农业场景中的落地方式为毕业设计或相关课题提供参考。1. 蜜蜂行为分析系统从 YOLOv8 检测到 ByteTrack 轨迹的完整落地路径蜂箱门口每分钟进出上百只蜜蜂靠人眼数根本数不过来更别说区分「采蜜归巢」「外出侦察」「守卫振翅」这些行为模式。这个毕业设计项目要解决的就是这件事用 YOLOv8 做单帧目标检测把每只蜜蜂框出来再用 ByteTrack 做多目标跟踪给每只蜜蜂分配稳定 ID最后根据轨迹的位移、速度、停留时间判断行为类别。整套系统面向农业生态研究和智能蜂箱监控两个场景核心难点在于蜜蜂体型小、密度高、遮挡频繁标准 YOLOv8 的 P3/P4/P5 特征金字塔对小目标不够友好所以项目里加了 P2 层优化。这篇文章把环境搭建、数据集处理、P2 层改造、ByteTrack 接入、行为判定逻辑和部署踩坑全部拆开讲新手能照着跑通熟手能看到参数边界和工程取舍。2. 环境搭建与数据集准备让 YOLOv8 先跑起来2.1 Ubuntu 20.04 下 CPU 版 YOLOv8 的最小可用环境很多人一上来就装 CUDA结果显卡驱动版本对不上折腾两天还没跑通第一行推理。我的建议是先用 CPU 版把流程走通确认数据和代码没问题再切 GPU 加速训练。Ubuntu 20.04 自带的 Python 3.8 就够用不需要额外升级。# 创建独立虚拟环境避免污染系统 Python python3 -m venv bee_env source bee_env/bin/activate # 安装 PyTorch CPU 版本注意 torch 和 torchvision 版本要匹配 pip install torch2.0.1 torchvision0.15.2 --index-url https://download.pytorch.org/whl/cpu # 安装 ultralytics这是 YOLOv8 的官方包 pip install ultralytics8.0.200 # 验证安装是否成功 yolo checksyolo checks会输出当前环境信息重点看三行Python 版本、PyTorch 版本、是否检测到 CUDA。CPU 环境下 CUDA 显示为 None 是正常的。如果后面要切 GPU把 torch 换成对应 CUDA 版本的包即可ultralytics 本身不用重装。提示ultralytics包版本更新很快8.0.x 和 8.1.x 之间 API 有细微差异。毕业设计建议锁定一个版本避免训练到一半接口变了。2.2 蜜蜂数据集标注用 LabelImg 还是 CVAT蜜蜂数据集和常规目标检测数据集不一样。单张蜂箱入口照片里可能有 50 到 200 只蜜蜂密集处框与框之间重叠严重。LabelImg 适合小规模标注但遇到这种高密度场景框选效率很低。我一般推荐用 CVAT 的「跟踪标注」模式先标第一帧后面用插值自动传播效率能提升三到五倍。标注格式统一用 YOLO 格式每张图对应一个.txt文件每行是class_id x_center y_center width height坐标全部归一化到 0 到 1 之间。类别按行为分还是按个体分这里有个关键决策如果只做「蜜蜂 vs 非蜜蜂」的二分类标注量小但后续行为分析全靠跟踪轨迹如果直接标行为类别采蜜、守卫、振翅标注成本高但检测阶段就能输出行为。我建议检测阶段只标「蜜蜂」一类行为判断交给轨迹分析这样标注一致性更好模型也更容易收敛。# 检查标注文件是否合法坐标必须在 0-1 之间宽高不能为 0 import os def validate_labels(label_dir): issues [] for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue path os.path.join(label_dir, fname) with open(path) as f: for i, line in enumerate(f): parts line.strip().split() if len(parts) ! 5: issues.append(f{fname} 第{i1}行字段数不对: {len(parts)}) continue cls, x, y, w, h parts vals [float(x), float(y), float(w), float(h)] if any(v 0 or v 1 for v in vals): issues.append(f{fname} 第{i1}行坐标越界) if float(w) 0 or float(h) 0: issues.append(f{fname} 第{i1}行宽高为0) return issues problems validate_labels(datasets/bee/labels/train) print(f发现 {len(problems)} 个问题) for p in problems[:10]: print(p)这段脚本在训练前跑一遍能提前发现标注错误。蜜蜂数据集最常见的问题是框太小导致宽高归一化后接近 0以及密集区域漏标。漏标对训练的伤害比错标还大因为模型会把没标的目标当成背景来学习。2.3 数据集划分与 YAML 配置YOLOv8 要求数据集按images/train、images/val、labels/train、labels/val的目录结构组织。蜜蜂数据有个特殊点同一段视频的连续帧不能同时出现在训练集和验证集里否则验证指标会虚高。正确做法是按视频片段划分一个片段的所有帧要么全在训练集要么全在验证集。# bee_dataset.yaml path: /home/user/datasets/bee train: images/train val: images/val names: 0: bee配置文件里path写绝对路径最稳妥相对路径在不同工作目录下容易翻车。names只写一个类别bee和标注时的 class_id 0 对应。3. 特征金字塔 P2 层优化让小目标检测不再漏框3.1 为什么标准 YOLOv8 对蜜蜂小目标不友好YOLOv8 默认使用 P3、P4、P5 三层特征图做检测头对应的下采样倍率是 8、16、32。一张 640x640 的输入图P3 层的特征图尺寸是 80x80每个格子对应原图 8x8 像素。蜜蜂在画面里通常只有 15 到 30 像素宽映射到 P3 层只有 2 到 4 个格子特征信息非常有限。P2 层的下采样倍率是 4特征图尺寸 160x160每个格子对应原图 4x4 像素蜜蜂能占到 4 到 8 个格子特征表达明显更充分。代价也很直接P2 层特征图面积是 P3 层的 4 倍检测头计算量和显存占用都会上升。在 GTX 1660 Ti 这种 6GB 显存的卡上加了 P2 层后 batch size 要从 16 降到 8 甚至 4。所以 P2 层不是无脑加要看目标尺寸分布。如果蜜蜂在画面里普遍大于 40 像素P3 层就够了加 P2 反而拖慢推理速度。3.2 修改 YOLOv8 配置文件加入 P2 检测头YOLOv8 的模型结构定义在ultralytics/cfg/models/v8/yolov8.yaml里。不要直接改这个文件复制一份到项目目录下改避免升级 ultralytics 时被覆盖。# yolov8-bee-p2.yaml nc: 1 scales: n: [0.33, 0.25, 1024] backbone: - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2 - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4 - [-1, 3, C2f, [128, True]] - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8 - [-1, 6, C2f, [256, True]] - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16 - [-1, 6, C2f, [512, True]] - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32 - [-1, 3, C2f, [1024, True]] - [-1, 1, SPPF, [1024, 5]] head: - [-1, 1, nn.Upsample, [None, 2, nearest]] - [[-1, 6], 1, Concat, [1]] - [-1, 3, C2f, [512]] # 12 - [-1, 1, nn.Upsample, [None, 2, nearest]] - [[-1, 4], 1, Concat, [1]] - [-1, 3, C2f, [256]] # 15 - [-1, 1, nn.Upsample, [None, 2, nearest]] - [[-1, 2], 1, Concat, [1]] - [-1, 3, C2f, [128]] # 18 (P2 层输出) - [[18, 15, 12], 1, Detect, [nc]]关键改动在 head 部分原来从 P3 层索引 4开始做上采样融合现在多接了一层从 P2 层索引 2再融合一次最终 Detect 头接收 P2、P3、P4 三层特征。scales里的n表示 nano 版本深度系数 0.33、宽度系数 0.25适合显存有限的场景。3.3 P2 层训练参数调整与显存控制加了 P2 层后训练配置要跟着调。学习率可以稍微降一点因为浅层特征对学习率更敏感。warmup 轮数适当增加让 P2 分支的权重平稳初始化。from ultralytics import YOLO model YOLO(yolov8-bee-p2.yaml) model.train( databee_dataset.yaml, epochs150, imgsz640, batch8, # P2 层显存占用大6GB 卡建议 8 或更低 lr00.005, # 比默认 0.01 降低浅层特征更稳定 warmup_epochs5, # 默认 3P2 分支需要更长预热 patience30, # 30 轮无提升就早停 device0, ampTrue, # 混合精度训练省显存 cacheTrue, # 数据集不大时缓存到内存加速训练 projectruns/bee, namep2_exp1 )batch和imgsz是显存占用的两个主要因素。如果 OOM 报错优先降 batch不要降 imgsz因为输入分辨率降低会让小目标更小P2 层的优势就没了。ampTrue在支持 Tensor Core 的卡上能省 30% 到 40% 显存GTX 1660 Ti 也支持。训练过程中用nvidia-smi -l 1实时看显存占用留 500MB 余量比较安全。4. ByteTrack 多目标跟踪接入给每只蜜蜂一个稳定 ID4.1 ByteTrack 的匹配逻辑与蜜蜂场景适配ByteTrack 的核心思路是把检测框按置信度分成高分和低分两组先用高分框和已有轨迹匹配再用低分框去匹配那些没匹配上的轨迹。这个设计对蜜蜂场景特别有用蜜蜂密集时部分个体被遮挡检测置信度会掉到 0.3 以下标准跟踪算法直接丢弃这些框导致 ID 跳变。ByteTrack 把低分框捞回来做二次匹配ID 稳定性明显提升。ByteTrack 的运动模型用的是卡尔曼滤波预测下一帧轨迹位置。蜜蜂运动速度快、方向变化突然卡尔曼滤波的预测误差比行人场景大。实际调参时要把track_buffer从默认 30 降到 15 到 20因为蜜蜂被遮挡后重新出现的间隔通常不超过 1 秒30 帧的缓冲会导致旧轨迹残留新蜜蜂被错误匹配到旧 ID。4.2 把 YOLOv8 检测结果喂给 ByteTrackultralytics 包内置了 ByteTrack 支持不需要单独安装 ByteTrack 库。直接在model.track()里指定跟踪器配置就行。from ultralytics import YOLO model YOLO(runs/bee/p2_exp1/weights/best.pt) # 自定义 ByteTrack 配置 tracker_config { tracker_type: bytetrack, track_high_thresh: 0.5, # 高分检测框阈值 track_low_thresh: 0.1, # 低分检测框阈值蜜蜂遮挡时靠这个捞回 new_track_thresh: 0.6, # 新建轨迹的置信度门槛防止误检生成轨迹 track_buffer: 20, # 轨迹丢失后保留帧数蜜蜂场景建议 15-20 match_thresh: 0.8, # 匹配 IoU 阈值 fuse_score: True # 融合检测置信度和 IoU 做匹配 } results model.track( sourcebee_video.mp4, trackerbytetrack.yaml, conf0.25, # 检测置信度阈值比跟踪阈值低 iou0.5, persistTrue, # 视频流中保持轨迹连续 streamTrue, saveTrue ) for r in results: if r.boxes.id is not None: ids r.boxes.id.cpu().numpy() boxes r.boxes.xyxy.cpu().numpy() for tid, box in zip(ids, boxes): print(fID {int(tid)}: [{box[0]:.0f}, {box[1]:.0f}, {box[2]:.0f}, {box[3]:.0f}])conf0.25是检测阶段的置信度阈值track_high_thresh0.5是跟踪阶段的高分阈值两者不要混淆。检测阈值低一点没关系ByteTrack 会在跟踪阶段过滤。persistTrue在视频文件推理时必须开否则每帧都重新初始化跟踪器ID 会从 1 重新开始。4.3 轨迹数据存储与行为特征提取跟踪输出的原始数据是每帧的(track_id, x1, y1, x2, y2)要转成行为分析可用的特征需要计算每只蜜蜂的轨迹序列。import numpy as np from collections import defaultdict class BeeTrajectory: def __init__(self): self.tracks defaultdict(list) # track_id - [(frame, cx, cy, w, h)] def update(self, frame_idx, track_ids, boxes): for tid, box in zip(track_ids, boxes): cx (box[0] box[2]) / 2 cy (box[1] box[3]) / 2 w box[2] - box[0] h box[3] - box[1] self.tracks[int(tid)].append((frame_idx, cx, cy, w, h)) def compute_features(self, fps30): features {} for tid, points in self.tracks.items(): if len(points) 10: # 轨迹太短不足以判断行为 continue arr np.array(points) frames arr[:, 0] cx, cy arr[:, 1], arr[:, 2] # 位移和速度 dx np.diff(cx) dy np.diff(cy) dist np.sqrt(dx**2 dy**2) speed dist * fps # 像素/秒 # 方向变化率 angles np.arctan2(dy, dx) angle_diff np.abs(np.diff(angles)) angle_diff np.minimum(angle_diff, 2*np.pi - angle_diff) features[tid] { total_dist: dist.sum(), mean_speed: speed.mean(), max_speed: speed.max(), mean_angle_change: angle_diff.mean(), duration: len(points) / fps, start_pos: (cx[0], cy[0]), end_pos: (cx[-1], cy[-1]) } return features这段代码把轨迹转成六个特征总位移、平均速度、最大速度、平均方向变化率、持续时长、起止位置。行为判定规则可以基于这些特征组合。比如「采蜜归巢」的典型模式是速度较快、方向变化小、从画面边缘向蜂箱入口移动「守卫行为」是位置基本不变、速度接近零、持续时长长「侦察行为」是方向变化率大、速度中等、轨迹覆盖范围广。5. 避坑与排查蜜蜂跟踪系统最常见的五个翻车点5.1 ID 频繁跳变同一只蜜蜂换了三四个 ID现象跟踪视频里蜜蜂的 ID 标签不停变化一只蜜蜂从画面左边飞到右边ID 从 5 变成 12 再变成 23。原因蜜蜂相互遮挡时检测框消失track_buffer设得太大旧轨迹保留太久新检测框匹配到了错误的旧轨迹。或者match_thresh设得太高IoU 匹配过于严格稍微偏移就匹配失败。解决把track_buffer降到 15match_thresh从默认 0.8 降到 0.7。同时检查检测模型的召回率如果漏检严重跟踪再好也没用。用验证集跑一遍model.val()看 mAP50 是否低于 0.85低于这个值先优化检测模型。5.2 P2 层训练 loss 震荡不收敛现象加了 P2 检测头后训练前 20 轮 box_loss 上下震荡没有下降趋势。原因P2 层特征图分辨率高浅层权重初始化后梯度幅值大默认学习率 0.01 太大。另外 P2 层的正样本数量远多于 P3/P4损失被 P2 主导。解决学习率降到 0.005 甚至 0.003warmup_epochs 加到 5 到 8。如果还震荡检查数据集标注质量P2 层对小目标敏感标注框偏移几个像素就会产生大量低质量正样本。用model.train(..., close_mosaic20)在前 20 轮关闭 Mosaic 增强让 P2 分支先稳定下来。5.3 CPU 推理速度太慢一帧要 2 秒现象在 Ubuntu 20.04 CPU 环境下跑推理640x640 输入每帧耗时 1.5 到 2 秒完全达不到实时。原因YOLOv8n 在 CPU 上单帧推理大约 80 到 120 毫秒加了 P2 层后计算量增加约 40%到 150 毫秒左右。如果跑到 2 秒大概率是 PyTorch 没用 MKL 加速或者输入分辨率设成了 1280。解决确认torch.backends.mkldnn.is_available()返回 True。输入分辨率保持 640不要为了精度调到 1280。如果还是慢用 ONNX Runtime 导出推理CPU 上能快 2 到 3 倍。# 导出 ONNX 模型 model YOLO(runs/bee/p2_exp1/weights/best.pt) model.export(formatonnx, imgsz640, simplifyTrue, opset12) # ONNX Runtime 推理 import onnxruntime as ort session ort.InferenceSession(best.onnx, providers[CPUExecutionProvider]) # 输入需要预处理为 [1, 3, 640, 640] 的 float32 数组5.4 行为判定规则误报率高现象明明在蜂箱入口停留的守卫蜂被判定成「采蜜归巢」因为它的轨迹终点靠近蜂箱。原因只用了位置特征没有结合速度和方向。守卫蜂速度接近零采蜜蜂速度明显更高。另外蜂箱入口位置在不同视频里不一样硬编码坐标会翻车。解决行为判定至少用三个特征做与运算。采蜜归巢 平均速度大于阈值 AND 终点在蜂箱区域 AND 方向变化率小于阈值。蜂箱区域用第一帧手动标定或者用背景差分自动检测不要写死坐标。5.5 验证集指标很高但实际视频效果差现象model.val()输出 mAP50 达到 0.92但拿实际蜂箱视频跑漏检和误检都很明显。原因训练集和验证集来自同一段视频的相邻帧画面背景、光照、蜜蜂密度几乎一样验证集没有真正检验泛化能力。这是数据划分的经典错误。解决按视频片段划分数据集验证集用完全不同的时间段拍摄。如果只有一段视频用前半段做训练、后半段做验证中间留 10% 的帧做缓冲避免相邻帧信息泄漏。重新划分后再看 mAP通常会掉 5 到 10 个点这才是真实水平。6. 从轨迹到行为规则引擎与验证方法行为判定不需要上深度学习模型规则引擎在蜜蜂场景足够用而且可解释性强答辩时好讲。核心思路是把每只蜜蜂的轨迹特征映射到行为类别再用时间窗口做平滑避免单帧误判。我一般用滑动窗口做行为判定取最近 2 秒约 60 帧的轨迹片段计算窗口内的平均速度、方向变化率、与蜂箱入口的距离变化。三个特征分别设阈值组合判定行为类别。阈值不要拍脑袋定用标注好的行为片段做统计取类间区分度最大的值。def classify_behavior(features, hive_center, speed_thresh15.0, angle_thresh0.8): features: 滑动窗口内的轨迹特征字典 hive_center: 蜂箱入口中心坐标 (x, y) speed_thresh: 速度阈值像素/秒 angle_thresh: 方向变化率阈值弧度 speed features[mean_speed] angle_change features[mean_angle_change] end_dist np.sqrt((features[end_pos][0] - hive_center[0])**2 (features[end_pos][1] - hive_center[1])**2) start_dist np.sqrt((features[start_pos][0] - hive_center[0])**2 (features[start_pos][1] - hive_center[1])**2) if speed 3.0 and angle_change 0.3: return 守卫 if speed speed_thresh and angle_change angle_thresh and end_dist start_dist: return 归巢 if speed speed_thresh and angle_change angle_thresh and end_dist start_dist: return 外出 if angle_change 1.2 and speed 5.0: return 侦察 return 其他验证方法上我习惯抽 10 段 30 秒的视频人工标注每只蜜蜂的行为类别作为 ground truth然后跑规则引擎输出混淆矩阵。重点看「守卫」和「其他」的混淆这两个类别最容易混。如果守卫的召回率低于 0.7把速度阈值从 3.0 降到 2.0或者把角度变化阈值从 0.3 放宽到 0.5。规则引擎的边界在于它假设行为模式在窗口内稳定但蜜蜂的行为切换可能很快2 秒窗口可能跨越两种行为。解决办法是把窗口缩到 1 秒但特征统计噪声会变大。我的经验是 1.5 秒窗口加 0.5 秒步长兼顾稳定性和响应速度。这套参数在三个不同蜂箱的视频上验证过行为分类准确率在 78% 到 85% 之间对毕业设计来说够用了。如果要做产品化再考虑上时序分类模型但那是另一个话题了。希望帮到你。本文还有配套的精品资源点击获取