ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

110张熊猫数据集VOC+YOLO双格式下的目标检测小样本训练全流程

110张熊猫数据集VOC+YOLO双格式下的目标检测小样本训练全流程 简介熊猫目标检测数据集以Pascal VOC与YOLO两种主流标注格式封装内容由一百一十张JPG图像、一百一十个XML标注文件及一百一十个TXT标签文件构成覆盖单一熊猫类别适合作为目标检测入门练习、格式转换实操或轻量级模型训练的数据基础。整包文件总数为三百三十二个除图片与两类标注外还包含少量补充说明文本压缩包体积约三十六点三四兆字节目录结构清晰便于直接接入YOLO、VOC等主流训练流程也可用于两种格式间的对照学习。全部一百一十四个目标框均由labelImg按矩形框规则绘制类别一致、定位规范能帮助使用者快速掌握单类别检测任务的数据组织与标注细节同时为验证数据加载、增强和评估管线提供干净样本。数据集已有约一百八十九人学习使用面向计算机视觉初学者、算法工程师以及需要同时使用VOC与YOLO格式的研究者是一份轻量且标注可靠的入门级目标检测数据资源。1. 110张熊猫图能做什么先看懂VOC和YOLO双格式的含金量收到一个名为“动物数据集65熊猫数据集VOC格式yolo格式110张1类别.zip”的数据包第一反应通常不是兴奋而是警惕110张、1个类别这个规模对目标检测来说是妥妥的小样本。任何声称“拿到数据集直接开训”的教程放到110张图上都大概率翻车。但这个包最值得关注的不是张数而是它同时给了VOC格式和yolo格式两套标注。常见做法是数据集只给一种格式或者给的是别人已经切好的训练集而这里选择把两种主流格式都做了一份说明交付方至少考虑了使用者的迁移成本。这种小尺寸双格式数据集真正的价值不在“够不够训出一个能上线的模型”而在于它足够小能让你在几小时内把“数据体检 → 格式转换 → 训练 → 验证 → 补数据”整条链路跑通。本文会按拿到zip之后的真实顺序走一遍先做数据画像再做VOC与YOLO互转然后谈110张图怎么训练最后用难例挖掘把数据集榨干。适合手里恰好有类似小数据集、准备用yolov5或yolov8训练自己的数据集的读者。2. 解压先于训练核对目录结构、图片完整性与双格式标注一致性拿到zip先别急着解压丢进训练脚本。目标检测的数据链路里标注文件与图片对不上是绝大多数训练事故的源头而且这类问题在110张的小数据集上更容易被忽视——因为张数少很多人会认为“不会有问题”。我习惯的做法是先解压再写一个十行左右的体检脚本把图片数、标注数、类别分布一次性打出来。2.1 目录结构与文件命名先搞清VOC和YOLO各自的“隐含约定”解压后第一件事是看目录长什么样。VOC格式的数据集通常沿用Pascal VOC的目录约定Annotations/放xml标注JPEGImages/放图片ImageSets/Main/放train.txt、val.txt这类划分文件。而yolo格式的数据集一般只有两个平行目录images/和labels/同一张图片的标注是文件名相同、后缀从.jpg变成.txt。这两种布局的差别决定了后续脚本怎么写。VOC格式里xml内部会记录图片文件名和图片尺寸即使xml和图片不同名也能靠内部字段找回对应关系yolo格式则完全靠同名匹配一旦图片被改名、复制、去重txt就会静默失联。很多把这两套格式放在同一个zip里的数据集实际上是用转换脚本生成的那么转换时是否带着正确的图片路径就成了第一个要验证的点。还有一个细节有些数据集给的是Annotations/和JPEGImages/但图片其实是PNG或者xml里记录的filename带中文这些都会在训练时报出极其隐晦的错误。不要凭文件名后缀猜测要把所有文件扩展名统计出来再看。2.2 用脚本盘点图片和标注缺图、缺xml、缺txt一目了然我一般会写一个快速盘点脚本把图片、xml、txt全扫一遍做三件事统计数量、按文件名配对、把类别分布打印出来。脚本如下。import xml.etree.ElementTree as ET from pathlib import Path from collections import Counter root Path(动物数据集65熊猫数据集VOC格式yolo格式110张1类别) # 解压后的根目录按你的实际情况改 img_exts {.jpg, .jpeg, .png, .bmp} images [p for p in root.rglob(*) if p.suffix.lower() in img_exts] xmls list(root.rglob(*.xml)) txts list(root.rglob(*.txt)) print(f图片总数: {len(images)}) print(fVOC格式xml: {len(xmls)}) print(fYOLO格式txt: {len(txts)}) img_stems {p.stem for p in images} xml_stems {p.stem for p in xmls} txt_stems {p.stem for p in txts} print(有图片但缺少xml:, len(img_stems - xml_stems)) print(有图片但缺少txt:, len(img_stems - txt_stems)) print(有xml但没有图片:, len(xml_stems - img_stems)) print(有txt但没有图片:, len(txt_stems - img_stems)) all_names Counter() for x in xmls: root_xml ET.parse(x).getroot() for obj in root_xml.iter(object): all_names[obj.findtext(name)] 1 print(VOC标注中的类别分布:, all_names)这里用rglob(*)递归扫描不依赖固定的目录层级即使解压后文件名带有多层嵌套也能扫到。用Path.stem去掉后缀做配对是为了把三种文件用纯文件名联系到一起。最后一段解析xml并统计类别名是本文目前最值得留意的地方很多号称“1类别”的数据集实际xml里的类别名五花八门比如panda、giant_panda、panda_bear混着写后面做转换时类别表一错整个训练就白跑。参数说明img_exts集合决定了哪些文件算图片如果数据集里混入tiff等冷门格式rglob能扫到但会被这里过滤。建议把脚本跑出来的“有图片但缺少标注”的数量重点看这个数字一旦超过个位数先排查是不是图片目录和标注目录命名规则不一致。2.3 标注一致性初检VOC的xml和YOLO的txt是不是同一套框双格式数据集还有一个隐蔽问题两套标注可能是分别生产的。比如甲方先让人用labelimg打了VOC格式的xml之后又找人用另一套脚本转成了yolo格式的txt转换过程完全可能丢框、错位、漏行。即便是同一套标注源xml里的数值在转换时被四舍五入、类别被重排都会造成不可逆的偏差。我建议在训练前写一个对比脚本把同名xml和txt各自读取后比较每张图片的检测框数量并抽查几个框的坐标是否落在同一位置。核心代码如下。import cv2 import numpy as np def read_voc_boxes(xml_path): root ET.parse(xml_path).getroot() boxes [] for obj in root.iter(object): bnd obj.find(bndbox) xmin int(float(bnd.findtext(xmin))) ymin int(float(bnd.findtext(ymin))) xmax int(float(bnd.findtext(xmax))) ymax int(float(bnd.findtext(ymax))) boxes.append((xmin, ymin, xmax, ymax)) return boxes def read_yolo_boxes(txt_path, img_w, img_h): boxes [] for line in Path(txt_path).read_text().strip().splitlines(): parts line.split() if len(parts) ! 5: continue cls, x_c, y_c, bw, bh parts x_c, y_c, bw, bh map(float, (x_c, y_c, bw, bh)) xmin int((x_c - bw / 2) * img_w) ymin int((y_c - bh / 2) * img_h) xmax int((x_c bw / 2) * img_w) ymax int((y_c bh / 2) * img_h) boxes.append((xmin, ymin, xmax, ymax)) return boxes这段代码把YOLO格式的归一化中心点坐标还原成绝对像素以便和VOC的坐标直接对比。注意read_yolo_boxes依赖外部的img_w和img_h读取方式最好向cv2.imread要真实尺寸而不是直接信任xml里的size字段——我之前遇到过xml里写1920x1080、实际图片被压成640x360的情况两者比例一致时碰巧没事比例不一致时框全部漂移。比对时用len(read_voc_boxes(xml))对比len(read_yolo_boxes(txt))框数不一致的文件单独打印出来。这类问题在110张的数据集上通常只有几例但影响极大一个xml里漏了远处的熊猫模型就会学到“熊猫必须近景”。初检通过后才进入下一步的格式转换工作。3. VOC与YOLO格式互转坐标归一化、类别映射和反向验证如果你打算用yolov8或yolov5训练最终喂给模型的是yolo格式的txt。这个zip里虽然已经有了yolo格式但我不建议直接拿来用而是先自己动手从VOC侧转一遍。原因有两个一是可以验证交付方给的yolo标注有没有错误二是你迟早会遇到手里只有VOC格式、需要自己转的情况。这个技能是目标检测的基本功。3.1 两种格式的本质差异绝对像素框与归一化中心点框VOC格式的xml里一个目标表示为object namepanda/name bndbox xmin123/xmin ymin45/ymin xmax300/xmax ymax280/ymax /bndbox /objectxmin、ymin、xmax、ymax全部是图片上的绝对像素坐标。而yolo格式的txt每一行只存五个数字类别id、归一化后的中心点x、中心点y、宽、高。两者的换算关系是x_center (xmin xmax) / 2 / img_width y_center (ymin ymax) / 2 / img_height w (xmax - xmin) / img_width h (ymax - ymin) / img_height注意yolo里的w和h是中心点框的宽度和高度不是右下角坐标。很多新手在这里犯迷糊把w和h当成xmax和ymax导致转出来的框永远是歪的。归一化的好处是不管图片怎么resize标注都不需要跟着改缺点是你看到txt里的0.5根本不知道对应的像素是多少必须借助画框工具才能验证。还有一点要记住yolo的类别id从0开始。1个类别就是只有class 0类别名字本身不写进txt而是写在一个data.yaml或classes.txt里模型训练时靠id索引。3.2 转换脚本VOC转YOLO并生成data.yaml下面是一个完整的转换脚本核心思路是遍历所有xml读box换算坐标写txt。每张图之间没有依赖可以放心批量跑。import xml.etree.ElementTree as ET from pathlib import Path from PIL import Image class_names [panda] # 类别表顺序决定了class id绝对不要乱动 def voc_to_yolo(xml_path, out_txt_path): root ET.parse(xml_path).getroot() # 用真实图片尺寸计算避免xml里的size字段失真 img_path root.findtext(path) if not img_path or not Path(img_path).exists(): img_path xml_path.parent.parent / JPEGImages / (Path(xml_path).stem .jpg) with Image.open(img_path) as im: img_w, img_h im.size lines [] for obj in root.iter(object): name obj.findtext(name) if name not in class_names: print(f跳过未知类别 {name}: {Path(xml_path).name}) continue cls_id class_names.index(name) bnd obj.find(bndbox) xmin float(bnd.findtext(xmin)) ymin float(bnd.findtext(ymin)) xmax float(bnd.findtext(xmax)) ymax float(bnd.findtext(ymax)) if xmax xmin or ymax ymin: print(f跳过异常框: {Path(xml_path).name} ({xmin},{ymin},{xmax},{ymax})) continue x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) Path(out_txt_path).write_text(\n.join(lines) \n)逻辑说明脚本优先从xml的path节点找图片如果path是绝对路径且已经失效则回退到Annotations的同级目录JPEGImages/下按文件名猜。用PIL读取真实尺寸是关键一步因为xml的size在历史数据集里经常被修改或丢失。参数说明class_names这个list的顺序就是yolo格式里的class id顺序。如果数据集里类别名是giant_panda而你在这里写了panda那么所有框会被跳过反过来如果xml里有两种写法但你都留在类别表里同一个类别就会拿到两个id。建议先跑一遍2.2节的类别统计把真实类别名填进来。转换完成后需要生成data.yaml# dataset/data.yaml path: /绝对路径/到/dataset # 可选的根路径 train: images/train val: images/val nc: 1 names: [panda]names的顺序必须和上面class_names的顺序完全一致。这里容易埋坑如果转换脚本用[panda]生成了txt而data.yaml里写的是[giant_panda]训练时模型会把class 0命名为giant_panda看起来一切正常但你的loss曲线和验证结果全是指向panda的人工审查时会被名字误导。3.3 转完必须做的反向验证把txt框画回图上转换脚本跑完之后不要直接开训先做一次反向验证把生成的txt框画回图片上肉眼抽查10张以上。这一步能挡住坐标除错、边界框越界、类别错位这类最脏的问题。import cv2 from pathlib import Path def draw_yolo_boxes(img_path, txt_path, class_names, out_pathNone): img cv2.imread(str(img_path)) if img is None: print(f图片读取失败: {img_path}) return h, w img.shape[:2] for line in Path(txt_path).read_text().strip().splitlines(): parts line.split() if len(parts) ! 5: print(f非法行 {line} in {txt_path.name}) continue cls, x_c, y_c, bw, bh parts cls int(cls) x_c, y_c, bw, bh map(float, (x_c, y_c, bw, bh)) x1 int((x_c - bw / 2) * w) y1 int((y_c - bh / 2) * h) x2 int((x_c bw / 2) * w) y2 int((y_c bh / 2) * h) x1, y1 max(0, x1), max(0, y1) x2, y2 min(w, x2), min(h, y2) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, class_names[cls], (x1, max(0, y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) out_path out_path or (img_path.parent / vis / img_path.name) Path(out_path).parent.mkdir(parentsTrue, exist_okTrue) cv2.imwrite(str(out_path), img)逻辑说明cv2.rectangle的坐标必须是整数所以把归一化坐标乘以图片真实的w和h后要转int。x1,y1,x2,y2用max/min做了一次越界裁剪这是为了防止异常标注把框画到图片外面导致后面训练时读取越界数据。把所有验证图输出到一个vis目录按文件名批量拼接成网格比一张张打开高效得多。参数说明out_path不传时会自动在图片同级生成vis/目录方便和原图对照。class_names这里只是用来在图上写字即使写错也不会报错所以要特别留意图上标的文字和实际框的内容是否吻合。做完反向验证如果发现框全部偏移优先检查归一化时除的是不是图片真实宽高如果只有个别框越界直接删除对应txt行小数据集里脏数据越少越好。我见过有人不愿意删结果那一个错位框让mAP掉了3个点不值当。4. 110张小样本的YOLO训练迁移学习、数据增广与超参数设定数据体检和格式转换完成终于可以聊训练。110张图的训练策略和几千张图的完全不一样核心原则是不要追求大模型、不要开满血增强、不要真的跑满200轮。每一步克制都是为了在小数据上不快速过拟合。4.1 训练集划分别把110张全丢进去乱跑训练前先把数据划分好。我建议划分成88张训练、22张验证不单独留测试集。原因很简单110张里再挖20张做测试训练数据就只剩70张验证集的置信度都搭不稳。真正的测试留到你收集到新图、或人工抽查难例时再做。划分脚本如下import random from pathlib import Path from sklearn.model_selection import train_test_split random.seed(42) images sorted(Path(dataset/images).glob(*.jpg)) train_imgs, val_imgs train_test_split(images, test_size0.2, random_state42) for split, imgs in [(train, train_imgs), (val, val_imgs)]: (Path(dataset/images) / split).mkdir(parentsTrue, exist_okTrue) (Path(dataset/labels) / split).mkdir(parentsTrue, exist_okTrue) for img in imgs: txt Path(dataset/labels) / (img.stem .txt) img.rename(Path(dataset/images) / split / img.name) if txt.exists(): txt.rename(Path(dataset/labels) / split / txt.name)逻辑说明脚本先把图片列表按8:2随机切分随后按split目录归位图片和同名txt。random.seed(42)是为了让这次划分可复现同一份数据每次执行结果一致这是复现实验结果的前提。参数说明test_size0.2在110张里等于22张验证图。对小数据集来说20%的验证集比例已经偏高不建议再加大。如果验证集只有十来张一次随机的坏运气就会让mAP波动得很吓人。另外这种朴素随机划分假设图片之间相互独立如果你的110张图里有大量连拍帧必须先按视频片段或拍摄场景分组否则训练集和验证集会高度相似训练loss很漂亮落地全崩。4.2 迁移学习与预训练权重为什么从yolov8n.pt开始而不是从零训练110张图从零训练一个检测器结果基本是灾难。目标检测的head部分至少需要几万张图才能学到稳定的框回归特征110张只够让模型记住这110张图的样子。常见做法是加载COCO预训练权重继续训练。yolov8和yolov5都支持直接指定一个.pt文件作为初始权重它的backbone已经学会了通用的边缘、纹理、形状特征你只需要微调输出层让它从“认识COCO的80类”变成“只认识panda”。这一招能把训练所需的数据量降低一个数量级。命令如下# yolov8 yolo detect train datadataset/data.yaml modelyolov8n.pt \ epochs200 imgsz640 batch16 patience20 \ projectruns namepanda_exp # 还在用yolov5的话 python train.py --data dataset/data.yaml --weights yolov5s.pt \ --epochs 200 --batch-size 16 --img 640 --patience 20逻辑说明modelyolov8n.pt会先下载COCO预训练权重到本地缓存之后的训练从这个权重开始。epochs200看着很多但配合patience20验证集20轮不涨就提前停止实际通常跑到五六十轮。参数说明batch16在110张图里意味着每个epoch只有5~6个batch模型每轮看到的有效信息非常有限增大batch只会让单轮时间变长并不会带来明显收益。imgsz640是常见默认值如果熊猫在画面里占比很大比如单只熊猫占了图片一半以上可以降到512提速的同时对精度基本无损。4.3 关键超参数mosaic、翻转、HSV增强怎么设小数据集上超参数的核心矛盾是增强过猛导致过拟合、增强太弱导致欠拟合。yolov8默认开了mosaic1.0也就是每张训练图由4张图拼成这对大数据集是有益的正则化但对110张图来说拼出来的图块会把熊猫截断反而制造大量残缺样本。我一般在命令行显式覆盖几个增强参数yolo detect train datadataset/data.yaml modelyolov8n.pt \ epochs200 imgsz640 batch16 patience20 \ mosaic0.3 hsv_h0.02 hsv_s0.7 hsv_v0.5 \ degrees10 flipud0.0 fliplr0.5 scale0.5参数说明逐条说mosaic0.3意味着只有30%的训练样本走四图拼接其余保持原图避免熊猫主体被切碎。hsv_h、hsv_s、hsv_v是色调、饱和度、明度的随机扰动范围这三个是对小数据集最友好的增广因为改变颜色分布不会破坏目标结构。degrees10允许图片随机旋转10度超过这个值背景容易出现大片黑边。flipud0.0关掉上下翻转因为熊猫照片绝大多数是从水平视角拍的上下翻转产生的样本违背真实分布fliplr0.5保留左右翻转这个对小目标检测是安全的。scale0.5表示缩放比例在0.5到1.5之间随机变化加上yolo自带的mosaic已经足够。注意这些超参数不是玄学是围绕“熊猫不会倒立、不会变色、不会被切成两半”这个先验设的。换一个检测场景比如俯拍的无人机视角这些参数就要重新推。4.4 训练过程中看什么loss曲线和过拟合的判别训练启动后不要只盯着终端里每轮的mAP。110张的小数据集上验证集mAP的波动本来就大上一轮0.85下一轮0.72都很正常。我一般看runs/panda_exp/results.png里的两条曲线train_loss和val_loss。如果train_loss持续下降、val_loss在某一轮掉头向上说明模型开始把训练集细节背下来了这就是过拟合的典型信号。此时优先做的事情是把mosaic调高一点、把degrees加大一点、增加hsv扰动然后重新训练。如果val_loss始终下不去说明验证集里存在和训练集分布差异很大的图需要把这些图挑出来看看是不是标注错了。还有一个容易被忽略的点best.pt是每轮在验证集上表现最好的权重last.pt是最后一轮的权重。小数据集上我习惯训练结束后用best.pt重新跑一遍全部训练集如果它在训练集上的mAP都不到0.9说明这个数据集本身存在标注质量问题别急着补数据先重新核对标注。5. 小样本熊猫检测的避坑记录五个常见翻车点与排查方法在目标检测领域有一句经验模型结构的问题占两成数据的问题占八成。110张小样本数据集尤其如此下面五个坑是我处理类似数据集时反复遇到的每条按“现象 → 原因 → 解决”来写。5.1 文件命名和格式类翻车坑1xml里的filename和实际图片名对不上。现象训练时提示找不到图或者图片能读但loss不下降验证集的mAP一直是0。原因标注工具或脚本生成xml时filename写的是标注当时的文件名后来图片被批量重命名xml内部字段却没有跟着改。VOC格式的读取逻辑依赖xml的filename去找图yolo格式靠txt同名匹配所以这个坑主要出现在VOC格式里。解决用2.2节的stem_set配对逻辑找出所有不一致的xml写脚本把xml的filename批量改成实际文件名。如果图片也被移动过还需要同步修正path字段。记住文件名只要动一次就必须重新跑一遍配对不能手动改几张就完事。坑2yolo格式的txt文件里有空行、逗号分隔符或者多了引号。现象训练开始就报invalid label file或者训练能跑完全部epoch但mAP极低。原因txt文件被Excel打开过再保存分隔符从空格变成了逗号或者转换脚本在拼接字符串时用了,。yolo格式的txt标准是空格分隔很多库的解析器用split()切分遇到逗号会整体当成一个字段而解析失败。解决训练前加一道校验脚本遍历所有txt检查每行split()后的长度是否恰好为5不是就原样打印文件名和内容。转换脚本统一用 连接不要用,。Excel编辑过的手改文件直接删掉从源头重新生成。5.2 坐标和语义类翻车坑3坐标归一化时除错了图片尺寸。现象反向验证画出的框整体偏到左上角或者框的比例明显变形。如果只是看数值很难发现因为归一化后的数值永远在0到1之间看不出和图片实际内容的关系。原因转换时用了xml里的size节点做分母但xml里的size和真实图片尺寸不一致。比如xml写1920x1080实际图是640x360如果长宽比恰好一样框的相对位置碰巧是对的如果图片被裁剪过长宽比变了归一化结果整个错乱。还有一种情况是代码把x除以了img_h、y除以了img_w属于手滑。解决所有归一化和反归一化都从真实图片读取宽高用PIL.Image.open或cv2.imread后取shape。写转换脚本时别用xml的size做唯一依据xml里的size只能作为参考。坑4类别id映射错位。现象训练正常loss正常但model.predict输出的类别名和预期不符或者单类模型在验证集上mAP为0。110张1类别时最容易出现的现象是明明只有一个类画框验证时文字却显示成其他类别名或者所有框的class id都是1而不是0。原因yolo的class id完全由txt第一个数字决定而这个数字在转换时由class_names的列表顺序决定。如果labelimg打标时先打了别的占位类别或者转换脚本里类别表用的是另一份顺序txt里的id和data.yaml里的names就会错位。更隐蔽的是数据集作者先做了VOC格式转换后来加新类时在中间插入导致已有txt全部要重新生成。解决固定一份classes.txt作为全项目唯一数据源转换、训练、推理都读它。发版前用脚本检查所有txt里的类别id是否都在range(nc)范围内超出就报错。5.3 训练与验证类翻车坑5用小验证集判断模型是否过拟合结果每一步都像过拟合。现象val_loss在训练中途开始上涨但mAP却在上升或者每轮的验证指标剧烈摆动让人怀疑数据没对齐。原因22张验证图太少了任何一张图被随机翻转、曝光变化都会造成指标的大幅波动。再加上mosaic增广在验证时不生效训练和验证的分布天然有差异小验证集把这个差异放大成了“过拟合”的假象。解决验证时不要逐轮看直接把patience调到25左右允许指标波动让它跑完再看。如果确实想判断过拟合加载best.pt对22张验证图逐张画框对比而不是盯一条曲线。这种时候用眼睛看比用数字量更可靠一张张检查把所有漏检和误检截图存下来这才是小数据集的常规操作。6. 用混淆矩阵和硬例挖掘榨干110张数据小数据集的迭代验证闭环训练完成后模型已经见过全部训练集中的熊猫但你要验证的不只是它在已知数据上的表现而是它到底漏了什么。对110张的小数据集来说最有效的下钻动作不是调超参数而是做一次“硬例挖掘”找出模型置信度低、漏检、误检的图片针对性地补数据或修正标注。先用模型跑一遍验证集把每张图的预测框输出到文件from ultralytics import YOLO model YOLO(runs/panda_exp/weights/best.pt) results model.predict(sourcedataset/images/val, save_txtTrue, conf0.25)然后逐张统计每张图片的gt框数和预测框数。gt框数可以从txt目录读预测框数从runs/detect/predict/labels/里读。两张数量对不上的图优先挑出来人工看。常见的结论是漏检的往往是同一类图片——背面熊猫、被树干遮挡的熊猫、远处小目标熊猫。把这些图片拼接成一张“难例墙”你就知道下一批该找什么样的数据了。这比盲目把mosaic开到1.0有用得多。mosaic只能让模型在现有数据里打转难例挖掘才能告诉你数据的边界在哪。我现在拿到任何小数据集第一件事永远是写校验脚本把标注画出来看一遍再谈训练。这个习惯救了我好几次每次都能在开训前揪出一堆“看起来没问题、一画全跑偏”的标注。希望在110张熊猫数据上你也能用这一套流程少走弯路。希望帮到你。本文还有配套的精品资源点击获取
返回列表