简介机械常用工具检测数据集面向计算机视觉目标检测任务涵盖 crowbar、gasolinecan、hammer、pliers、rope、screwdriver、toolbox、wrench 共8类工具包含4713张真实场景图片与6962个标注框。资源同时提供Pascal VOC格式xml和YOLO格式txt标注可无缝用于YOLO系列、Faster R-CNN等主流检测框架的训练与验证适合初学者入门或工程师进行工业场景工具识别模型迭代。压缩包内共2000个文件标注文件与图片一一对应整体大小87.82MB轻量易下载。目前已有352人学习下载数据完整、格式规范经labelImg工具人工画框标注类别分布与数量已在说明文档中详细列出便于数据均衡分析与抽样检查。对需要标准检测数据集的开发者来说这是一份可直接投入使用的现成资源。1. 拿到机械常用工具检测数据集先看清VOCYOLO双格式机械常用工具检测数据集VOCYOLO格式4713张8类别.7z是一份同时带VOC和YOLO两套标注的工具检测数据4713张图、8个常见工具类别解压后可以直接进入目标检测训练流程。双格式的价值在省时间VOC的XML保留原始坐标方便核对YOLO的TXT直接喂训练脚本。对刚入目标检测的团队这份数据能把标注和格式转换的工作量压到最低适合练手和原型验证。但解压不等于能训练。类别顺序、归一化坐标、类别不均衡都会在训练阶段变成代价。下面按我处理这类压缩包的流程走一遍解压体检、VOC转YOLO、YOLOv8训练、避坑与验证。2. 解压7z与数据体检4713张图先别急着训练2.1 Linux和Windows解压7z命令、参数与常见报错拿到.7z文件第一件事不是看标签是先完整解压。Windows下用资源管理器双击解压解到一半弹“无法作为归档打开”或者CRC校验失败的情况很常见这种问题越早暴露越好。我一般习惯先在命令行里做一次完整解压并校验确认压缩包本身没坏再开始碰数据。Windows有7-Zip的话最稳的是右键解压到指定目录。命令行也可以7z x tools.7z -oD:\tools_data注意-o后面紧跟输出路径不能有空格。参数x表示保留压缩包内目录结构解压如果写成e所有文件会被平铺到同一目录文件多、目录深时容易乱套。Linux下常见做法是先装p7zip-full然后测试和解压两步走# 安装 p7zip-full提供 7z 命令行工具 sudo apt install p7zip-full # 测试压缩包完整性先过这一关再解压 7z t mechanical_tools.7z # 完整解压并保留目录结构 7z x mechanical_tools.7z -o/home/user/datasets7z t只测试、不落盘专门用来检查压缩包有没有在下载或者拷贝过程中损坏。解压时报CRC failed、Unexpected end of archive这类错误优先怀疑压缩包自身问题而不是工具版本不对。Linux下解压7z文件最常见的坑就是少装了p7zip只装p7zip不带-full的话部分格式支持不全建议直接装p7zip-full。这里有一个老生常谈的问题7z压缩文件密码是正确的但一直报错。多数情况不是密码错而是终端编码问题尤其密码里带中文或特殊符号时。解决方法是把密码写进脚本、用UTF-8执行或者直接改用7-Zip图形界面输入。这个坑和数据集本身无关但赶上了解压不出来能折腾一下午。解压完成后别急着删压缩包。我先核对三样东西图片数量、标签文件数量、目录结构。工具检测数据集按惯例VOC部分会用JPEGImages存放图片、Annotations存放XML、ImageSets/Main存放划分列表YOLO部分通常分images和labels两个主目录。两边图片数量对不上说明解压不完整或者压缩包本身带了筛选后面会连环出错。2.2 数据体检先统计类别分布和图片尺寸压缩包解压后第一件事不是打开图片看画质而是写脚本做一次静态统计。常见做法是扫描labels目录下所有TXT统计每个类别出现的目标数量同时统计图片尺寸分布。这一步能快速判断类别是否均衡、图片是否都能被正常读取比肉眼翻图高效得多。# stats.py from pathlib import Path from collections import Counter from PIL import Image label_dir Path(labels) img_dir Path(images) class_counter Counter() img_sizes set() img_count 0 for img_path in img_dir.iterdir(): if img_path.suffix.lower() not in (.jpg, .jpeg, .png): continue img_count 1 with Image.open(img_path) as im: img_sizes.add(im.size) for label_path in label_dir.glob(*.txt): for line in label_path.read_text().strip().splitlines(): parts line.split() if len(parts) 5: class_counter[int(parts[0])] 1 print(images:, img_count) print(sizes:, img_sizes) print(class distribution:, sorted(class_counter.items()))逻辑说明class_counter按类别ID累加目标数img_sizes用集合去重能一眼看出图片尺寸是否统一。print输出的前半部分是类别ID后半部分是该类目标总数。类别ID是YOLO格式TXT里的第一个数字必须和训练时的names顺序一一对应这一步就能提前发现“有个类别只有几十个框”这类失衡问题。参数说明脚本默认图片直接放在images目录、标签直接放在labels目录。如果解压后多了train/val子目录把img_dir.iterdir()换成img_dir.rglob(*)labels同理。图片后缀筛了jpg、jpeg、png三种遇到webp或bmp需要自行补充。PIL读取失败会直接抛异常正好用来定位损坏图片。统计结果里我重点关注两件事。第一有没有类别目标数少到个位数。8个类别里如果某类只有几十条标注训练时这个类别AP会很难看后面要么补数据、要么单独调阈值。第二图片尺寸差异。YOLO训练时imgsz参数会强制缩放尺寸极端不均匀会引入大量letterbox留边小目标召回率下降。看到这种情况训练时的imgsz就得保守一点。2.3 标签文件解剖XML和TXT里到底存了什么体检完下一步是抽几张图同时打开它的XML和TXT确认标签是完整的、两份格式能对上。VOC格式的XML是树状结构关键字段有filename、size下的width/height以及每个object节点的name和bndbox坐标。YOLO格式的TXT则每行一个目标五个数字分别表示类别ID、归一化中心x、中心y、宽、高。写一个小脚本随机抽三个文件对照看# inspect_label.py import xml.etree.ElementTree as ET from pathlib import Path import random def show_xml(path): tree ET.parse(path) root tree.getroot() file_tag root.find(filename).text w root.find(size/width).text h root.find(size/height).text print(f[XML] {file_tag} size{w}x{h}) for obj in root.findall(object): bnd obj.find(bndbox) print( obj:, obj.find(name).text, xmin, bnd.find(xmin).text, ymin, bnd.find(ymin).text, xmax, bnd.find(xmax).text, ymax, bnd.find(ymax).text) def show_txt(path): print(f[TXT] {path.name}) for line in path.read_text().strip().splitlines(): cls, xc, yc, w, h line.split() print(f cls{cls} xywh({xc},{yc},{w},{h})) xml_dir Path(Annotations) txt_dir Path(labels) all_xml sorted(xml_dir.glob(*.xml)) for xml_path in random.sample(all_xml, 3): show_xml(xml_path) txt_path txt_dir / (xml_path.stem .txt) if txt_path.exists(): show_txt(txt_path) print(---)脚本默认随机抽样每次运行结果不同想固定样本可以手动写死文件名。输出里能看到同一个文件的XML和TXT描述的是同一批目标。注意两点XML的bndbox是像素坐标TXT的xywh是归一化比例。如果两份文件里的目标数量不一致说明转换过程丢了框这是双格式数据集最需要提防的暗病。参数说明random.sample(all_xml, 3)抽3个文件想多核对就改成5或8。TXT路径用xml_path.stem拼接前提是两份文件同名VOCYOLO双格式数据集基本都遵循这个命名约定。如果TXT不存在脚本会跳过打印这类图片需要拉出来单独查训练时图片没有对应标注会直接影响loss计算。到这里数据集的底子已经摸清了。目录结构完整、类别数量和预期一致、XML和TXT能对上做格式转换和训练时才有底气。这三个步骤加起来不到十分钟能省掉后面好几个小时的返工。3. 把VOC转成YOLO格式转换脚本与四个边界坑3.1 两种格式的本质差异像素坐标与归一化中心VOC和YOLO的标注看起来都是“框”但存储方式完全不同直接把XML扔给YOLO是喂不进去的。VOC把每个目标写成xmin、ymin、xmax、ymax四个绝对像素值依赖XML的size字段才知道图片宽高YOLO则要求每行一个目标格式固定为“类别ID 中心x 中心y 宽 高”所有值归一化到0到1之间。归一化的意义在尺度无关同一份标注在640和1280两种分辨率下都能直接复用。两者的差异可以浓缩成一张对照表属性VOC XMLYOLO TXT框坐标xmin/ymin/xmax/ymax 像素值x_center/y_center/w/h 归一化值目标类别object标签内的name字符串行首整数类别ID从0开始图片尺寸size节点存放宽高不存放在TXT里由图片自身决定多目标每个object节点一个目标每行一个目标类别顺序不影响解析必须与训练配置的类别顺序一致转换的核心就两件事把像素坐标除以图片宽高变成归一化值把类别字符串映射成固定顺序的整数ID。第一件事靠公式第二件事靠你手里的类别清单也是最容易翻车的环节。XML里的name写法五花八门大小写、空格、别名都可能不一致转换前最好统计一遍出现过哪些name确认和类别清单完全匹配。3.2 转换脚本从XML读出框并归一化写入TXT下面是最基本的VOC转YOLO脚本我处理这类双格式数据集时常用这套逻辑。脚本从Annotations目录读XML输出到labels目录输出文件与图片同名。类别顺序从外部清单读取不在脚本里硬编码后面改数据时不用动代码。# voc2yolo.py import xml.etree.ElementTree as ET from pathlib import Path # 类别顺序从这里读一行一个名称顺序就是YOLO的ID CLASSES Path(classes.txt).read_text().strip().splitlines() xml_dir Path(Annotations) out_dir Path(yolo_labels) out_dir.mkdir(exist_okTrue) def convert(xml_path): tree ET.parse(xml_path) root tree.getroot() w float(root.find(size/width).text) h float(root.find(size/height).text) # 防御size缺失时回退到图片实际尺寸 # img Image.open(xml_path.with_suffix(.jpg)); w, h img.size lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in CLASSES: print(fskip unknown class: {name} in {xml_path.stem}) continue cls_id CLASSES.index(name) bnd obj.find(bndbox) xmin float(bnd.find(xmin).text) ymin float(bnd.find(ymin).text) xmax float(bnd.find(xmax).text) ymax float(bnd.find(ymax).text) # 归一化并保证边界不越出[0,1] x_center (xmin xmax) / 2.0 / w y_center (ymin ymax) / 2.0 / h box_w (xmax - xmin) / w box_h (ymax - ymin) / h if box_w 0 or box_h 0: continue lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) if lines: (out_dir / (xml_path.stem .txt)).write_text(\n.join(lines)) for xml_path in xml_dir.glob(*.xml): convert(xml_path)逻辑说明CLASSES是全局唯一的类别顺序来源转换脚本、data.yaml、训练结果三方都看它。CLASSES.index(name)返回类别字符串在清单里的下标这个下标就是YOLO的类别ID。归一化用的是中心法x_center取xmin和xmax的中点再除以图片宽度box_w是xmax减xmin的差除以宽度。脚本遇到清单外的类别会打印警告并跳过这些警告信息很关键能暴露出标注里混入的杂散类名。参数说明w和h从XML的size节点读取这是VOC格式的标准字段。如果XML缺这个字段脚本注释里给了回退方案用PIL打开同名图片读实际尺寸。.6f控制写入精度6位小数对归一化坐标足够。box_w 0的过滤是为了去掉退化成点的无效框。双格式数据集通常已经带好转换结果写这个脚本是为了在两边对不上时能自己重新生成一份。转换完成后我用反向逻辑做校验抽几个TXT把归一化坐标乘回图片宽高画在原图上看框是否贴合目标。这一步花五分钟能挡住“框错位一整份”的灾难。用opencv或PIL画框都行核心是框和图像出现在同一张图上肉眼扫一遍就知道有没有系统性偏移。3.3 目录组织与train/val划分别把4713张全喂进去YOLO训练不喜欢把图片和标签堆在一个目录里。标准布局是images下分train和val子目录labels下同构地分train和valdata.yaml里两行路径就能说清训练集和验证集。常见的坑是只按文件名前缀随机划分忽略了TXT同步结果图片去了train、标签留在了val训练时大量图片没有标注。划分脚本必须保证图片和标签以“同名不同后缀”的方式成对移动。下面这段按8:2比例划分用固定随机种子保证可复现# split_dataset.py import random from pathlib import Path random.seed(42) img_src Path(images) label_src Path(labels) out_img_train Path(dataset/images/train) out_img_val Path(dataset/images/val) out_lbl_train Path(dataset/labels/train) out_lbl_val Path(dataset/labels/val) for d in [out_img_train, out_img_val, out_lbl_train, out_lbl_val]: d.mkdir(parentsTrue, exist_okTrue) imgs sorted([p for p in img_src.iterdir() if p.suffix.lower() in (.jpg, .png)]) random.shuffle(imgs) split int(len(imgs) * 0.8) train_imgs, val_imgs imgs[:split], imgs[split:] def move_pair(img_path, img_out, lbl_out): label label_src / (img_path.stem .txt) img_path.rename(img_out / img_path.name) if label.exists(): label.rename(lbl_out / label.name) for img in train_imgs: move_pair(img, out_img_train, out_lbl_train) for img in val_imgs: move_pair(img, out_img_val, out_lbl_val) print(ftrain{len(train_imgs)} val{len(val_imgs)})逻辑说明脚本先收集images目录下所有图片打乱后按比例切片。move_pair把同一stem的图片和标签成对移动只要图片和标签同名就不会出现标签跑丢的问题。random.seed(42)固定随机顺序同一份数据在别的机器上重跑能得到相同划分这对复现训练结果很重要。参数说明* 0.8是训练集比例目标检测常用80/20或者90/10。4713张按8:2划分大约是3769张训练、944张验证对多数8类检测任务够用。如果某个类别训练后AP特别差可以改成按类别比例做分层划分而不是纯随机。rename在跨目录移动时是原子操作比copy后删更省事也不会在中间状态留下两份文件。划分完成后验证集里每个类别的目标数也值得打印一遍。分层抽样是更稳的做法按图片包含的目标类别做加权抽样确保每个类别在验证集里都有代表避免稀有类别只出现在训练集里、验证时完全看不到。8类别工具数据的分布如果不均分层划分比纯随机更推荐。4. 用YOLOv8训练自己的数据集配置、命令与调参4.1 环境准备与预训练模型选择数据到位后进入训练环节。YOLO系列里我最常用Ultralytics的YOLOv8上手成本低训练命令统一预训练权重在首次运行时由框架自动处理。环境安装就一条命令# 创建虚拟环境并安装ultralytics python -m venv yolo_env source yolo_env/bin/activate pip install ultralyticspython -m venv yolo_env创建独立环境source进入环境pip install ultralytics把依赖装进这个环境避免污染系统Python。安装后命令行里就有了yolo命令。第一次跑训练或验证时框架会自动下载对应的预训练模型权重网络正常情况下不用手动准备。选型上有个原则4713张的规模不算大8个类别也不复杂预训练模型建议从yolov8n或yolov8s起步不要直接上yolov8l或yolov8x。大模型在小数据集上更容易过拟合训练时间却翻几倍。预训练权重的作用是提供一个已经在COCO上学过的特征提取主干工具这类有明显边缘和纹理的物体迁移效果一般不错。n版本体小、单卡训练快适合先把训练链路跑通确认数据没问题后再换s或m提精度。我通常第一轮用n跑主要看loss能不能降、mAP能不能到及格线而不是追求最终精度。4.2 data.yaml与训练命令参数怎么设YOLOv8要求的配置文件是data.yaml内容极简但每个字段都不能错。path指向数据集根目录train和val指向划分后的子目录nc是类别数names是类别名列表顺序必须和转换脚本里的CLASSES完全一致。这里就是第一个黑匣子names顺序一错所有标签的类别ID全部错位模型能训练能收敛但推理结果全部张冠李戴。下面这份配置以8个常见工具类别为例实际训练时names务必替换成压缩包内类别清单里的名称path: /home/user/datasets/tools # 数据集根目录建议用绝对路径 train: images/train # 训练图片目录 val: images/val # 验证图片目录 nc: 8 # 类别数量 names: # 顺序必须与转换脚本的CLASSES一致 - wrench - pliers - screwdriver - hammer - tape - drill - cutter - glovepath字段如果写成相对路径YOLOv8会把train和val拼到当前工作目录下很容易找不到文件。names列表的顺序是所有环节共用的约定转换脚本、data.yaml、训练输出、推理结果都在同一套顺序上任何一环改了其他环节必须同步改。训练命令如下yolo detect train \ datadata.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ seed42 \ patience20参数说明modelyolov8n.pt先加载预训练权重再开始训练如果权重下载受阻可以换成随机初始化但收敛会慢很多。epochs100对4713张的规模偏中等早停触发时会自动提前结束。imgsz640把输入图片统一缩放到640x640数据体检时如果发现图片尺寸差异大建议先640跑通再说。batch16在多数单卡16GB显存下够用显存不够就降到8或4。patience20表示验证集mAP连续20轮不提升就早停这是防止时间浪费的有效手段。提示如果显卡只有8GB显存把batch降到8、imgsz降到480训练仍能正常进行只是收敛慢一点。不要因为参数调小就把整个训练放弃小参数跑出来的模型也具备参考价值。训练开始后的前几个epoch模型还在预热学习率mAP大概率在低位震荡不要急于判断好坏。等跑到30到50个epoch如果训练loss还在明显下降而验证mAP不再涨就要警惕过拟合了。4.3 训练过程怎么看loss曲线与过拟合信号YOLOv8在runs/detect/train目录下输出指标曲线最值得看的是box_loss、cls_loss、dfl_loss三条loss曲线和mAP50、mAP50-95两条精度曲线。loss持续下降是正常信号loss先降后升而mAP同时掉是典型的过拟合这时再训下去只会把验证集指标弄得更差。yolo损失函数这一块不用深究每个公式但要能看懂曲线的三种形态。第一种平稳下降正常。第二种训练loss降、验证loss不降说明泛化不足可以加数据增强或换小模型。第三种loss从一开始就在高位抖动一步一个高峰多数是标签或配置出了问题常见来源是类别ID错位、标签文件为空、框越界。训练日志里还有个容易忽略的值验证集mAP50-95比mAP50低一大截在小目标多的数据集上非常常见。工具检测里像螺丝、垫圈这类小目标IoU阈值从严时会大量漏检mAP50-95自然上不去。如果目标是工业级精度建议后期用更大imgsz或切图推理来补这部分窗口。早期YOLOv5版本里有过训练中BN崩溃的讨论表现为loss突然跳成NaN。YOLOv8对BN的处理已经稳定很多真遇到loss变NaN先查学习率初始值和标签里有没有异常数值比翻网络结构更实际。训练到早停或指定epoch结束模型权重会产出best.pt和last.pt。best.pt是验证集表现最好的权重后续验证和推理都用它last.pt只在你打算继续训练时才有用。至此训练链路已经跑通接下来真正花时间的是把模型拉到真实场景里验证。这个环节放到避坑之后集中讲。5. 避坑8类别工具数据训练中的常见问题5.1 类别编号错位loss下降但推理结果全错训练过程一切正常loss稳定下降验证集mAP看起来也不低但把模型放到真实图片上推理扳手被标成钳子、锤子标成螺丝刀错误非常有规律。原因这是VOC转YOLO时最典型的翻车点。XML里的name是字符串转成YOLO后变成整数ID这个ID由类别清单的顺序决定。如果转换脚本用的类别顺序和data.yaml里的names顺序不一致同一个ID在两套配置里指向不同类别模型学的是“ID0对应扳手”推理时却按“ID0对应钳子”来解释于是所有结果整体错位。解决以classes.txt为准让转换脚本和data.yaml都从这一份文件读取顺序脚本里不要出现第二份硬编码清单。转换完成后随机抽几个TXT把第一列ID映射回类别名打印核对一次。训练前用脚本把labels目录所有TXT的类别ID去重打印确认没有超出nc范围的数字这一步能把绝大多数错位问题拦在训练之前。5.2 标签文件为空或框越界训练中断和AP异常现象是训练到一半提示标签文件格式错误或者某个类别AP剧烈浮动、另几个类别完全不学习。打开labels目录检查发现一部分TXT是空文件一部分框的坐标超出了图片边界。原因转换脚本不严谨时容易产生两种坏标签。一是目标退化成点宽度或高度为0转换时没过滤YOLO加载标签时直接报错。二是标注框超出图片边界比如xmax大于图片宽度归一化后数值超过1训练时损失函数算出异常值。VOC数据集大多手工标注坐标越界并不罕见只是肉眼不容易发现。解决转换脚本里必须加两道过滤box_w 0 or box_h 0直接跳过所有归一化值用min(max(v, 0), 1)截断。训练前写一个标签校验脚本逐行检查五个数字是否都在合理区间空文件单独统计出来和对应图片核对是背景图还是漏标。我习惯把这步校验固化到每次训练前的准备流程里换数据集时不用再想。5.3 7z解压报错压缩包损坏和磁盘空间不足现象是7z解压到一半提示CRC failed或者解压进度条走了很久最后提示磁盘空间不足。前者集中在特定文件反复报错后者在输出目录写满时统一炸出来。原因7z文件在下载或拷贝过程中丢字节是最常见的压缩包损坏来源网盘和USB设备传输时尤其容易出问题。另一个原因是解压后所需空间超过剩余磁盘。两个原因症状好区分CRC failed跟着文件走磁盘空间不足跟着目录走。解决解压前先用7z t测试压缩包完整性这步能提前暴露损坏。测试通过再解压测试失败就重新下载或换一个源头不要用-y强行解压解出来的文件多半残缺。磁盘空间不足的情况先清理或df -h看剩余空间解压体量通常几个GB提前看好人不会翻车。解压完成后核对图片数量和压缩包说明里的数字核对不上说明有文件没解全。5.4 显存不足batch和imgsz的组合问题现象是训练命令启动后几秒钟报CUDA out of memory日志里能看到显存分配失败。把batch调小后能跑但速度明显变慢。原因显存占用由batch乘以单张图的显存消耗决定单张图消耗又和imgsz正相关。图片原分辨率高时imgsz640的单图显存占用并不小batch16在部分显卡上直接爆掉。这是参数组合问题不是环境坏了调低参数即可。解决优先降batch从16降到8或4显存立刻释放。batch降到4还不够把imgsz降到480或416。imgsz和batch是相乘关系一个不行就两个一起调。还有一个容易忽略的选项YOLOv8的cacheTrue会把数据集缓存到内存显存不足的机器上反而拖慢系统建议先保持cacheFalse跑通第一轮。5.5 类别不均衡mAP被少数类拉高真实表现打折现象是整体mAP看起来不错按类别看AP时某几个类别特别高个别类别AP不到20%。这类类别往往目标数很少或者目标本身很小。原因工具数据里大类目标数量多、框面积大模型容易学。小众类别样本少加上标注框小特征不明显整体mAP被大类拉高产生“模型还行”的假象。真实场景里小类几乎不可用问题被整体指标掩盖。解决先回看2.2的类别统计表按目标数排序。对明显少的类别优先查是场景里本来就少还是漏标多。漏标就补标本身就少可以在训练配置里调整hsv_h、hsv_s、degrees等增强参数让稀少类别的颜色、角度变化更丰富。如果问题是小目标加大imgsz或用切图推理比改损失权重更有用。6. 验证模型用混淆矩阵和可视化找出漏检与误检训练结束后的best.pt能不能上线不是看训练日志里那个mAP数字而是看它在验证集和真实场景里的表现。YOLOv8自带验证命令直接对划分好的val目录评估yolo detect val \ datadata.yaml \ modelruns/detect/train/weights/best.pt \ splitval命令跑完会输出每个类别的AP、mAP50和mAP50-95同时在runs/detect/val目录下生成混淆矩阵图confusion_matrix.png。混淆矩阵能直接告诉你哪两个类别容易被互认工具检测里扳手和钳子、螺丝刀和电钻这类形状相近的类别容易在矩阵里看到明显的交错块。看到哪个块颜色深就去翻对应类别的验证图片确认是标注画小了还是外观本来就相似。进阶一点的验证是批量可视化推理。写个几行脚本把验证集图片全部跑一遍预测输出带框图片后单独查看漏检率高的类别from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) # conf和iou是推理阶段的两个关键参数先按默认跑再按需调 results model.predict( sourcedataset/images/val, conf0.25, iou0.45, saveTrue, save_txtTrue, )参数说明conf0.25是置信度阈值低于该值的预测框被丢弃调低能发现模型“其实预测了但不敢承认”的目标iou0.45是NMS的IoU阈值同类目标互相遮挡时调低能保留更多框。save_txtTrue会把预测结果写成TXT方便脚本统计每个类别的预测总数和漏检情况。我现在的习惯是每次训练完把验证集里AP最低的那个类别单独抽出来跑一遍可视化逐个看漏检目标属于什么原因——光照太暗、目标太小、还是标注框画得太松。这个习惯帮我发现过不止一次“模型没问题是标注边界有问题”的情况比盯着mAP空想有效得多。希望帮到你。本文还有配套的精品资源点击获取