恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
红外狗类目标检测数据集:夜间巡检场景下的YOLOv8实战与避坑指南
首页
资讯中心
/
红外狗类目标检测数据集:夜间巡检场景下的YOLOv8实战与避坑指南
红外狗类目标检测数据集:夜间巡检场景下的YOLOv8实战与避坑指南
发布时间:2026/10/12 0:08:38
简介这份红外狗类目标检测数据集面向从事热成像目标检测的算法工程师、农业安防开发者与高校研究人员解决低光照、夜间及恶劣天气下动物识别样本稀缺的问题。数据全部为红外热成像图像按YOLO格式提供归一化边界框与类别标签类别0为非狗类干扰项、类别1为狗类目标可直接用于YOLOv5、YOLOv12等模型的训练与验证。压缩包共824个文件以411张jpg红外图片和411个txt标注文件为主另含1个yaml数据配置与1份docx说明文档整体约17.05MB轻量易用兼容PyTorch、TensorFlow等主流框架。数据集划分为训练集357张、验证集36张、测试集18张覆盖真实红外监控场景适合农场防盗、野生动物保护、边境安防警报及户外巡检机器人避障等应用。目前已有162人学习下载可帮助读者快速搭建红外目标检测基线、验证模型在低可见度条件下的鲁棒性并填补红外动物检测细分领域的数据缺口。1. 红外狗类目标检测数据集夜间巡检场景里被低估的一块拼图做安防巡检或者园区周界项目的同行大概率都遇到过这个场景可见光摄像头白天跑得好好的一到晚上或者雾霾天画面里只剩一团黑狗、猫、甚至人影全糊在一起。这时候红外热成像就成了刚需而红外狗类目标检测数据集正是解决「夜间到底有没有狗闯入」这个具体问题的起点。它不是一个通用的大而全数据集而是聚焦在红外波段下对犬类目标做标注适合做周界防护、养殖场看护、野生动物监测这类需要全天候感知的落地项目。很多人一上来就想着拿 COCO 或者 BDD100 直接训结果红外图像和可见光图像的灰度分布、纹理特征完全不是一回事模型直接翻车。这个数据集的价值就在于它把红外域里的狗类样本单独拎出来让你不用从零标注能快速验证「红外狗」这条技术路线到底跑不跑得通。适合谁做边缘端部署的嵌入式工程师、搞小样本迁移的算法同学以及需要快速出 demo 的解决方案团队。2. 红外狗类目标检测数据集到底包含什么从标注格式到场景分布2.1 红外图像与可见光图像的本质差异先把一个基础认知立住红外图像记录的是热辐射不是反射光。狗的身体温度通常在 38 度上下和夜间环境背景地面、墙体、植被的温差能拉开十几度所以在红外画面里狗往往呈现为高亮区域。但这个高亮不是稳定的受风速、湿度、狗的运动状态影响很大。可见光里靠纹理和颜色区分目标红外里只能靠灰度对比和轮廓形状。这就导致两个直接后果第一基于 RGB 预训练的 backbone 迁移到红外域浅层卷积核学到的边缘和颜色滤波器基本失效第二红外图像的信噪比普遍偏低狗和背景的边界容易模糊标注框的紧致度对训练影响比可见光更大。我一般会建议在正式训练前先抽 20 到 30 张样本做灰度直方图统计看看狗区域和背景区域的灰度均值差多少。如果差值低于 15 个灰度级这批数据就得先做对比度增强否则模型很难学到有效特征。常见做法是用 CLAHE限制对比度自适应直方图均衡做预处理clipLimit 设在 2.0 到 3.0 之间tileGridSize 用 8x8这个参数组合在多数红外狗类场景里比较稳。2.2 标注格式的识别与转换拿到一个目标检测数据集第一件事是确认标注格式。红外狗类数据集常见的标注格式有三种Pascal VOC 的 XML、YOLO 的 txt、以及 COCO 的 json。不同格式对应的训练框架不一样ultralytics 的 YOLO 系列吃 txtmmdetection 吃 COCO 或 VOCdetectron2 也吃 COCO。如果你拿到的数据集是 VOC 格式想用 YOLOv8 或 YOLOv11 训练就得先转格式。转换逻辑不复杂但有几个边界坑。VOC 的坐标是左上角和右下角的绝对像素值YOLO 的 txt 要求归一化后的中心点坐标和宽高。转换时要用图像的原始宽高做除数而不是标注文件里写的 size因为有些数据集在裁剪或缩放后忘了更新 size 字段直接除会得到超过 1 的坐标训练时 loss 直接爆炸。import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_dir, img_dir, out_dir, class_map): xml_dir: VOC标注文件夹 img_dir: 对应图像文件夹用于读取真实宽高 out_dir: 输出YOLO txt的文件夹 class_map: {dog: 0} 类别映射 if not os.path.exists(out_dir): os.makedirs(out_dir) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() # 从图像文件读取真实尺寸不信任XML里的size img_name root.find(filename).text img_path os.path.join(img_dir, img_name) from PIL import Image with Image.open(img_path) as im: w, h im.size lines [] for obj in root.findall(object): cls_name obj.find(name).text if cls_name not in class_map: continue bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 裁剪到图像边界内防止越界坐标 xmin max(0, min(xmin, w - 1)) ymin max(0, min(ymin, h - 1)) xmax max(0, min(xmax, w - 1)) ymax max(0, min(ymax, h - 1)) cx (xmin xmax) / 2.0 / w cy (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{class_map[cls_name]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) txt_name os.path.splitext(xml_file)[0] .txt with open(os.path.join(out_dir, txt_name), w) as f: f.write(\n.join(lines)) # 调用示例 voc_to_yolo(./annotations, ./images, ./labels, {dog: 0})这段代码的关键点有三个。第一宽高从图像文件实时读取不依赖 XML 里的 size 字段这是血泪经验很多公开数据集在这块有历史遗留问题。第二坐标做了边界裁剪防止标注员手抖画出越界框导致归一化后出现负值或大于 1 的值。第三类别映射用字典控制方便后续扩展多类别。参数上class_map 按你的实际类别改如果数据集里还有猫、人就加进去但红外狗类数据集通常只有 dog 一类保持 0 就行。2.3 数据集划分与场景分布检查转换完格式下一步是划分训练集、验证集、测试集。常见比例是 7:2:1 或 8:1:1但红外狗类数据集往往样本量不大如果按随机划分可能出现某个场景比如白天、夜间、雨天的样本全跑到训练集里验证集上指标虚高。我一般会先按场景标签做分层抽样确保每个子集里都有不同光照和天气条件的样本。检查场景分布有个笨办法但很有效把图像按平均灰度值排序然后均匀切分成若干段看每段里狗的数量和标注框大小分布。如果发现某个灰度段几乎没有狗说明这个数据集在极端暗光或过曝场景下覆盖不足训练出来的模型在这些场景下大概率漏检。这时候要么补数据要么在训练时对这部分场景做针对性增强。3. 用 YOLOv8 在红外狗类数据集上跑通第一个 baseline3.1 环境配置与数据目录组织ultralytics 的 YOLOv8 对新手比较友好环境配置不复杂。我一般用 conda 建一个干净环境Python 3.9 或 3.10 都行PyTorch 按 CUDA 版本装。如果你机器上没有 GPUCPU 也能跑但训练时间会拉长很多建议至少用一张 8G 显存的卡。conda create -n ir_dog python3.10 -y conda activate ir_dog pip install ultralytics pip install opencv-python pillow装完之后数据目录按 YOLO 的标准结构组织ir_dog_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ └── labels/ ├── train/ ├── val/ └── test/然后写一个 data.yaml告诉 YOLO 去哪里找数据和类别名path: ./ir_dog_dataset train: images/train val: images/val test: images/test names: 0: dog这个 yaml 里 path 是数据集根目录train/val/test 是相对路径。names 的键值对要和标注 txt 里的类别索引一致否则训练时类别对不上模型学出来的全是错的。3.2 训练命令与关键参数设置baseline 训练不需要一上来就调很复杂的超参先用默认配置跑通看 loss 曲线和 mAP 再说。命令很简单yolo detect train \ data./data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ projectir_dog_runs \ namebaseline这里有几个参数值得展开说。model 选 yolov8n.pt 是因为红外狗类数据集通常不大用 nano 版本先验证可行性速度快显存占用低。imgsz 设 640 是 YOLO 系列的默认值但如果你的红外图像分辨率很高比如 1280x1024直接缩到 640 会丢失小目标细节狗在画面里如果只占几十个像素缩完就没了。这时候要么把 imgsz 提到 960 或 1280要么先做滑窗切图。batch 根据显存调8G 卡跑 640 分辨率batch 16 一般没问题如果 OOM 就降到 8。训练启动后重点看三个指标box_loss、cls_loss 和 mAP50。box_loss 下降说明框回归在收敛cls_loss 下降说明分类在学mAP50 是最终衡量检测效果的。如果 box_loss 震荡不降大概率是学习率太大或者标注框质量太差。如果 cls_loss 降不下去检查类别映射和标注文件里有没有空文件。3.3 推理验证与结果解读训练完用验证集跑一遍推理看实际效果yolo detect predict \ modelir_dog_runs/baseline/weights/best.pt \ source./ir_dog_dataset/images/val \ conf0.25 \ saveTrueconf 设 0.25 是常用起点意思是置信度低于 0.25 的框不显示。如果发现漏检多把 conf 降到 0.1 看看是不是模型其实检到了但被阈值卡掉了如果误检多把 conf 提到 0.4 或 0.5。推理结果会保存在 runs/detect/predict 目录下打开图像肉眼过一遍重点看夜间场景和狗只部分遮挡的情况。我一般会额外统计一下不同置信度阈值下的 precision 和 recall画一条 PR 曲线找到最适合业务场景的平衡点。周界防护场景宁可误报也不能漏报所以 recall 优先conf 可以设低一点后面再加跟踪和时序滤波去误报。4. 红外狗类目标检测的避坑与排查清单4.1 现象训练 loss 正常下降但 mAP 始终在 0.1 以下原因通常出在标注格式上。YOLO 的 txt 要求每行是class_id cx cy w h全部归一化到 0 到 1 之间。如果转换脚本里忘了归一化或者用错了宽高坐标值会大于 1模型学到的就是错误的位置映射。另一种可能是类别索引从 1 开始而不是 0YOLO 默认从 0 开始对不上就全错。解决写个脚本抽查 10 个标注文件打印每行的数值范围确认 cx、cy、w、h 都在 0 到 1 之间且 class_id 是 0。如果发现异常回到转换脚本修。4.2 现象模型在白天红外图像上表现好夜间全漏原因是数据集的场景分布不均衡夜间样本太少模型没学到夜间红外图像的特征分布。红外图像在夜间和白天的主要差异是背景温度对比度夜间背景更冷狗的热信号更突出但同时也可能出现热晕效应狗的边缘反而模糊。解决先统计训练集里夜间样本占比如果低于 30%要么补数据要么在训练时对夜间样本做过采样。另一个办法是用 mosaic 和 mixup 增强但要注意红外图像做 mixup 时两张图的灰度分布差异大混合后可能产生不真实的中间态我一般会把 mixup 的概率调低到 0.1 以下。4.3 现象验证集 mAP 很高但部署到边缘设备上帧率只有个位数原因是模型选大了或者输入分辨率设太高。yolov8n 在 640 分辨率下主流边缘芯片比如瑞芯微、寒武纪跑几十帧没问题但如果你用了 yolov8x 或者 imgsz 设到 1280算力就跟不上了。解决先确认部署硬件的算力上限然后选对应规模的模型。红外狗类检测任务通常不需要超大模型yolov8s 或 yolov8m 在多数场景下够用。如果还不够快用 TensorRT 或 ONNX Runtime 做量化加速INT8 量化能把推理速度提一倍以上但要注意校准集要用红外图像不能用可见光图像否则量化误差会很大。4.4 现象狗只重叠或部分遮挡时检测框合并成一个原因是 NMS非极大值抑制的 IoU 阈值设得太高或者模型本身对遮挡场景训练不足。红外图像里狗和狗挨在一起时热信号连成一片模型容易把两只狗检成一个框。解决先把 NMS 的 IoU 阈值从默认的 0.7 降到 0.5 试试看能不能分开。如果不行说明模型特征区分度不够需要在训练数据里增加遮挡样本或者在 loss 里加一个排斥项让模型学会区分相邻目标。另一个工程上的办法是加跟踪算法用时序信息把连续帧里的检测框关联起来即使单帧合并了跟踪也能拆开。4.5 现象换了另一批红外摄像头的数据模型直接崩了原因是域偏移。不同厂商的红外摄像头在响应波段、增益设置、图像处理流水线上有差异导致同样场景下输出的灰度分布不一样。模型在 A 摄像头数据上训的换到 B 摄像头就水土不服。解决如果目标域数据量少用 few-shot 微调冻结 backbone只训检测头学习率设小一点比如 0.0001。如果目标域数据量够直接混合两个域的数据一起训让模型学到域不变特征。常见做法是在 backbone 里加一个域分类器做对抗训练但这个实现复杂度高新手先用微调顶住。5. 把红外狗类检测推到可落地从单帧检测到时序确认单帧检测在红外狗类场景里有个天然短板热信号受环境影响大偶尔会出现类似狗的热源比如刚熄火的汽车引擎、地暖出口单帧模型很容易误报。我一般会在检测后面加一层时序确认用简单的帧间逻辑把误报压下去。具体做法是对同一路视频流维护一个滑动窗口窗口长度设 15 到 30 帧。每帧跑检测如果某个位置连续 N 帧都出现狗才判定为真实目标。N 的取值看帧率25 帧的视频里 N 取 8 到 10 比较合适既能过滤瞬时热源干扰又不会漏掉快速跑过的狗。from collections import deque class TemporalConfirmer: def __init__(self, window15, min_hits8, iou_thresh0.5): self.window window self.min_hits min_hits self.iou_thresh iou_thresh self.buffer deque(maxlenwindow) def update(self, detections): detections: 当前帧的检测框列表每个元素是 (x1, y1, x2, y2, conf) 返回确认后的检测框 self.buffer.append(detections) confirmed [] for det in detections: hits 0 for frame_dets in self.buffer: for fd in frame_dets: if self._iou(det, fd) self.iou_thresh: hits 1 break if hits self.min_hits: confirmed.append(det) return confirmed def _iou(self, a, b): x1 max(a[0], b[0]) y1 max(a[1], b[1]) x2 min(a[2], b[2]) y2 min(a[3], b[3]) inter max(0, x2 - x1) * max(0, y2 - y1) area_a (a[2] - a[0]) * (a[3] - a[1]) area_b (b[2] - b[0]) * (b[3] - b[1]) union area_a area_b - inter return inter / union if union 0 else 0这段逻辑的核心是不是每一帧检到就报而是看这个目标在最近 window 帧里出现了多少次。min_hits 控制灵敏度设高了漏报多设低了误报多。我一般会在验证集上跑一遍画一条 hits 数量 vs 误报率的曲线找拐点。参数上window 和 min_hits 要配合帧率调高帧率场景 window 可以短一点低帧率场景 window 要拉长否则狗跑过去了窗口还没填满。还有一个进阶技巧把红外检测框和可见光检测框做融合。如果现场同时有红外和可见光摄像头白天用可见光检测夜间用红外检测过渡时段两个都跑用加权框融合WBF合并结果。这样能兼顾白天的纹理细节和夜间的热信号优势整体召回率比单模态高不少。融合权重按光照传感器读数动态调光照低于阈值时红外权重调高反之亦然。这套方案我在几个园区周界项目里跑过红外狗类检测的误报率从单帧的每天几十次压到了个位数漏报主要出现在狗贴着墙根走、热信号被墙体遮挡的场景这种只能靠加摄像头角度或者补红外补光灯解决。做工程就是这样算法能解的是一部分剩下的得靠现场调试。希望帮到你。本文还有配套的精品资源点击获取