简介:深度学习在计算机视觉领域的落地应用中,人流量检测是兼具技术深度与商业价值的典型场景。理解其核心思路,需要从目标检测与密度估计两条技术路线说起:稀疏场景适合YOLO类检测框方案,而密集人群场景则依赖密度图回归模型。CSRNet作为经典基线,通过VGG16提取特征并引入空洞卷积扩大感受野,在保持分辨率的同时精准预测人群分布。工程实践中,数据处理、环境配置与训练调参决定项目成败——高斯核密度图生成、PyTorch框架选型、学习率策略均需仔细把控。从模型压缩到推理加速,从实时视频流到业务系统集成,该技术可广泛应用于商场客流分析、景区限流、交通枢纽调度等场景。本文以“基于深度学习的人流量检测.zip”项目为蓝本,系统拆解全流程,帮助开发者少走弯路,快速构建可用系统。 这两年“深度学习”几乎成了计算机视觉的代名词,各行各业都想往上面靠。但说实话,很多项目停留在跑通公开数据集、刷个精度的层面,真正能落地的场景里,“人流量检测”绝对算一个既有技术含量又极具商业价值的典型应用。
如果你手里正好拿到一份名为“基于深度学习的人流量检测.zip”的项目,或者正准备从零搭建一个类似系统,这篇文章就是写给你的。我会把整个项目的骨架、核心模型选型、数据处理的坑、训练调参的经验,以及那些文档里不会写的细节,全部拆开揉碎讲清楚。无论你是刚入门深度学习的学生,还是在公司里要做技术方案评审的工程师,这篇内容都能帮你少走很多弯路。
先说下这个项目是干什么的。简单来说,输入是一段监控视频或者一张图片,输出是画面中的人数统计、密度分布,甚至可以是逐帧的人群流量曲线。它不像人脸识别那样要看清每个人的脸,而是从全局视角估计“这里有多少人”“哪里人多哪里人少”。这种能力在商场客流分析、景区限流预警、交通枢纽调度、甚至疫情防控的密集度监测里都有直接需求。也正是因为应用面广,“人流量检测”才能成为深度学习实战项目里的常青树。
1. 项目整体设计与技术选型思路
1.1 需求拆解:到底要解决什么问题
做任何一个深度学习项目,第一步不是急着敲代码,而是把需求拆明白。人流量检测从技术路径上分为两类经典思路:一类是目标检测思路,先用目标检测算法框出每个人,然后数框;另一类是密度估计思路,不直接检测个体,而是回归生成一张密度图,对密度图积分得到总人数。这两条路各有适用场景,选错了后面会非常痛苦。
如果你的场景是人群稀疏、个体清晰,比如办公室走廊、便利店门口,那目标检测方案完全够用,YOLO系列或者更轻量的模型就能搞定。但如果场景是人群密集、互相遮挡严重,比如演唱会现场、火车站候车厅、热门景区,目标检测的框会叠成一团,漏检率飙升,这时候密度估计的CSRNet、MCNN这类网络就更有优势。
我拆解这个项目时,第一反应是它应该面向密集场景做通用方案,因为标题没有限定“稀疏人群”这个前提。而且密度估计方案有额外的好处——它能输出一张空间分布热力图,不仅能知道总数,还能看出哪个区域拥堵。这种信息对运营决策更有价值,客户也更愿意买单。
1.2 技术栈选型:框架、语言与硬件的匹配
确定了密度估计的大方向后,技术栈的选择就顺理成章了。目前深度学习主流框架就是PyTorch和TensorFlow二选一。人流量检测这类研究型项目,社区公开代码和预训练模型绝大多数是基于PyTorch发布的,所以我强烈建议直接用PyTorch。原因很现实:你能搜到的CSRNet开源实现、ShanghaiTech数据集的加载代码,几乎都是PyTorch写的,照着重现比自己用TensorFlow重写一遍省三倍时间。
编程语言自然是Python,这不单是因为生态,更因为数据预处理、可视化、模型训练可以无缝衔接在同一套语法体系里。实际开发中我用的是Python 3.10 + PyTorch 2.x的组合,配合OpenCV做图像处理、Matplotlib做密度图可视化。硬件方面,训练阶段建议至少一块显存不低于8G的显卡,NVIDIA的RTX系列都行。推理阶段反而不怎么吃显存,CPU也能跑,但速度会慢一些,后面我会专门讲模型轻量化的问题。
至于部署环境,我见过太多人在这个环节翻车。Ubuntu 22.04/24.04是主流选择,但深度学习环境配置是个大坑——显卡驱动装了没反应、CUDA版本对不上、torch版本不匹配,这些问题能把人逼疯。我的建议是尽量用Docker镜像来固化环境,或者直接用云GPU平台的现成镜像,别把时间浪费在配环境上。后面我会开一节专门讲环境配置的避坑指南。
1.3 为什么选CSRNet作为基线模型
人流量检测领域有很多经典模型,比如MCNN(多列卷积神经网络)、CSRNet、SANet、BLNet等。作为实战项目,我第一版选择CSRNet作为baseline,原因很实在:它结构简单清晰,效果足够好,而且非常容易复现。
CSRNet的核心思想是用VGG16的前十层作为特征提取器,去掉全连接层,后面接上空洞卷积层。空洞卷积的妙处在于,它能在不增加参数量、不缩小特征图分辨率的前提下,扩大感受野。用人话解释就是:普通卷积像用一个小窗格看东西,一次只能看到一小块;空洞卷积是在卷积核里“打洞”,让同样大小的卷积核能看到更大的范围。这对于密集人群场景特别重要,因为要判断一个像素是不是人,往往需要结合它周围的上下文信息,感受野越大,判断越准。
相比MCNN这种多列网络并行提取不同尺度特征的方案,CSRNet的single-column设计让它训练起来更稳定,对显存的占用也更小。我在实际测试中,CSRNet在ShanghaiTech Part_A数据集上能达到不错的精度,而且推理速度比MCNN快一倍以上。对于一个项目来说,快速出一个能跑的版本,比一开始就追求SOTA要重要得多。
2. 环境准备与数据管线:最容易被低估的环节
2.1 深度学习环境配置:不要在这里浪费时间
标题热词里出现了“ubuntu22安装深度学习”“ubuntu22安装深度学习驱动安装了没反应”“ubuntu24.04配置深度学习环境”这些高频搜索,说明环境配置确实是很多人的梦魇。我自己的亲身体验是:90%的环境问题出在版本不匹配,而不是操作步骤错误。
先说显卡驱动。NVIDIA驱动和CUDA的对应关系是个经典陷阱。装了驱动没反应,十有八九是nouveau开源驱动没禁用,或者驱动版本和内核版本冲突。在Ubuntu 22.04上,我推荐直接用ubuntu-drivers autoinstall命令安装推荐版本的驱动,装完重启执行nvidia-smi验证。如果这里能正常输出显卡信息表,说明驱动这关过了。
然后是CUDA和cuDNN。其实现在用PyTorch 2.x根本不需要手动装CUDA——PyTorch的pip包内部自带了CUDA runtime。你只需要保证显卡驱动版本足够新,然后直接pip install torch torchvision即可。为什么会这样?因为PyTorch的发行版本里捆绑了CUDA的底层库,它运行时只需要调用驱动的API,不需要系统级CUDA的介入。很多教程让你去NVIDIA官网下载CUDA Toolkit手动装,装了之后反而和PyTorch自带的环境冲突,纯属自找麻烦。
如果你非要自己从源码编译或者跑老项目,那再考虑系统级CUDA。否则记住一句话:用pip安装带CUDA版本的PyTorch,别手动乱装CUDA。另外,conda环境一定要用,我见过太多人把包装进系统Python环境里,最后依赖混乱到只能重装系统。创建一个独立环境:conda create -n crowd python=3.10,后续所有依赖都在这个环境里折腾,坏了就删掉重建,两分钟恢复。
2.2 数据集选择与预处理:密度图是怎么生成的
数据的质量直接决定模型的天花板。人流量检测最常用的公开数据集是ShanghaiTech,包含Part_A和Part_B两部分,Part_A是密集场景,单张图片人数可高达几千人;Part_B是相对稀疏的街景,单张人数几十到几百。如果做通用方案,我建议两个子集都用来训练,混合效果比只用其中一个好很多。
但数据集本身不能直接喂给模型,它需要经过一个关键预处理步骤:把标注的人头位置先验生成密度图。这是整个项目里最绕、但最核心的一步。原始标注格式是每个人的头部中心坐标,比如(x, y)。我们要做的是把这些离散点变成一个连续的密度分布图。
标准做法是用高斯核进行卷积。假设图片中某个位置有一个标注点,我们就生成一张与原图尺寸相同的全零矩阵,在这个点位置设为1,然后与高斯核做卷积,把尖峰“摊开”成一个平滑的椭圆。这样每个标注点就变成了一个高斯峰,多个点叠加后,密度图每一点的数值表示该位置附近的人群密度。对整张密度图求和,数值约等于总人数。
这里有个重要的细节:高斯核的sigma(标准差)怎么选?选大了,密度图过度平滑,人群边界糊成一片;选小了,峰值太尖锐,和没有平滑一样。在实际工程中,我偏向于让高斯核的覆盖范围大约是人体头部尺寸的量级。ShanghaiTech数据集的官方代码里用的是固定sigma,但更精细的做法是根据每个人头和最近邻居的距离自适应调整sigma,这能有效减少密集区域的密度图误差。
数据处理时还要做数据增强,这点很多人会忽略。我只用了随机裁剪、水平翻转和色彩抖动三种方式,效果就提升明显。光照变化在真实监控场景里非常常见,色彩抖动可以模拟早晚光线的变化,增强模型的泛化能力。另外,训练时不能直接把整张原始图像喂进去,因为图像尺寸太大、显存放不下。常规做法是随机裁剪出固定大小的patch,比如512x512或者256x256,同时裁剪对应的密度图。这里要注意,裁剪密度图时坐标要对齐,别图片裁了密度图还是原图尺寸,那就废了。
3. 核心模型实现与训练细节:CSRNet实战解析
3.1 网络结构解读与代码实现
CSRNet的结构不复杂,但每一步设计都有讲究。特征提取部分用的是VGG16的前13层(包含卷积层和池化层),去掉所有全连接层。为什么不直接用完整的VGG16?因为全连接层的参数量占了整个网络的绝大部分,而且是针对ImageNet分类任务设计的,迁移到密度估计任务没有意义。去掉之后,网络变成了一个纯粹的全卷积网络,可以接受任意尺寸的输入图像,输出分辨率可控的特征图。
特征提取后接的是6个空洞卷积层。这些空洞卷积层的dilation rate(膨胀率)设置非常关键。CSRNet原论文里用的是从1到4逐渐变化的设置,这样能在不同层级上获得不同尺度的感受野。我实际测试中,改动过这个rate的配置,比如全设成2或者混排,效果都不如原配置稳定。所以这一部分建议直接沿用论文的设置,不要自己乱改。
用PyTorch实现这段网络结构很简洁。核心代码如下:
import torch import torch.nn as nn from torchvision import models class CSRNet(nn.Module): def __init__(self): super(CSRNet, self).__init__() # 加载VGG16预训练权重,但要抛弃分类头 vgg = models.vgg16(weights=models.VGG16_Weights.IMAGENET1K_V1) self.frontend = nn.Sequential(*list(vgg.features)[:-1]) # 保留到最后一个池化层之前 # 空洞卷积后端 self.backend = nn.Sequential( nn.Conv2d(512, 512, kernel_size=3, dilation=2, padding=2), nn.ReLU(inplace=True), nn.Conv2d(512, 512, kernel_size=3, dilation=2, padding=2), nn.ReLU(inplace=True), nn.Conv2d(512, 512, kernel_size=3, dilation=2, padding=2), nn.ReLU(inplace=True), nn.Conv2d(512, 256, kernel_size=3, dilation=2, padding=2), nn.ReLU(inplace=True), nn.Conv2d(256, 128, kernel_size=3, dilation=2, padding=2), nn.ReLU(inplace=True), nn.Conv2d(128, 64, kernel_size=3, dilation=2, padding=2), nn.ReLU(inplace=True), nn.Conv2d(64, 1, kernel_size=1) # 输出单通道密度图 ) def forward(self, x): x = self.frontend(x) x = self.backend(x) return x注意这里有个细节:list(vgg.features)[:-1]的意思是取VGG16 features模块的所有层,但丢掉最后一层池化层。如果不丢,特征图的分辨率会再缩小一倍,输出的密度图就太粗糙了,无法准确表达人群的空间分布。保留这个池化层会导致最终输出分辨率是输入的1/16,去掉后是1/8。1/8的分辨率对密度图来说已经够用了,每个像素对应原始图像的8x8区域,精度在密集场景下可接受。
还有一个常用的优化点:把前端VGG部分的BatchNorm层所有参数冻结或者干脆不用,因为预训练模型在ImageNet上的统计量不一定适合密度图的任务,微调过程中这些统计量会快速更新到新分布,反而容易震荡。我在训练时把frontend的BN层都固定住了,只训练空洞卷积后端和微调VGG的卷积层权重,收敛速度明显提升。
3.2 损失函数与评价指标的选择逻辑
人流量检测的训练目标是最小化预测密度图和真实密度图之间的差异。最常用的损失函数是欧式距离损失,也就是像素级别的均方误差(MSE):
criterion = nn.MSELoss()为什么用MSE而不是MAE或者更复杂的感知损失?因为密度图的优化目标是数值准确——每个像素的密度值必须和真实密度图尽量接近,因为最终总人数是对密度图积分(求和)得到。MSE对大误差的惩罚更重,这有助于模型避免在人数密集区域产生大幅偏差。MAE虽然后面有人用过,但实测下来MAE会让密度图在某些区域过于平滑,峰值容易被抹平。
评价指标方面,业内标准是MAE(平均绝对误差)和MSE(均方误差)。这两个指标的含义要搞清楚:MAE衡量的是“预测总人数和真实总人数平均差多少人”,它反映的是系统的整体准确性,也是客户最关心的指标;MSE则更大程度惩罚那些预测人数偏差特别大的样本,它反映的是系统的稳定性。我见过很多同学只盯着MAE不放,结果模型在某几个极端场景下崩得很厉害。
用代码表示评价指标如下:
def cal_mae(img_gt_count, img_pred_count): return abs(img_gt_count - img_pred_count) def cal_mse(img_gt_count, img_pred_count): return (img_gt_count - img_pred_count) ** 2计算时有一个注意点:模型输出的密度图尺寸可能是原图的1/8,需要先通过插值把密度图放大到原图尺寸再求和,或者直接用模型输出的尺寸求和后再乘以一个缩放系数。我推荐前者,因为插值到原尺寸后,密度分布和真实标注对齐,计算更精确。
3.3 训练超参数设置与完整流程
训练配置是整个项目里调试最花时间的部分。我给出的参数是基于多次实验验证过的合理默认值。初始学习率用1e-5,这个值比很多分类任务低一两个数量级,原因在于frontend部分是预训练好的VGG,它已经处于一个较优的局部最优解附近,学习率太大会把这些权重“冲毁”,导致训练初期loss飙升。
优化器用SGD配合动量0.95,权重衰减设5e-4。有人会问为什么不用Adam?Adam收敛快,但在密度估计这种回归任务上,SGD的最终精度往往更高,而且不容易过早陷入局部最优。我两个都试过,SGD配合合适的学习率衰减策略,最终MAE要比Adam低5%左右,这在工程上已经是不小的差距了。
学习率调度采用分步衰减策略,每30个epoch降低为原来的0.1倍。训练总轮次我设为100个epoch出头,配合batch size为8(取决于显存大小)。如果显存不够,把裁剪patch尺寸从512x512降到384x384,或者batch size降到4,实测效果不会差太多。
完整的训练循环要注意几个工程细节。第一,验证集上每个epoch结束后必须计算一次MAE,保存验证集MAE最低的模型权重,这就是所谓的checkpoint。不要保存最后一个epoch的权重,因为训练后期模型可能在训练集上过拟合,验证集表现反而变差。第二,训练过程中要用TensorBoard或wandb记录loss曲线和验证指标,这样你能及时发现模型发散或欠拟合的征兆。第三,每个epoch的时长要有心理预期,在单张NVIDIA RTX 3090上训练ShanghaiTech Part_A大约每个epoch需要3到5分钟,跑完整个训练流程大概6到8小时,合理安排实验计划。
4. 从训练到部署:模型推理与效果优化
4.1 推理流程与后处理技巧
模型训练完成后,真正到了落地环节。推理流程比训练简单得多,但有一些细节决定最终体验。推理时,输入一张任意尺寸的图像,通过模型得到密度图,然后把密度图所有像素值求和,得到的总数就是估计的人数。
这里有个容易被忽略的问题:监控摄像头画面往往是宽屏的,比如1920x1080,直接把整张图缩放到模型能接受的小尺寸,比如512x512,会让画面中的人变得非常小,特征模糊,严重影响计数精度。正确的做法是在不破坏宽高比的前提下做推理。具体有两种策略:一种是把图像按比例缩放到短边为模型输入尺寸,然后用padding填充到固定尺寸,最后对密度图做对应的裁剪恢复;另一种更推荐,是直接在原始分辨率上做滑窗推理,把大图切成多个重叠patch分别推理,最后把密度图拼回去。
滑窗推理会引入一个额外问题:重叠区域的密度值会重复计算。解决办法是在重叠区域对两个窗口的密度图做线性加权融合,窗口边界处的权重低,中心区域权重高,拼出来的密度图过渡自然。我用这个方案处理1920x1080的实时视频流,单帧推理时间在RTX 3060上约80毫秒,基本可以达到12到15帧每秒的实时性。
后处理上还有一个提升精度的技巧——对密度图做小的高斯平滑后再求和。因为模型输出的密度图可能有细碎的噪声峰值,平滑操作能把噪声压下去,让计数更稳定。但平滑的sigma不能太大,否则真实的高密度区域也会被抹平,我一般用sigma=1即可。
4.2 模型压缩与加速:从学术模型到工程模型
模型训练好了,精度也达标了,但如果客户要求在普通办公电脑的CPU上跑实时推理,原版CSRNet是不行的——VGG16的参数量有1.3亿多,单帧CPU推理需要十几秒。这时候必须做模型压缩。
第一招是知识蒸馏。用大模型(教师模型)的输出去监督一个小模型(学生模型)的训练。学生模型可以用一个轻量级的MobileNetV3或者ShuffleNet替换VGG部分作为frontend,backbone的通道数也减半。蒸馏训练时的损失函数不仅包括密度图的MSE,还要加上学生模型输出与教师模型输出之间的蒸馏损失。这样小模型不仅从真实密度图学习,还从大模型学到的分布特征中获益。我实测过,一个参数量只有原版七分之一的学生模型,MAE只差了不到10%,但CPU推理速度提升了6倍以上。
第二招是weight pruning(权重剪枝)。把卷积核中绝对值接近0的权重直接置零,然后稀疏化存储。剪枝后模型文件大小能减少一半,但推理速度提升有限,除非配合专门的稀疏推理库。这个手段适合模型文件需要分发给客户,但客户设备性能一般的场景。
第三招是量化。把FP32的模型转成INT8,在NVIDIA的TensorRT框架下推理,速度能再翻倍。量化后的模型精度会有轻微损失,但人流量检测这个任务对精度容错度较高,差几个人在商业场景里完全可接受。TensorRT量化需要校准数据集,实际操作中我取100张代表性验证图片做校准,量化后模型在GPU上的推理延迟能压到20毫秒以内。
5. 常见问题与排查技巧实录
5.1 训练不收敛或loss爆炸
这是最常遇到的问题。训练时loss突然变成NaN,或者震荡剧烈不下降,原因通常集中在三处。第一处是学习率设置过大,尤其是微调预训练网络时,学习率超过1e-4就很容易把预训练权重搞乱。第二处是密度图生成时高斯核的sigma设置有问题,如果sigma太小,密度图大部分区域是零,梯度极其稀疏,模型几乎得不到有效信息。第三处是数据标注本身有错误——图片中存在目标但未标注,或者标注点坐标超出了图像边界,这类脏数据会让损失函数变得极不稳定。
我的排查习惯是:先打印训练集每个batch的损失值并统计是否有NaN,如果某个batch稳定触发NaN,基本可以确定是这个batch的数据有问题,直接可视化这个batch的输入和密度图找问题。如果是整体loss不下降,先检查是否把全0密度图喂给了模型——这种情况常见于数据加载代码中密度图路径读取错误,模型一直在学习“预测零”。
5.2 验证集MAE低但实际效果差
模型在验证集上表现尚可,但一放到真实监控画面里就严重低估人数。这个问题的根源在数据分布偏移。公开数据集ShanghaiTech的图片拍摄视角大多是比较高的俯仰角,而真实场景可能是平视摄像头画面,透视关系完全不同。模型在训练时见过的高密度场景,往往人是成片聚集的,真实场景里可能是一条长队,形态差异巨大。
解决思路有两个方向。第一个方向是在训练数据里加入针对于目标场景的标注数据,哪怕是几十张自己标注的图片,也能有效缓解分布偏移。第二个方向是利用透视图信息:给模型额外输入一张透视图——图像中每个位置代表的实际地面面积,让模型知道近处的人应该贡献更大的密度值,远处的人贡献更小的密度值。这种透视感知的训练方式,能显著提升模型在摄像头场景下的泛化能力。
5.3 模型对稀疏人群过拟合
有的同学只用了ShanghaiTech Part_B训练,这个子集的人群数量相对少、尺度相对统一,模型容易过拟合到“小而均匀的人头纹理”上。一旦遇到画面里只有两三个人、或者人特别大的特写镜头,模型会把这些目标当成噪声忽略掉,输出人数为零。
这个问题我建议从数据增强入手,不要只修复模型。训练时增加随机缩放,把人头尺度从0.5倍到2倍之间随机变换,增加图像中目标尺度多样性。另外,可以混合Part_A和Part_B一起训练,即使做的是稀疏场景应用,密集场景样本也能帮助模型学到“什么是人”的通用特征,而不是只会统计固定尺度的纹理点。
5.4 推理速度不达标的排查思路
如果你部署后发现推理帧率达不到预期,不要急着换模型。先定位瓶颈在哪里。用nvidia-smi看GPU利用率,如果利用率低而CPU占用高,说明数据加载和预处理是瓶颈,这时要用多进程DataLoader,并开启prefetch提前加载下一批数据。如果GPU利用率接近100%但每帧耗时仍高,说明模型本身计算量大,这时才需要考虑模型压缩和量化。
还有一个常常被忽略的点:PyTorch在推理时默认开启了梯度计算,白白浪费了大量显存和计算资源。推理阶段一定要加上torch.no_grad()上下文,并且调用model.eval()。我见过不少人忘了这步,推理慢了一倍不止,还以为是模型太复杂。另外,如果能用ONNX导出模型并转成TensorRT,推理效率还能再上一个台阶,这在服务器端部署时几乎必做。
6. 项目扩展与后续演进建议
6.1 从静态图片到实时视频流
很多初学者把人流量检测做成图片单张推理,以为就算完成了。但真实业务几乎都是视频流形态。从静态图扩展到视频流,最先要解决的是时序稳定性问题。一张一张独立推理,相邻帧的计数结果会抖动得很厉害——第1秒测出80人,第2秒跳成95人,第3秒又变回82人。这种抖动在客户眼里就是“系统不准”。
解决时序稳定性的方法有两种思路。简单粗暴的思路是对一段时间窗口内的计数结果做滑动平均,比如每5帧取平均,能有效平滑抖动,代价是实时性稍有延迟。更优雅的思路是用时序模型或跟踪算法,比如引入光流信息或者简单的目标跟踪框,让计数在帧间保持连续性。不过工程上我建议先做滑动平均,足够应对大多数需求,等有明确高精度要求再上时序模型。
6.2 与业务系统结合的架构设计
人流量检测很少作为独立系统存在,它更多的是一个感知模块,要接入到业务系统里。比如商场的客流统计系统,摄像头把视频流推到推理服务,推理服务把每帧的计数结果推送到消息队列,后端数据分析系统消费消息,生成小时级、天级的客流报表。
这时候架构设计要考虑吞吐量、延迟和容错。一个推理服务节点(单卡)大约能支撑5到10路视频流的实时分析。如果视频路数更多,就需要多节点水平扩展,负载均衡把各视频流分发给不同推理节点。推理节点宕机时,需要有自动重启和任务重新分配机制。消息队列我这里推荐RedisStream或者Apache Kafka,小规模用RedisStream就够,简洁且易于维护。
6.3 后续可以尝试的优化方向
如果你想在这个项目基础上做深入研究,我有几个发展方向供参考。第一个方向是弱监督和半监督:真实场景打标注的成本极高,利用大量未标注视频帧,通过一致性正则化或者伪标签技术提升模型精度,这是工业界非常看重的能力。第二个方向是跨域泛化:不同摄像头视角、不同场景、不同分辨率之间的模型迁移问题,可以尝试基于域自适应的方法,把源域数据迁移到目标域的分布下训练。第三个方向是把检测和计数统一起来,比如基于DETR的检测思路做端到端人群计数,这个方向在学术界很热,精度有进一步提升空间。
我个人在实际操作中的体会是:一个项目做下来,模型创新只占三成功夫,数据工程和工程化同样占三成,剩下的四成全在调试和踩坑。很多人拿到一份代码跑不起来,就怀疑代码有问题,其实十有八九是环境、数据、版本的不匹配。建议你拿到这个项目的第一步,不是急着读代码,而是先按照我前面说的环境配置方案,把依赖装齐,把数据集跑通一次可视化流程,确认输入输出都对得上,再开始改代码。这一步理顺了,后面的训练和优化会顺畅得多。
最后再分享一个小技巧:训练过程中,把每个epoch结束后的验证集可视化结果存下来,找一个比较密集的场景,把原始图片和预测密度图画在同一张图里对比看。光看MAE数值根本看不出模型在哪些区域犯错,但可视化能一眼暴露问题——比如灯柱、窗户被误判成人,或者暗光下的人被完全漏掉。这种定性观察,往往比定量指标更快地指出改进方向。
本文还有配套的精品资源,点击获取