简介:面向红外场景下车辆与行人检测的YOLOv7解决方案,采用PyTorch框架,包含训练好的权重、数据集与配套代码,适合目标检测研究者、算法工程师及需要快速落地红外检测的开发者。模型基于数千张红外图像训练,输入尺寸640×640,mAP达到90%以上,检测目标为car与person,数据集标签提供txt和xml两种格式,便于分别用于YOLO与VOC训练流程。压缩包共166个文件,涵盖Python脚本、yaml配置、Jupyter Notebook演示、pt权重、txt/xml标签、jpg/png图像等,整体约444.56MB,并附Dockerfile与shell脚本,便于环境搭建与运行。已有1268人学习。除了可直接使用的权重,还包含PR曲线、loss曲线等训练过程记录,以及TensorRT与ONNX Runtime相关notebook和配套博客说明,方便复现实验、结果分析或迁移到自有红外数据继续训练,无论用于算法学习、论文实验还是工程预研,都有直接参考价值,可作为红外目标检测项目的起点。 红外场景下的目标检测这两年问的人越来越多。原因很直接:普通摄像头一到晚上就成了半个瞎子,而红外成像完全不依赖可见光,夜里、雾天、强逆光都能稳定输出画面。可问题也随之而来——拿现成的YOLOv7权重直接去跑红外图,效果通常惨不忍睹。这不是YOLOv7不行,而是训练它的人喂的是可见光数据。红外图像只有单通道灰度信息,目标和背景的对比度逻辑跟可见光根本不是一回事。这篇文章就围绕YOLOv7在红外场景下做车辆和行人检测这件事,把数据集准备、权重训练、推理部署这条链路完整梳理一遍。无论你是刚接触红外的初学者,还是已经被红外数据折磨过几轮的开发者,这篇内容应该都能给你省下不少踩坑的时间。
1. 红外场景检测的真正痛点:不是模型不行,是输入不一样
1.1 红外图为什么难倒一堆“效果很好”的预训练权重
很多人第一次拿到红外视频,第一反应是直接用YOLOv7官方预训练权重跑一下。结果往往是:行人漏检、车辆框漂移、甚至把路灯当成人。原因在于红外图像和可见光图像之间存在几个本质差异。
先说通道数。红外图像传感器输出的本质是热辐射强度分布图,绝大多数情况下是单通道灰度图。而网上能下载到的YOLOv7预训练权重,输入要求是三通道RGB。直接把单通道图复制成三通道喂进网络,算法看到的其实是同一份灰度信息重复搬运,模型从可见光数据里学到的色彩纹理特征完全派不上用场,性能自然会崩。
再看对比度和纹理。可见光图像里车辆和行人通常有丰富的颜色、阴影、边缘纹理,算法能借助这些“外观线索”做判别。红外图像则不同,它记录的是物体表面温度差异,车辆引擎盖热、轮胎冷,行人头部和躯干温度高、四肢相对低,整个目标在画面里呈现出一个亮度不规则的“热斑”。目标内部缺少细节纹理,轮廓模糊,并且和周围环境的热辐射容易发生混淆——夏天路面温度高,车辆底部阴影区域反而不热;冬天人体温度与建筑物外墙温差巨大,红外图里人像发光一样刺眼。这种种非线性的特征差异,决定了可见光权重基本不可能直接迁移到红外场景。
1.2 摸清两类红外场景任务,再决定要不要自己训练
红外目标检测需求大致分为两类:一类是安防监控和辅助驾驶里最常见的地面场景,目标就是行人和车辆,镜头固定或车载平台运动,背景相对可控;另一类是高空或航拍视角,比如无人机吊舱里安装红外载荷,在几百米高度往下看地面车辆和行人,目标尺寸小、背景复杂、运动轨迹混乱。你的标题对应的是第一类地面红外场景,处理起来相对成熟,公开数据集也比较多,完全值得自己训练一版专用权重。
这里有一个判断基准:如果你拿可见光预训练权重跑红外图,mAP掉到在可见光上的一半以下,那就别指望靠调阈值和图像后处理来补救,老老实实准备数据、重新训练。这不是玄学,是特征分布发生了根本性偏移,治本的办法只有让模型见过足够多的红外样本。
2. 数据集怎么搭:公开数据够用吗,自建数据要注意什么
2.1 公开红外数据集盘点
训练任何模型,数据先行。红外车辆和行人的公开数据集其实比想象中多,但分布零散,很多人找不到。这里把我实际用过的几个列出来:
| 数据集 | 规模 | 特点 | 适用场景 |
|---|---|---|---|
| FLIR Thermal Dataset | 约1万张标注图像,14000多个框 | 车载红外相机,涵盖白天、夜晚、黄昏,类别有行人、车辆、自行车 | 最接近真实车载红外检测需求 |
| KAIST Multispectral Benchmark | 可见光与红外成对数据,白天夜晚全覆盖 | 带对齐的RGB和热成像对,支持双模态研究 | 需要做多光谱融合的进阶玩法 |
| OTCBVS Benchmark | 多个子集,规模较小 | 经典红外行人数据集,标注质量高,适合算法研究和效果对比 | 入门验证、学术实验 |
| LLVIP | 约3万张红外-可见光对齐图像对,已有训练/验证划分 | 专为夜间低光行人检测构建,识别目标以行人和骑车人为主 | 夜间监控场景,行人检测为主的项目 |
如果你做的是纯红外车辆和行人检测,FLIR是我的首选。它的标注格式为COCO JSON格式,官方划分了训练集和验证集,拿过来可以直接转成YOLO格式使用。KAIST虽然名气大,但它的标注文件是老式MATLAB格式,转换起来稍费一点功夫,不过胜在提供了配套的可见光图,后面如果你想做“可见光+红外”的双模态融合,这组数据相当有价值。
另外提一句dmsd(船舶红外可见光双模态数据集)。虽然它的目标是船舶检测,不是车辆行人,但它的数据组织思路——同一场景下红外图和可见光图进行像素级对齐——很值得借鉴。如果你未来想把红外检测从地面安防扩展到水面监控(比如港口巡逻、内河航道管理),这种双模态对齐的组织方式能帮你少走很多弯路。
2.2 自建数据集的关键处理环节
公开数据通常只能解决“从无到有”,真实部署时你面对的环境大概率跟数据集分布不一样,这时候自建数据是必经之路。自建红外数据集时,我有几个切身教训要提醒你。
首先是采集设备的标定。红外镜头和可见光镜头在硬件上是两套系统,如果后续要做双模态对齐,必须先做联合标定,否则画出来框的偏移量随着距离增加会越来越大,最后根本无法使用。哪怕你只做纯红外检测,也要保证红外镜头的画面不能有严重畸变,尤其是边缘区域的目标形变,会直接拉低小目标的检测效果。
其次是标注原则要和可见光数据集区分开。红外图像中,行人有时被雨伞、背包遮挡,导致热量特征不完整;夏天车辆熄火后车身温度与环境温度接近,轮廓若隐若现。标注时需要有一套明确的规则:可见光中“看轮廓”就能标注的,红外里一定要结合热辐射特征判断,宁可漏标一个模棱两可的目标,也不要带着错误标签训练,否则模型会学到“这种模糊区域随便框一下也行”的错误逻辑。
数据增强方面,我建议在红外任务里适当加大Mosaic和MixUp的使用概率。红外图像的整体对比度经常偏低,而且单场景的画面重复度高,不做强增强很容易过拟合。但要注意,红外图像的亮度反转(热白冷黑变成热黑冷白)本身也是一种数据增强方式,如果设备支持切换极性,建议直接在代码里加一个随机反转的预处理分支,能显著提升模型的泛化能力。
3. 训练前的关键准备:环境、配置、anchors一个都不能少
3.1 环境安装与数据组织
YOLOv7的环境安装相对友好,要求在PyTorch 1.7以上的环境里运行,建议直接用PyTorch 1.12搭配CUDA 11.x,兼容性最稳。项目克隆下来之后,核心依赖就是opencv、pyyaml、matplotlib、numpy、tqdm这几个,直接pip安装即可。
数据组织要按YOLO的目录规范来,拿FLIR数据集举例,转完格式之后的目录结构长这样:
datasets/ ├── infrared/ │ ├── images/ │ │ ├── train/ │ │ └── val/ │ ├── labels/ │ │ ├── train/ │ │ └── val/ │ └── infrared.yaml说明一下,images目录放红外原图,labels目录放对应的txt标注文件,每一行格式为class_id x_center y_center width height,全部归一化到0~1之间。FLIR原始COCO标注里类别比较多,做车辆和行人检测时建议只保留person、car、truck、bus这几个类别,其余类别要么合并,要么直接删掉,减少干扰。
3.2 修改yaml配置文件与anchor计算
数据集准备好之后,首先修改infrared.yaml:
train: datasets/infrared/images/train val: datasets/infrared/images/val nc: 2 # 或者按你的类别数量写,比如person和car为2类 names: ['person', 'car']然后是anchors的重新计算。这是很多人跳过但恰恰最关键的一步。YOLOv7默认anchors是基于COCO数据集的,COCO里面小目标成千上万,而红外场景的目标尺寸分布通常集中在中等尺度,小目标的比例明显偏低。直接用默认anchor训练,模型在预测框回归阶段会白白浪费大量参数去适配一个不存在的尺寸分布。
用项目自带的工具重新算一下:
python tools/anchors.py --data cfg/infrared.yaml --img_size 640 --batch_size 8命令跑完会输出9组新anchors,把它填到cfg/training/yolov7.yaml的对应位置。我实测在FLIR数据集上重新计算anchor后,小目标召回率能提升2~3个百分点,这属于纯数据驱动的白送收益。
如果用的模型结构是yolov7-tiny(体积更小、更适合嵌入式部署),同理修改cfg/training/yolov7-tiny.yaml。注意tiny版本的层数较浅,如果红外目标特别小,建议把输入分辨率从默认的640提升到768,代价是推理速度略降,但小目标检测的收益通常很可观。
3.3 预训练权重和训练参数的选择逻辑
关于预训练权重,比较稳妥的做法是直接使用YOLOv7官方在COCO上训练好的yolov7_training.pt作为起点。虽然前面说过可见光权重的特征跟红外不匹配,但底层卷积层提取的通用边缘、轮廓、形状信息仍然是可迁移的,重新训练时这些通用特征可以加快收敛。不需要担心“域偏移太大导致迁移失效”,实际训练里加载COCO权重比从头训练在初期收敛速度上快得多,一般能快40%左右的epoch数。
训练超参数同样值得细说。建议batch size设为8或16,初始学习率0.01,配合cosine学习率调度。红外数据集不像大规模可见光数据集那么大,如果loss在某个epoch附近波动明显,优先考虑降低学习率而非增加epoch。
4. 训练实战:跑起来容易,判断好坏才是本事
4.1 训练命令与loss解读
一切就绪后,用下面这条命令开始训练:
python train.py --workers 8 --device 0 --batch-size 8 --data data/infrared.yaml --img 640 640 --cfg cfg/training/yolov7.yaml --weights yolov7_training.pt --name yolov7_infrared --hyp data/hyp.scratch.p5.yaml --epochs 150训练过程中重点盯三个指标:box_loss、obj_loss和cls_loss。红外图像的objectness loss通常降得比可见光慢,原因是红外目标与背景的对比度差异不稳定,模型需要更多轮次才能把“热斑”和“噪声”区分开。如果你发现obj_loss在前50个epoch已经降得很低,但box_loss还在高位徘徊,大概率是anchor没算准,回去重新检查第3节。
我从实操经验里给个参考范围:在FLIR数据集上训练,最终box_loss大致降到0.04以下,obj_loss降到0.01以下,cls_loss接近0,模型的检测效果基本就能满足多数安防场景的实用要求了。
4.2 从val结果里读出模型的真实水平
训练结束后,模型会自动保存best.pt和last.pt,并输出验证集的mAP结果。很多新手只看mAP这个数字,其实这里有坑。
FLIR数据集中“车辆”这一类包含轿车、卡车、巴士等多个子类,当车辆和行人混在一起时,如果车辆这一类的AP明显低于行人,说明模型把不同尺寸的车辆特征学混了,需要检查数据集里轿车的框是否被标注得太少。此外,还要单独看置信度阈值下的precision和recall曲线,红外场景比较容易出现“精度高但召回低”的假象——模型只检测出那些亮度对比明显的目标,暗弱目标全被漏掉了,这在夜间监控里很难接受。调整策略通常是降低confidence阈值到0.15~0.25,用更多的候选框换取召回率,后面再用NMS把重叠框收敛掉。
5. 检测权重的部署与推理调优
5.1 推理脚本里的红外图像预处理
训练完得到权重之后,下一步是部署。很多人在训练阶段表现不错,一上真实场景就掉链子,问题往往出在推理时没有做和训练一致的预处理。
YOLOv7的推理路径中,读入图像后会做letterbox缩放、归一化再送进网络。对于红外图像,我强烈建议在送入模型之前增加一步对比度增强。红外图像的像素分布经常集中在一个很窄的灰度区间内,直接归一化会让模型看到一张“灰蒙蒙”的图。用CLAHE(限制对比度自适应直方图均衡)做预处理,效果提升非常明显:
import cv2 def preprocess_infrared(img): # img为单通道红外灰度图 clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) img = clahe.apply(img) # 转为三通道,保持与模型输入一致 img = cv2.merge([img, img, img]) return img注意clipLimit不要设置太大,否则会把红外噪声也一并放大,产生大量伪目标。2.0是我试过最稳的值,如果场景特别暗,可以微调到3.0。
5.2 从pt到onnx/tensorrt的转换与NMS调节
训练好的best.pt可以先用官方脚本转成ONNX格式:
python export.py --weights runs/train/yolov7_infrared/weights/best.pt --grid --end2end --simplify --topk-all 100 --iou-thres 0.45 --conf-thres 0.25 --img-size 640 640 --max-wh 640如果要在Jetson这类边缘设备上做实时推理,建议继续把ONNX转成TensorRT的engine文件。红外检测的部署通常不是在高性能服务器上跑,而是在嵌入式设备或工控机上跑,TensorRT的FP16精度在红外这种轮廓模糊的任务里损失可以忽略不计,但推理速度能提升2倍以上。
TensorRT版本推理时,NMS参数和PyTorch推理时不完全一样。红外场景下同类目标(比如一排停放车辆头部挨着头部)之间的距离很近,如果IoU阈值设得太高,容易把两个相邻目标合并成一个框。我建议IoU阈值设在0.45左右,不要超过0.5,保持适度的容忍度。
5.3 实测中的误检漏检处理
红外场景里最经典的误检是:夏天被暴晒过的金属井盖、沥青路面裂纹、路灯杆、甚至空调外机,在红外图里都可能有跟车辆相似的热斑特征。排查这类误检时,单纯调confidence阈值是治标不治本。
我的建议分两步:第一步,收集误检样本加入训练集做hard negative mining,这个过程重复三轮以上,基本能把绝大多数场景误检压下来;第二步,针对固定机位的监控场景,可以在后处理里加一些先验规则,比如检测框的长宽比和车辆/行人典型比例严重不符时直接丢弃。这两步做完,误检率通常能再降一个量级。
还有一个细节容易被忽略:红外视频流的抖动比可见光明显,如果目标跟踪或检测线程直接跑在原始视频帧上,画面抖动会导致同一辆车在不同帧的框位置漂移严重,看起来像检测不稳。建议在推理前做一次轻量级的帧间配准(比如参考上一帧的全局运动向量做平移补偿),或者干脆在后处理阶段接一个简单的IoU跟踪器,给同一目标分配稳定ID,视觉效果会好得多。
6. 踩坑记录与调参经验
6.1 我试过最坑的几个问题
第一个坑是训练时忘了改类别数。YOLOv7的模型配置文件里nc默认是80,如果你数据集的yaml里写了2类,cfg没改过来,训练过程不会报错,但最终模型行为会非常奇怪——模型依赖于COCO的80类语义做初始化,输出头的神经元数量跟你的数据集不匹配,训练loss虽然会下降,但推理结果毫无意义。检查方法很简单:训练脚本启动后,第一时间看log里打印的model nc: 2是否和预期一致。
第二个坑是红外的“热白冷黑”极性差异。不同厂商的红外模组输出极性可能相反:有的设备人体是亮的(白热),有的是暗的(黑热)。如果你在A设备采集的数据上训练,拿到B设备上推理,模型性能会立刻崩掉。比较好的做法是在训练数据增强里加入“随机极性反转”,让模型对两种极性都鲁棒,或者部署时在预处理阶段统一做一次极性判断,保证输入分布跟训练一致。这个坑隐蔽性极强,遇到模型换机台就失灵的情况,先检查这个。
第三个坑是混合精度训练在红外任务上的表现不稳定。我遇到过用AMP训练后权重正常,但转成FP16的TensorRT引擎后,夜间小目标全部丢失的情况。原因是红外小目标本身的信号强度就弱,FP16的精度损失把这个弱信号直接“抹”掉了。解决办法是部署端保留FP16,但在预处理里对红外图做更强的对比度增强,或者在导出engine时用INT8量化加calibration数据集做校准,对小目标更友好一些。
6.2 给红外场景的参数微调建议
最后分享几个针对红外场景的实用调参习惯,这些不是标准文档里能查到的,但我在多个项目里验证过效果稳定。
训练阶段建议把--img从640提到768甚至896,红外车辆和行人的边缘模糊,分辨率越高的输入,模型越容易捕捉轮廓细节。代价是显存占用和推理耗时上升,需要根据设备来权衡。行人目标通常在画面远处时特别小,如果场景里远距离行人多,建议适当调大网络里的P5层输出,或者换用能输出更大特征图的模型结构。
数据增强方面,红外图像不需要像可见光那样强的色彩抖动(HSV),这些增强会浪费训练时间,建议把hsv_h、hsv_s、hsv_v调小或者直接关闭,把省下来的训练资源留给Mosaic和MixUp。我常用的配置是hsv_h=0.01、hsv_s=0.1、hsv_v=0.1,比默认值低了不少,但红外图的单通道特性决定了增强的重点应该在几何变形和尺度变化上。
还有一个看似不起眼但实际影响很大的点:推理时的置信度阈值,建议用验证集上的PR曲线动态选择。命令行里默认的0.25在红外场景往往偏高,我自己做夜间行人检测时通常会降到0.15,配合上面提到的NMS调节和跟踪器,效果反而更稳。实际上阈值的设置跟模型的训练充分度直接挂钩,训练越充分,阈值可以设得越低,误检率也不会失控。
红外场景的检测项目,最耗时间的永远不是模型选择和训练本身,而是数据分布和预处理这些容易被忽视的细节。把数据组织好、把预处理思路理清、把配置文件的每一项都验证过,再上训练和部署,整个链路才会走得顺畅。我这套流程改一改也能适配其他单模态传感器数据,比如微光夜视或者超声热成像,底层逻辑是相通的。
本文还有配套的精品资源,点击获取