
简介面向智慧城市安防、目标检测与计算机视觉方向学习者这份PDF聚焦YOLOv11在高密度人群异常行为检测中的优化策略系统讲解YOLO系列演进、网络结构、原理并深入分析高密度场景下的目标遮挡、复杂背景、实时性等挑战随后围绕多特征融合、注意力机制、数据增强、损失函数优化、模型融合与集成五大方向给出改进方案附PyTorch、OpenCV、Scikit-learn代码示例在商场、车站、广场等典型场景中完成实验对比与分析覆盖从理论、代码到实验验证的完整链路。资源共1个pdf文件大小1.9MB共30页目录支持章节跳转和大纲快速定位便于按需查阅已有62人学习下载适合正在做智慧城市安防、异常行为检测或YOLO系列应用研究的读者获取完整技术脉络与可落地思路。1. 高密度人群异常行为检测YOLOv11 为什么不能直接用默认配置地铁换乘大厅、景区检票口、大型活动散场通道这些监控画面在安防项目里是最容易让算法翻车的场景人贴着人远处的行人只有十几个像素互相遮挡严重而异常行为往往发生在最拥挤的那一瞬间。标题里这份《智慧城市安防YOLOv11高密度人群异常行为检测算法优化策略.pdf》讲的方向就是用 YOLOv11 做底把检测、跟踪、行为判定这一整条链路在高密度人群上调到能用。直接拿默认权重和默认训练参数跑这种画面mAP 会明显下滑这篇笔记按我的实践顺序把难点评估、数据、模型、训练和部署这几个环节讲清楚新手能照着跑通熟手直接看参数和踩坑。2. 高密度人群检测难点评估先把默认权重翻一次车再谈优化很多人拿到 YOLOv11 第一件事是换模型、加模块我建议先别急。高密度人群场景的问题不是模型不够新而是目标尺度、遮挡程度和分布密度完全超出 COCO 预训练分布的覆盖范围。花一个晚上把基线跑出来把漏检和误检的具体形态记下来再决定优化方向比直接改结构高效得多。2.1 遮挡、小目标与密度不均高密度人群的三个硬伤高密度人群场景和常规行人检测最大的差别在于“目标之间的相互干扰”成了主导问题。先说遮挡人挨着人的时候检测框大量重叠模型在训练时看到的是被截断的人体推理时又要从被遮住的身体边缘里找回完整目标框回归的噪声会被放大。再说小目标一台 1080P 的相机覆盖一个 20 米宽的通道离镜头 30 米外的人可能只有 20 乘 40 像素经过 YOLOv11 下采样之后在深层特征图上就剩几个像素点特征几乎被背景信息淹没。第三是密度不均画面里某个区域人挤人其他区域完全空旷稀疏区域的负样本和密集区域的正样本在损失函数里互相拉扯模型很难同时学好。这种情况下的异常行为检测通常不是靠单帧识别“打架”“跌倒”这种语义就能完成的。常见做法是两级结构先用 YOLOv11 把画面里所有人检测出来再做跟踪最后用轨迹、速度、驻留时间、跨线等规则或时序分类器判断行为是否异常。所以检测这一级的召回率直接决定了行为判定的上限检不出来的人根本进入不了下一级。这也是为什么在优化策略里“先保住召回率”比“提高框的精确度”优先级更高。2.2 先跑通 baseline用 yolo11m 对重点区域视频做一次推理ultralytics 环境配置其实没有什么玄学Python 3.10 或 3.11装好 GPU 版 PyTorch再pip install ultralytics就可以了。权重文件不用手动找首次加载会自动下载。有个小坑官方模型名是yolo11m.pt不是yolov11m.pt拼错会一直报下载失败。纯小白最稳妥的顺序是先跑通预测再碰训练不然环境问题、权重问题和代码问题会混在一起根本定位不了。# 推理视频并保存结果对应“yolov11 保存推理结果”这个诉求 from ultralytics import YOLO model YOLO(yolo11m.pt) # 首次运行会自动下载预训练权重 results model.predict( sourcedemo/station_peak.mp4, conf0.15, # 高密度场景低阈值先把召回保下来 iou0.45, # IoU 阈值适当调低保留相互遮挡的相邻框 imgsz1280, # 提高输入分辨率别让远处小目标直接被压没 saveTrue, # 保存带检测框的视频肉眼看翻车现场 save_txtTrue, # 同时输出 txt 格式结果后面统计指标用 )这几个参数在高密度场景下都有具体含义conf0.15是故意让模型“多检”宁可出一批误检也要先看漏检长什么样iou0.45是为了让两个重叠的行人框都能留下来默认的 0.6 以上很容易把挨着的人合并成一个框imgsz1280能明显提升小目标的检出代价是显存占用翻倍。如果显卡显存只有 8G可以把imgsz降到 1024但低于 960 的话小目标基本就没救了。2.3 第一次微调与指标解读mAP、召回率分别看什么跑完推理你会看到两类典型问题一是人群密集区漏检成片二是单人重复框。这时候再开始第一次微调目标不是直接达到最终效果而是拿到一组干净的基线指标。数据配置文件用一个 YAML 指向自己的数据集目录和类别定义然后命令行直接开训。# 第一次微调对应“yolov11 训练自己的模型” yolo detect train \ modelyolo11m.pt \ data/data/dense_crowd.yaml \ epochs100 \ imgsz1280 \ batch8 \ cos_lrTrue \ patience20 \ ampTrue以 24G 显存为例imgsz1280时batch8是比较稳的起点。patience20表示连续 20 个 epoch 没提升就提前停密集人群数据量通常不大100 个 epoch 足够收敛。训完看两张图results.png里的 mAP 曲线和验证集上的召回率。高密度场景下 mAP0.5 和 mAP0.5:0.95 的差距会比常规场景大不少因为遮挡导致框回归精度上不去如果 mAP0.5 过了 0.7 但 mAP0.5:0.95 还在 0.4 以下说明漏检已经不是主要矛盾框的定位精度才是。3. 数据侧优化密集人群数据集的筛选、标注校正与增强参数模型结构再有新意数据不对也是白搭。高密度人群项目里数据侧的工作量通常占整个优化周期的一半以上而且这部分做的越扎实后面模型侧和训练侧的改动越省事。3.1 数据从哪里来公开人群数据集与自采视频的组合策略常见的做法是先拿公开的密集人群数据集做预训练再拿项目现场自采视频做微调。公开数据侧重在提供“遮挡的多样性”像人群密集的行人道、地铁车厢这类画面能帮模型学到人被挡住一半时的特征自采视频则负责“场景一致性”画面角度、相机高度、光线条件都要贴近实际部署点位。只靠公开数据集的问题在于场景偏差太大模型在公开集上指标不错一到现场就掉点只靠自采数据的问题在于密集样本收集慢而且单一场地容易过拟合。我一般会把数据按密度分层每帧画面里超过 20 人的算高密度5 到 20 人的算中密度少于 5 人的算低密度。训练时三个密度段都保留但高密度段优先扩量比例控制在 5:3:2 左右。如果高密度段样本太少模型很容易被中低密度样本带偏到了真正拥挤的闸口又恢复成漏检一片。3.2 标注质量检查把拖后腿的遮挡框提前找出来密集人群的标注质量比数量更重要。常见问题是标注员把相互遮挡的两个人框得过大一个框同时套住两个人或者只标了露出来的上半身下半身被挡住的部分直接不标。这两种标注都会给模型传递错误信息。与其靠肉眼一张张翻图不如写个小脚本自动扫一遍所有标注。# 检查 YOLO 格式标注中的两个典型问题过小目标和高度重叠框 from pathlib import Path def iou(a, b): ax1, ay1, ax2, ay2 a bx1, by1, bx2, by2 b ix1, iy1 max(ax1, bx1), max(ay1, by1) ix2, iy2 min(ax2, bx2), min(ay2, by2) iw, ih max(0, ix2 - ix1), max(0, iy2 - iy1) inter iw * ih area_a (ax2 - ax1) * (ay2 - ay1) area_b (bx2 - bx1) * (by2 - by1) return inter / (area_a area_b - inter 1e-6) def scan_labels(label_dir, img_w1920, img_h1080, overlap0.6, min_side32): for txt in sorted(Path(label_dir).glob(*.txt)): boxes [] for line in txt.read_text().strip().splitlines(): cid, xc, yc, w, h map(float, line.split()) x1 (xc - w / 2) * img_w y1 (yc - h / 2) * img_h x2 (xc w / 2) * img_w y2 (yc h / 2) * img_h boxes.append((cid, (x1, y1, x2, y2), w * img_w, h * img_h)) for i, (cid, box_i, wi, hi) in enumerate(boxes): if wi min_side or hi min_side: print(f{txt.name}: box{i} 像素尺寸 {wi:.0f}x{hi:.0f}疑似小目标漏标) for j in range(i 1, len(boxes)): if iou(box_i, boxes[j][1]) overlap: print(f{txt.name}: box{i} 与 box{j} IoU{iou(box_i, boxes[j][1]):.2f}需人工复核)这段代码做的事情很简单把 YOLO 格式的中心点坐标还原成像素坐标筛出宽或高小于 32 像素的目标再找出 IoU 超过 0.6 的框对。高密度画面里相邻行人 IoU 超过 0.6 是正常的但如果同一个文件名下大量出现这种告警就要重点看是不是标注员把一个人标成了两个框或者一个框罩住了两个人。3.3 增强参数马赛克、拼接与随机遮挡的搭配密集人群增强的核心不是“把图变花”而是模拟“重叠、遮挡、拥挤”的分布。ultralytics 内置的几个增强项参数配置比想象中敏感下面这组是我在密集人群项目上的起点。增强项推荐初始值作用与注意点mosaic1.0四张图拼一张变相增加人群密度前 10 个 epoch 之后建议关闭mixup0.2两张图叠加让模型学会区分重叠边界太高会让前景模糊hsv_h / hsv_s / hsv_v0.015 / 0.7 / 0.4模拟早中晚光线变化但色相变化别调太大避免肤色失真degrees0.0固定相机场景不要旋转画面里的行人是不会横着走的fliplr0.5水平翻转安全垂直翻转不要开close_mosaic这个参数特别重要它的作用是在训练的最后 10 个 epoch 自动关闭 mosaic 增强。原因是马赛克拼出来的图里很多目标被切在边缘模型在训练后期如果还在学这种残缺样本小目标的回归精度反而会变差。如果项目视频里有大量密集遮挡的瞬间我还会额外收集这些帧单独跑一次微调效果比调增强参数更直接。4. 模型侧优化从 HCANet 思路到损失函数的改动数据补齐之后才开始动模型结构。YOLOv11 本身在通用目标检测上已经做得很均衡但高密度人群这类任务有两个特殊需求一是特征图需要保留更多细粒度信息二是模型要对相互遮挡的目标有更强的区分能力。最近确实能看到把 HCANet 这类混合注意力结构与 YOLOv11 结合的工作核心思路就是把卷积分支的局部特征和注意力分支的全局上下文互补起来。下面按我的顺序讲三个可改的位置。4.1 YOLOv11 网络结构上可以动的三个位置先明确一点不建议上来就换 backbone。YOLOv11 的网络结构图网上到处都能搜到backbone 底部那几层负责边缘和纹理Neck 部分做多尺度融合Detect 头输出三个尺度的预测。在高密度人群场景里我一般只动三个位置backbone 最后一层之后插入一个轻量注意力模块让特征图在进入 Neck 前增强行人显著区域Neck 的 P3 小目标分支上调权重因为高密度画面里大量目标集中在 P3 这一级Detect 头不动改动头部的风险最高收益却不一定明显。在讲注意力模块之前先说一下超参搜索的问题。有些团队会用粒子群优化、哈里斯鹰优化这类元启发式算法去自动搜结构参数或训练超参白鲸优化这类新算法在社区里讨论也挺多。我的看法是线性调参解决不了的问题换搜索算法也大概率解决不了元启发式算法适合在已经有成熟基线、只想再榨 1 到 2 个点的时候用不适合作为前期探索手段。4.2 借鉴 HCANet 思路的轻量注意力模块实现与参数量对比HCANet 这类混合注意力结构的核心是“卷积与注意力互补”卷积负责局部纹理通道注意力与空间注意力负责让模型更关注“哪里有人、哪些通道对人更重要”。这里给出一个最小的混合注意力模块参数很少可以直接插在 YOLOv11 的 C3k2 层后面。# 借鉴 HCANet 思路的最小混合注意力模块适合插入 YOLOv11 Backbone 尾部 import torch import torch.nn as nn class HybridAttention(nn.Module): def __init__(self, channels, reduction8): super().__init__() # 通道注意力先池化再两段卷积计算每个通道的重要性 self.channel_att nn.Sequential( nn.AdaptiveAvgPool2d(1), nn.Conv2d(channels, channels // reduction, 1, biasFalse), nn.ReLU(inplaceTrue), nn.Conv2d(channels // reduction, channels, 1, biasFalse), nn.Sigmoid(), ) # 空间注意力用 7x7 卷积融合平均池化和最大池化特征 self.spatial_att nn.Sequential( nn.Conv2d(2, 1, kernel_size7, padding3, biasFalse), nn.Sigmoid(), ) def forward(self, x): c_weight self.channel_att(x) c_out x * c_weight # 通道维加权 avg_out torch.mean(c_out, dim1, keepdimTrue) max_out, _ torch.max(c_out, dim1, keepdimTrue) s_weight self.spatial_att(torch.cat([avg_out, max_out], dim1)) return c_out * s_weight # 空间维加权在 ultralytics 里接入自定义模块的常见做法是把这个类放到ultralytics/nn/modules/下新建的 py 文件里在__init__.py中导出再在任务解析文件里注册模块名最后改 yaml 结构。以输入通道 256 为例这个模块的参数量大约是256*32 32*256 2*7*7约一万六千多个参数对比主干网络动辄几百万的参数可以忽略不计但能让特征图在进入 Neck 前多一次“按重要度重标定”。4.3 损失函数与匹配策略稳住遮挡样本的梯度结构改动之后训练损失也要跟着调。YOLOv11 的损失由分类、框回归和 DFL 三部分构成高密度场景下最常见的问题是框回归损失被大量遮挡样本带偏。原因是遮挡目标的边界本身模糊模型在训练初期梯度波动很大如果回归权重配置过高模型会花大量精力去拟合那些“本来就不该精确”的遮挡边缘。我一般会做两件事一是把框回归损失权重稍微抬高让模型更重视可精确定位的非遮挡目标同时用后期close_mosaic保证小目标不被拼图切成碎块二是检查正负样本匹配如果密集区域大量目标没有被分配为正样本说明默认的 anchor 匹配策略在拥挤场景下淘汰率太高这时候优先降低匹配时的 IoU 门槛而不是加大损失权重。判断方法很简单训练到第 30 个 epoch 左右单独统计验证集上人群密度最高那部分图里的召回率如果明显低于平均水平优先回数据侧补样而不是继续调损失。5. 训练避坑密集人群下 YOLOv11 的 5 个常见问题与排查这章里的问题全部来自实操踩坑每条按“现象、原因、解决”展开按出现频率排序。如果你训练时遇到类似情况直接对照着排查。5.1 训练 Loss 不降先查学习率和标签匹配而不是换网络现象是 loss 曲线前 10 个 epoch 就不动了或者降到一半突然横盘。原因多半是学习率过大导致梯度震荡或者数据标签里混进了大量空白帧模型在无效学习。解决方法是把lr0从默认值降到 0.0005 左右同时确认数据配置里的路径指向真实存在标注的图片目录如果 loss 仍然不降再单独加载 validation 集检查标注可视化不要急着换网络结构。5.2 mAP0.5 高、mAP0.5:0.95 低边界框回归在密集人群上偷懒现象是训练日志里 mAP0.5 到了 0.75但 mAP0.5:0.95 只有 0.35 左右。原因是大量遮挡样本的边界框本身不确定模型学会了“框个大概齐”就能拿到 IoU 0.5 的分数对 0.95 这种严格指标完全无所谓。解决方向是把输入分辨率稳定在 1280 而不是训练后期降到 960并适当抬高框回归损失权重另外检查验证集里有没有大量低于 32 像素的小目标小目标天生在 IoU 0.75 以上拿不到分这不是训练问题是数据构成问题。5.3 人挨着人时 NMS 把两个框并成一个IoU 阈值设置与二次验证现象是推理画面上两个人被框成一个框或者一个框在两人之间来回跳。原因是推理时 NMS 的 IoU 阈值设置过高默认值 0.6 以上会把重叠严重的行人框合并。解决方法是推理时把 IoU 阈值降到 0.4 到 0.45同时把置信度阈值压到 0.2 以下先恢复召回如果这样导致单人重复框过多就在行为判定阶段加一个“同一目标跨帧去重”的逻辑而不是靠调高 NMS 阈值硬压。5.4 大图训练显存爆炸切图训练与拼接推理现象是imgsz1280一开24G 显存直接 OOM。原因是 batch size 太大而密集人群数据往往来自大分辨率相机原图在完整图上训练成本很高。解决方法是先把 batch 降到 4 或 2开启 AMP 混合精度如果还是不够就做切图训练把 1920x1080 的图切成四个 960x960 的 patch 分别训练和推理最后用 SAHI 这类切片推理库把结果拼回全图。注意切图时要让相邻 patch 保留 20% 重叠区域避免目标刚好被切在边缘。5.5 小目标召回率低imgsz、检测头与损失权重的组合调整现象是离镜头远的那批人始终检不出来放大画面能看到人但模型就是没反应。原因是小目标在深层特征图里本身只剩少量像素加上训练时被马赛克增强反复裁切模型对小目标的响应被进一步削弱。解决方法是保底方案训练和推理都用 1280 及以上分辨率结构方案在 Neck 的 P3 输出上强化小目标特征必要时插入一个轻量的注意力模块而不是增加网络深度。实测中这两步做完远端小目标的召回率通常会有明显改观但别指望恢复到近景水平物理极限摆在那里。6. 部署侧验证TensorRT 导出、NMS 调参与边缘设备帧率模型在 GPU 服务器上跑得再快也没有意义智慧城市安防项目最终要落在边缘设备上。常见配置是 NVIDIA Jetson 系列或工业级 GPU 盒子推理引擎用 TensorRT。高密度人群场景有个特殊点输入分辨率不能随便降否则小目标立刻消失所以帧率优化的核心不是缩小分辨率而是把引擎和预处理流程压到极致。TensorRT 导出本身很简单关键在导出后的精度校验。# 将训练好的权重导出为 TensorRT 引擎FP16 1280 输入 yolo export modelruns/detect/train/weights/best.pt \ formatengine \ halfTrue \ imgsz1280 \ device0导出后一定要用同一份验证集做一次精度对比不要想当然认为 FP16 不掉点。常见做法是记录导出前 PyTorch 模型的 mAP 和导出后引擎的 mAP如果 mAP0.5 掉了超过 0.5 个点优先确认是不是imgsz不一致或 NMS 参数没对齐其次再排查 TensorRT 的层融合问题。边缘设备上的帧率优化重点是 NMS 和高密度场景的配合。Jetson 这类设备 CPU 算力有限大批检测框的 NMS 会成为瓶颈我的习惯是把置信度阈值从训练时的 0.15 逐步上调测试找到一个“召回不掉点、误检可接受”的平衡点仍不够稳的情况下用切图推理拼回全图虽然总帧率下降但单帧召回率明显提高对安防告警类项目来说漏报比延迟更不可接受。我之前接过一个景区出入口的告警项目第一版只调了损失函数没动数据现场跑通后误报率一直压不下来回头补了两周的密集遮挡样本才稳住。从那以后我把“先数据、再结构、最后训练调参”当成固定顺序宁愿多花时间看漏检视频也不急着换网络。希望帮到你。本文还有配套的精品资源点击获取