资讯详情

红外飞机小目标检测:YOLO数据集与训练实战指南

📅 2026/9/28 16:16:22 | 华诺云谱 👁 阅读
红外飞机小目标检测:YOLO数据集与训练实战指南
简介YOLO红外飞机小目标检测数据集面向目标检测入门与进阶学习者也适合需要开展红外弱小目标识别研究的工程师和学生提供1000张来自真实场景的高质量红外飞机图片覆盖多种背景与目标尺度可有效支撑小目标检测算法研究与模型验证。数据使用LabelImg标注标注框质量可靠同时提供VOCxml、COCOjson与YOLOtxt三种格式标签分别存放可直接接入YOLO系列训练流程免去自行格式转换的麻烦。压缩包共2000个文件包含1000个xml标注文件、990个txt文本文件主要为YOLO格式标签以及6个html图文教程、3个py划分脚本和1个yaml配置文件整体约13.29MB。教程覆盖Linux与Windows两种环境下的YOLO环境搭建并结合案例演示如何修改配置训练自己的数据集划分脚本可灵活生成训练集、验证集和测试集显著降低上手门槛。目前已有302人学习下载适合需要快速获取高质量红外飞机小目标数据集并完成环境配置、模型训练与验证的读者。1. 红外飞机小目标检测数据集1000张红外图能不能喂出一个能用的YOLO模型夜视、云层遮挡、远距离监视这几个场景一叠加红外飞机小目标检测就成了目标检测里最磨人的一块。你拿YOLO跑常规数据集顺风顺水一到红外图就原形毕露飞机在画面里只有十几二十个像素没有颜色纹理背景又是大片大片的暗区检测器要么漏检要么把云层噪声当目标框出来。这个题为YOLO红外飞机小目标检测数据集的压缩包解决的正是这个痛点——它把1000张红外飞机图像整理成了可以直接喂给YOLO的工程目录附上voc、coco、yolo三套格式的标签、划分脚本和训练教程省掉你自己标注、自己转换、自己踩坑的时间。适合谁刚接触小目标检测、想在红外场景下用YOLO出结果的研究生和工程师以及需要一份标准数据来验证检测算法改进效果的开发者。一个反直觉的结论先放这儿1000张图对YOLO来说不算多但只要类别单一、标注规整、训练参数调对单类红外飞机检测完全能跑到可用水平关键在数据组织和参数设置。2. 拆解数据集红外小目标的三套标注体系与划分逻辑2.1 红外图里的小目标到底多小尺寸、信噪比与检测难点小目标检测和常规目标检测的第一道分水岭是目标尺寸。COCO数据集里把面积小于32×32像素的目标定义为小目标而红外飞机场景里很多目标连这个门槛都够呛。1000张红外图里如果飞机出现在远景它的包围框可能只有10×10到25×25像素占整张图的面积比例往往不到0.1%。目标面积小意味着网络下采样几次之后目标在特征图里只剩一两个像素点检测头根本拿不到有效特征。更麻烦的是红外图像本身的特性。可见光图像有丰富的边缘、纹理、颜色信息而红外图像里目标和背景的灰度差往往很小目标只是一个稍微亮一点的斑点没有轮廓细节。加上红外传感器本身的噪声云层边缘、地物热辐射都可能形成和目标灰度相近的干扰。所以在处理这类数据集时不能只看标签格式对不对还要关注两个隐含信息目标尺寸分布范围和图像背景的灰度分布。拿到压缩包后第一步应该做的不是直接训练而是统计标签里所有包围框的宽高分布确定目标到底是小还是极小这直接影响后文的anchor策略和推理时的输入分辨率。2.2 voc、coco、yolo三种标签格式同一张图三种坐标写法怎么换算这个压缩包的最大价值在于同一批图片给了三套标签。为什么需要三套因为不同训练框架吃不同的格式voc格式是目标检测老牌数据集Pascal VOC的XML标签Darknet系的YOLOv5/YOLOv8原生用txt格式而coco格式是通用目标检测数据集COCO的JSON标注很多检测框架和评估工具都以COCO为基准。voc格式里一个目标用一个XML节点描述核心字段是bndbox里的xmin、ymin、xmax、ymax单位是像素表示包围框左上角和右下角坐标。coco格式则是一个大JSON文件每张图对应一个annotation条目bbox字段是[x, y, width, height]同样以像素为单位同时还有area、segmentation、iscrowd等字段。yolo格式最不一样每行一个目标五个数字依次是class_id、x_center、y_center、width、height前两个是包围框中心点坐标后两个是宽高四个值全部除以图片宽高做了归一化所以取值范围是0到1之间的小数。三者换算的核心公式是xmin (x_center - width / 2) * img_w ymin (y_center - height / 2) * img_h xmax (x_center width / 2) * img_w ymax (y_center height / 2) * img_h反向换算时同理用像素坐标减去半宽半高得到左上角再除以图像宽高得到归一化值。看起来简单但实际动手时踩坑最多的地方有两个一是voc转yolo时忘了除以图像宽高导致train时坐标全部大于1被判为无效框二是coco的bbox和voc的xmin不一致——voc用的是左上右下coco用的是左上宽高不少人转格式时空着area字段不填后面跑评估脚本时报KeyError。下面给出一段可复用的voc转yolo核心函数读取XML并输出YOLO格式的txt文件。import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, out_txt_path, class_names): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in class_names: continue cls_id class_names.index(cls_name) bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) with open(out_txt_path, w) as f: f.write(\n.join(lines))这段代码先从XML的size节点读出原图真实宽高再遍历所有object节点取出类别名和包围框坐标按公式做归一化后写入txt。注意两个细节类别名必须预先定义好class_names列表且顺序不能变因为YOLO的类别编号按列表顺序生成训练时dataset.yaml里的names顺序必须和这里完全一致否则会出类别错位的玄学问题另外边界框坐标超出图像范围时有人直接clip到[0,1]没问题但最好先检查标注本身是否越界而不是盲目裁剪。2.3 1000张图的划分逻辑比例只是表象防泄漏才是关键有了图片和标签下一步是划分train/val/test。大多数人随手按8:1:1随机切分但红外飞机数据集有个容易被忽视的坑——数据可能存在时间相关性。如果这1000张图是连续视频帧抽出来的相邻帧里的飞机位置、姿态高度相似随机划分很可能让同一段连续帧既出现在训练集又出现在验证集val指标虚高模型实际部署效果大打折扣这就是典型的数据泄漏。正确做法是划分前先看图片文件的命名或拍摄时间信息。如果文件名带时间戳或者推断出是视频抽帧而来应该按时间顺序把整个视频片段切分成三段再分别分入train、val、test保证验证集和训练集里的飞机来自不同片段。如果文件名没有时间信息退一步也要把同一批连拍的图片手动归组再按组划分。训练起来之后如果val的mAP高得离谱而测试时效果很差大概率就是验证集泄漏了这时回头改划分脚本比加数据更有效。划分脚本本身要保证图片和对应的三套标签同步移动不能只搬图不搬标签。常见的做法是建立文件名映射关系以不带后缀的图片名为key分别查找同名.xml和同名.txt以及记录在coco.json里的image_id移动到对应目录。这一步放到第3章的划分脚本里一并处理。3. 把压缩包装成工程目录规范、格式转换脚本与划分脚本的改造3.1 解压后先干三件事建目录、画框检查、核对类别压缩包解压出来先别急着配环境。我拿到任何数据集的第一件事永远是画框检查因为标注质量决定了训练效果的上限。用OpenCV把XML里的包围框画回原图肉眼扫一遍重点看三类问题框有没有明显偏移目标、有没有漏标的目标、有没有类别标错的。红外图里目标和背景对比度低标注时很容易框大一圈或框到背景噪声上这种错标在训练时会被模型当成正确答案学进去后期再调参也救不回来。目录建议按YOLO工程的标准结构组织方便后面直接用ultralytics训练dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── annotations/ │ ├── train.json │ └── val.json └── dataset.yamlimages和labels目录是YOLO训练的直接输入annotations目录放coco格式的JSON供需要coco格式的框架或评估工具使用。如果你手头的压缩包结构不是这样就用脚本整理成这个标准结构。类别核对也在这里做打印所有标签里的类别名集合确认是否只有一类airplane或类似命名类别数量要小于10否则后文训练配置和评估都会变得更复杂。3.2 转换脚本改造给voc转yolo脚本加上coco输出第2.2节给的是单张XML转txt的核心函数实际工程里要把它包装成批量处理并同时产出coco格式的JSON。常见做法是分两步先批量把XML转成yolo的txt再从同一批XML生成coco JSON。这里给出批量转换加coco导出的完整脚本骨架。import os import json import xml.etree.ElementTree as ET from glob import glob def voc_to_yolo_batch(xml_dir, label_out_dir, class_names): os.makedirs(label_out_dir, exist_okTrue) for xml_path in glob(os.path.join(xml_dir, *.xml)): name os.path.splitext(os.path.basename(xml_path))[0] voc_to_yolo(xml_path, os.path.join(label_out_dir, name .txt), class_names) def voc_to_coco(xml_dir, json_out_path, class_names): images, annotations [], [] ann_id 1 for img_id, xml_path in enumerate(glob(os.path.join(xml_dir, *.xml))): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) file_name root.find(filename).text images.append({ id: img_id, file_name: file_name, width: img_w, height: img_h }) for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in class_names: continue bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) w, h xmax - xmin, ymax - ymin annotations.append({ id: ann_id, image_id: img_id, category_id: class_names.index(cls_name), bbox: [xmin, ymin, w, h], area: w * h, iscrowd: 0, segmentation: [[xmin, ymin, xmax, ymin, xmax, ymax, xmin, ymax]] }) ann_id 1 coco { images: images, annotations: annotations, categories: [{id: i, name: n} for i, n in enumerate(class_names)] } with open(json_out_path, w) as f: json.dump(coco, f)这个脚本里有几个参数值得解释。class_names列表是全局约定voc_to_yolo和voc_to_coco必须传入同一个列表才能保证txt里的类别编号和JSON里的category_id对应。segmentation我按多边形框填了四个顶点如果后续你要训练实例分割模型这个字段就能直接复用不用的框架往往只读bbox也不会报错。area字段务必填上很多coco评估工具会在算AP时读取area做尺寸分组缺失会直接跳过该目标导致指标偏低。3.3 划分脚本图片和三套标签同步移动并做孤儿文件检查划分脚本是整个流程里最容易出低级错误的一步常见翻车现场是图片分了train标签没跟上训练时每张图都找不到标签文件ultralytics直接跳过这些图你还不容易察觉。我习惯把划分脚本写成按图片主名同步搬移的方式再跑一遍一致性检查。import os import shutil import random from glob import glob random.seed(42) img_dir dataset/images_all xml_dir dataset/annotations_xml yolo_label_dir dataset/labels_all split_ratio {train: 0.8, val: 0.1, test: 0.1} imgs glob(os.path.join(img_dir, *.jpg)) names [os.path.splitext(os.path.basename(p))[0] for p in imgs] random.shuffle(names) # 按比例切分先按完整视频片段分组再shuffle效果更好 cut_train int(len(names) * split_ratio[train]) cut_val int(len(names) * (split_ratio[train] split_ratio[val])) splits { train: names[:cut_train], val: names[cut_train:cut_val], test: names[cut_val:] } for split, name_list in splits.items(): for img_out in [dataset/images, dataset/labels, dataset/annotations]: os.makedirs(os.path.join(img_out, split), exist_okTrue) for name in name_list: for ext in [.jpg, .png]: src_img os.path.join(img_dir, name ext) if os.path.exists(src_img): shutil.move(src_img, os.path.join(dataset/images, split, name ext)) break src_xml os.path.join(xml_dir, name .xml) if os.path.exists(src_xml): shutil.move(src_xml, os.path.join(dataset/annotations, split, name .xml)) src_txt os.path.join(yolo_label_dir, name .txt) if os.path.exists(src_txt): shutil.move(src_txt, os.path.join(dataset/labels, split, name .txt)) # 孤儿文件检查labels目录里有txt但没有对应图片的一律删掉 for split in splits: label_paths glob(os.path.join(dataset/labels, split, *.txt)) orphan [] for lp in label_paths: base os.path.splitext(os.path.basename(lp))[0] img_exists os.path.exists(os.path.join(dataset/images, split, base .jpg)) or \ os.path.exists(os.path.join(dataset/images, split, base .png)) if not img_exists: orphan.append(lp) for lp in orphan: os.remove(lp) print(fremoved orphan label: {lp})脚本逻辑分三段。第一段用random.seed固定随机种子保证每次运行划分结果一致这很重要——你调参后要复现实验随机种子不同会导致训练集不同指标没法对比。第二段按8:1:1切片切片前shuffle打乱这里我注释了按完整视频片段分组再shuffle效果更好如果你的图来自连拍片段改成先按片段名分组再对组shuffle更稳。第三段是孤儿文件检查清理掉有标签无图片的txt防止训练时读入无效标签。提示划分完成后建议再跑一遍数量统计打印train/val/test各自的图片数和标签数确认三个集合里都有数据且比例正确。val集为空时ultralytics会直接跳过验证环节很多人没注意照样训练完最后拿不出可信的mAP。4. 跑通YOLOv8训练红外飞机小目标环境、数据配置与5个必调参数4.1 环境安装与预训练模型选择v8权重怎么拉、版本怎么锁训练红外小目标检测我推荐直接上YOLOv8的ultralytics库理由很简单配置最省事、验证指标齐全、数据格式兼容上面做好的目录。环境安装用pip一把梭Python版本建议3.9到3.11之间太新的Python版本有些CUDA轮子还没跟上装torch时会踩坑。pip install ultralytics预训练模型的下载是新手最困惑的一步。yolo预训练模型下载其实不需要手动找链接ultralytics会在你第一次指定模型名时自动从官方GitHub Releases拉权重文件比如yolov8n.pt约6MB、yolov8s.pt约22MB。如果有人告诉你yolo预训练模型下载必须去某些第三方站那多半是误导。我一般直接用yolov8n或yolov8s做红外小目标的基础权重因为模型越小训练越快小数据集上过拟合风险也越低。yolo detect train datadataset/dataset.yaml \ modelyolov8n.pt \ epochs100 \ imgsz1280 \ batch8上面这行命令就是完整的训练入口。modelyolov8n.pt表示加载COCO预训练权重如果网络环境不好导致权重下载失败可以手动下载后放到当前目录ultralytics检测到本地文件就不会再拉取。训练时如果batch过小导致显存溢出优先降imgsz而不是关掉训练重来。4.2 数据配置文件dataset.yaml类别顺序必须和标签一致数据集配置文件是连接目录结构和训练器的桥梁。单类红外飞机检测的yaml很简单但这里出过最多的坑names顺序和标签文件里的class_id不一致。前面第3.2节强调class_names列表的顺序不能变就是在为这一步埋伏笔。写yaml时直接沿用转换脚本里的class_names顺序path: dataset train: images/train val: images/val test: images/test names: 0: airplanepath是相对当前工作目录的路径train和val指向图片目录ultralytics会到对应目录找图片再去同级父目录下的labels目录找同名txt标签。这个依赖关系是框架约定的如果你的图片在images/train那么标签必须放在labels/train且文件名第一段完全一致。所以第3章划分脚本里我把labels目录同步建好就是为了满足这个约定不用在yaml里再写一遍label路径。注意类别名建议统一用英文小写不要带空格和特殊字符。红外数据集的类别通常只有airplane一类但如果压缩包里还有其他类别比如helicopter、dronenames列表必须按类别编号升序排列和转换脚本里的class_names严格一致。4.3 5个必调参数imgsz、batch、epochs、optimizer与mosaic训练红外小目标检测和训练常规数据集参数策略有明显差异这里列出五个最关键的调参项。第一个是imgsz输入分辨率。默认640在常规数据集上够用但红外飞机只有十几二十个像素640下采样8倍后目标只剩两三个像素检测头几乎学不到特征。我的经验是把imgsz提到1280甚至1536目标在输入图里能占十几个像素检测率会有明显提升。代价是显存和训练时间翻倍显存不够时先降batch。第二个是batch批大小。红外图像背景大都是暗区图像内容相似度很高batch太小会让梯度估计噪声大训练不稳定。在显存允许的前提下batch尽量不小于8。如果你只有一个GPU且显存只有12Gimgsz1280时batch4是底线。第三个是epochs。1000张图单类别epochs设100足够设太大容易过拟合。具体判断看训练日志里的val精度曲线连续20个epoch没有上升就该停了ultralytics支持patience参数做早停。第四个是optimizer。红外小目标数据集上我一般用SGD带动量动量为0.937初始学习率0.01。AdamW收敛快但容易在小数据集上过早饱和SGD的泛化在小样本场景下更好。第五个是mosaic数据增强里影响最大的一项。mosaic增强会把四张图拼在一起训练问题在于拼接时小目标可能在裁剪边缘被切断目标消失或变成半截框。红外小目标本身像素少mosaic的破坏效果比常规目标更严重。我通常把mosaic关闭或降到0.3以下同时保留其他的翻转、缩放增强。yolo detect train datadataset/dataset.yaml \ modelyolov8n.pt \ epochs100 \ imgsz1280 \ batch8 \ optimizerSGD \ lr00.01 \ mosaic0.3 \ patience204.4 训练过程看什么loss曲线、验证指标与yolo损失函数的行为训练跑起来之后别盯着进度条发呆。ultralytics日志里会同步输出box_loss、cls_loss、dfl_loss三条loss曲线红外小目标场景下box_loss会比较高因为目标小、像素少回归精度本身就受限。正常的loss曲线应该整体缓慢下降如果box_loss震荡剧烈或者出现NaN多半是学习率过大或输入图像有异常这时候直接停掉先查数据再调lr。每个epoch结束后的验证环节会输出mAP50、mAP50-95、precision、recall四组指标。红外小目标检测的mAP50-95通常低于常规检测因为小目标对IoU的变化极其敏感这是任务本身的客观难度不用太焦虑。更值得关注的是precision和recall的平衡如果recall低说明漏检多优先提分辨率或增强数据如果precision低说明误检多优先调置信度阈值或检查背景噪声标注。yolo损失函数里的dfl_loss控制边界框回归的分布小目标场景下dfl_loss的绝对值会比大目标高这正常不必因为这个单独调权重。5. 红外小目标训练最常见的5个翻车点现象、原因与处理5.1 训练中loss变成NaN或者bn崩溃yolo训练中bn崩溃的全链路排查现象训练进行到十几个epochloss突然变成nan或者验证mAP剧烈震荡最终全红。多人遇到这类问题第一反应是调低学习率但根本原因往往在数据侧。红外图像里存在大量纯黑或近纯黑的背景区域经过网络卷积后这些区域的响应值极低批归一化层的均值和方差被这些暗区拉偏统计量不稳定导致梯度爆炸。原因要分几层排查一是数据里有没有全黑或全灰的坏图检查方法是统计每张图的灰度均值找出均值低于某个阈值的图直接剔除二是输入图像里目标太靠近图像边界增强时把目标切没了一半标签框越界或面积趋近于零导致回归loss异常三是初始学习率过大红外小目标数据集的梯度尺度更大0.01的初始学习率对yolov8n在小数据集上可能偏高。解决按顺序三步走先清洗数据剔除异常图再把mosaic降到0或0.3减少目标被裁剪破坏的概率最后把lr0降到0.005或0.001。改完这三步bn崩溃的问题基本不会再出现。如果依然有loss抖动检查标签txt里有没有归一化坐标大于1或小于0的值转换脚本里漏了clip操作也会造成这个问题。5.2 验证集指标高但实际检测很差数据泄漏和划分脚本的锅现象训练日志里val mAP50到了0.9以上测试集效果却差得离谱漏检率很高。第一反应是模型过拟合但把训练轮数调低后依然如此这时候要怀疑验证集和训练集太像了。原因大概率是第2.3节说的数据泄漏。红外飞机图如果是视频连拍抽帧随机划分会让同一段飞行动作的相邻帧同时进入train和val验证集成了开卷考试模型记住的是帧间相似性而不是目标的通用特征。另一个常见原因是划分脚本bug图片移动了标签没跟着移动导致val集实际为空ultralytics在验证时静默跳过日志里的mAP是最后一次train batch的伪指标。解决方法是重写划分脚本按视频片段分组后再划分保证同一片段只进一个集合。同时加一道校验val集里随机抽10张图手动数一下有没有标签并用训练好的模型跑一遍预测确认能正常画出框。没有验证集的训练日志等于没有指标这种翻车最隐蔽也最伤时间。5.3 混淆矩阵总和不是1yolo混淆矩阵总合不唯一的真凶现象训练结束后画混淆矩阵发现所有数字加起来不等于样本总数或者和预期的目标数对不上。这不算模型错误而是理解偏差。原因是混淆矩阵统计的是预测框和真实框在IoU匹配阈值下的匹配关系一个真实框最多匹配一个预测框但背景类别会统计所有未匹配的预测框所以矩阵里面除了airplane类还有一个background列或行把所有格子的数加总自然不等于目标总数而是等于真实目标数误检框数。yolo混淆矩阵总合不唯一这个说法往往是把背景类别漏算了。解决方法是不要追求总和等于GT数而是看对角线上的数值占比尤其关注airplane这一行的漏检率是多少background那一行里有多少误检框。如果你用的是coco格式评估工具还要确认类别顺序和id是否对齐coco的category_id从1开始yolo的class_id从0开始错一位整个矩阵就乱了。5.4 检测框整体偏移半张图转换脚本里除错了宽高现象训练出来的模型能检测到目标但画出的框整体偏移框的位置在目标的上方或左上方偏移几十上百像素目标越大偏移越明显。原因不是模型问题是标签坐标错了。最常见的错误是voc转yolo时把x_center除以了错误的尺寸比如原图实际是1920×1080脚本里读到的却是某次resize后的640×640或者转换时把xmin和ymin直接当作中心坐标没有加上半宽半高。另一类错误是coco格式的bbox是左上角坐标加宽高转yolo时直接拿bbox[0]当x_center来算忘了加w/2。解决方法是给一张已知的图写个验证脚本用opencv读原图根据yolo标签的坐标还原像素坐标并画框和voc原标注叠加对比人工确认是否重合。这个验证步骤每转换一个数据集都应该做一次别嫌麻烦它能在训练前拦住70%的标签错误。检测框偏移这种问题等训练完再发现返工成本就高了。5.5 小目标mAP始终为0anchor设置和输入分辨率的锅现象训练完mAP50有数值但mAP50-95很低或者按COCO尺寸分组后小目标那一组的AP是0。这在小目标检测里非常典型刚入坑的人容易怀疑模型能力不够。原因是模型的下采样倍率和默认anchor尺寸不匹配。YOLOv8默认anchor锚定在8、16、32倍下采样特征层如果输入是640最小特征层每个格子对应原图8×8像素。一个16×16像素的飞机在8倍下采样层上只占2×2个格子特征少得可怜。更关键的是anchor初始化偏向COCO数据集的常规目标尺寸红外小目标的宽高往往只有十几像素和预设anchor相差太远。解决方法有两个方向一是把imgsz提到1280以上目标在特征图上占据更多像素本质上是把小目标放大成中目标二是采用切片推理方案把大图切成无重叠的块分别检测再合并结果。训练侧还可以把anchor的宽高范围手动向小尺寸方向收缩YOLOv8支持自动anchor进化在小数据集上可以关掉自动统计显式指定anchor尺寸。先做imgsz提升成本最低见效也最快。6. 验证与进阶用混淆矩阵和置信度曲线把漏检率再压一截模型训练完别急着部署先用val集做一轮细致的验证分析。YOLOv8自带混淆矩阵和F1-confidence曲线这两个工具能把模型的问题暴露得很清楚。yolo detect val modelruns/detect/train/weights/best.pt \ datadataset/dataset.yaml \ conf0.25 \ imgsz1280上面的命令会输出混淆矩阵图和f1_curve.png、pr_curve.png等文件。打开混淆矩阵重点关注airplane类所在行如果对角线的值占了80%以上说明主类别识别稳定如果background那一行的值不小说明误检集中在背景噪声上这时你可以把conf阈值往上调用f1_curve.png找F1最大值对应的置信度阈值把这个值写进推理参数里能明显降低误检框数量。进一步进阶可以用切片推理。红外飞机图分辨率通常很高整张图直接放大到1280会丢失目标细节但如图分辨率只有640×512直接推理即可。如果是1920×1080的大图我一般把图切成512×512的块检测完按坐标拼回去过滤掉重叠框。这个思路在电力红外检测、遥感小目标场景里都适用属于不换模型就能提点的手段。最后说一个我养成的习惯每次训练完随机抽30张测试图把预测框画出来人工看一遍不看指标只看框。红外小目标检测的指标曲线再漂亮都不如眼睛确认几个典型场景来得踏实。新一轮训练前先复盘上一轮的漏检图是漏在远距离还是漏在强背景下再决定下一次调参方向。这个先看框、再调参的流程帮我省掉了很多在参数里瞎试的时间也希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑