news 2026/10/2 8:37:12

药丸缺陷检测数据集VOC+YOLO格式使用指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
药丸缺陷检测数据集VOC+YOLO格式使用指南

简介:这是一份面向计算机视觉与工业质检场景的药丸缺陷检测数据集,提供2759张药丸图像的目标检测标注数据,覆盖污染、裂纹与合格品三类目标,适用于训练YOLO、Faster R-CNN等主流检测模型。数据同时给出Pascal VOC格式的xml标注与YOLO格式的txt标注,并配有使用前必读说明,方便直接接入训练流程。压缩包内共2000个文件,以xml和txt标注文件为主(约1049个xml、951个txt),整体大小411.78MB,便于一次下载使用。三类目标总框数为2798个,分布相对均衡,由labelImg按矩形框规则完成标注,基础质量可靠。目前已有218人浏览学习,适合需要现成数据开展药丸外观检测实验或毕业设计的开发者,能大幅节省数据标注时间,将精力集中于模型训练与优化。

1. 药丸的缺陷检测数据集:VOC+YOLO双格式,2759张图能直接开训吗?

药丸的缺陷检测数据集,听起来像个小众资源包,但做过产线外观检验的人知道它卡住了多少人:缺角、裂纹、污点要靠人工盯,眼睛疲劳后漏检率压不下来,想上视觉检测又卡在没有带标注的数据。这个数据集恰好提供了2759张图片、3个类别的标注,同时给VOC和YOLO两种格式,解压就能喂给主流检测框架。适合刚接触缺陷检测、想跑通目标检测全流程的新手,也适合要快速验证药丸瑕疵检测可行性、再决定要不要投入产线的团队。下面按落地顺序拆:目录结构、格式转换、训练参数、排错验证。

2. 解压后先别急着训:VOC目录和YOLO标签怎么对得上

2.1 解压命令与目录结构:中文文件名是个坑

拿到 .7z 包后,先把文件放到纯英文路径下,比如~/projects/pill_defect,避免 YOLO 在读取路径时因为中文目录出现编码异常。Linux 下解压命令是:

7z x 药丸的缺陷检测数据集VOC+YOLO格式2759张3类别.7z -o./pill_defect

注意-o后面不跟空格,直接接输出目录,这是 7z 的参数格式,写错了会解压到意外位置。如果服务器上没有 7z,需要先安装 p7zip-full;Windows 下用 7-Zip 或 PeaZip 都行,但解压后我建议第一时间改名成pill_defect这种英文目录。

解压完成后不要急着找图片,先用tree或ls看整体布局。以我处理过的双格式数据集来说,最常见的目录是 VOC 和 YOLO 并列,各自维护一份标注,图片内容完全一致。典型结构是:

pill_defect/ ├── VOC/ │ ├── Annotations/ │ ├── JPEGImages/ │ └── ImageSets/ │ └── Main/ │ ├── train.txt │ ├── val.txt │ └── test.txt └── YOLO/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/

这个结构对应两种用法:VOC 目录喂给 MMDetection 这类需要标准 Pascal VOC 格式的框架,YOLO 目录直接给 YOLO 系列训练。两个目录里的图片文件名是同一套,标注内容也一致,只是表达方式不同。如果你的压缩包解压出来不是这个布局,只要内容还在,花十分钟把它整理成标准结构,后边会省很多麻烦。

2.2 VOC 的 XML 标注:框坐标和 size 字段怎么读

打开一个 XML,格式如下:

<annotation> <folder>pill_defect</folder> <filename>pill_0001.jpg</filename> <size> <width>640</width> <height>480</height> <depth>3</depth> </size> <object> <name>chip</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>120</xmin> <ymin>80</ymin> <xmax>180</xmax> <ymax>130</ymax> </bndbox> </object> </annotation>

这里类别名我用chip做例子,实际包里的 3 个类别以Annotations下的<name>为准。XML 里最关键的信息是name和bndbox,分别是类别名和左上右上、左下右下的绝对像素坐标。<difficult>标记在 YOLO 训练里没有对应概念,它表示这个框很难辨认,VOC 评估时会忽略这类框;但转成 YOLO 后,difficult 信息会被丢掉,等于把难例当成普通框参与训练。如果这类框本身标注质量差,就会带偏模型。

还有一个容易被忽略的点:<size>字段不一定和图片真实分辨率一致。有的标注工具在保存时会缓存图片尺寸,如果图片后来被压缩过,XML 里的尺寸就没更新。所以做格式转换时,宁可用 PIL 去读实际图片的宽高,也不要直接信任 XML 里的size,尤其是 width 和 height。另外,XML 里的filename有时会带相对路径,比如JPEGImages/pill_0001.jpg,读取时要用os.path.basename做一次清洗,否则找图片会失败。

2.3 YOLO 的 TXT 标签:归一化坐标和类别索引要对着 data.yaml 读

YOLO 标签每个 txt 文件里一行表示一个框:

0 0.234375 0.208333 0.093750 0.104167

这五个数字依次是类别索引、归一化中心 x、归一化中心 y、归一化宽、归一化高。药丸的缺陷框通常比较小,所以后两个数字会经常出现低于 0.1 的情况。类别索引 0 对应的是你在data.yaml里第一个类别的名字,不是 XML 里写的类名。如果 3 个类别的顺序排成了 chip、crack、stain,那么索引 0 就是 chip,索引 1 是 crack,索引 2 是 stain。

这个环节最容易翻车。之前有团队拿到的标签里,索引 0 本应是 crack,但data.yaml里第一个类别写成了 chip,模型训练时 loss 正常下降,推理出来所有框的类别名都错位。所以无论用现成工具还是自己写脚本,先打印一张图的 XML 和 TXT 对照,确认坐标和类别索引对得上,再批量转换。

为了便于对照,写一个小函数把 YOLO 归一化坐标转回绝对像素:

def yolo_to_pixel(cx, cy, w, h, img_w, img_h): xmin = (cx - w / 2) * img_w ymin = (cy - h / 2) * img_h xmax = (cx + w / 2) * img_w ymax = (cy + h / 2) * img_h return xmin, ymin, xmax, ymax print(yolo_to_pixel(0.234375, 0.208333, 0.093750, 0.104167, 640, 480))

输出结果大概落在(120, 80, 180, 130)附近,正好和上面 XML 的bndbox对齐。这里用的是归一化坐标加减宽高的一半再乘图片尺寸,不要套用 VOC 的绝对坐标公式。如果输出和 XML 差得很远,说明标签不是同一份图片生成的,需要重新确认数据来源。

2.4 双格式为什么都存在:一份数据要能喂给两套框架

VOC 格式是检测领域的通用格式,保存的信息更全,除了框和类别,还有难例标记、截断状态;YOLO 格式是简化后的训练格式,只有类别索引和归一化坐标。双格式同时存在,是为了让使用者不用统一转换工具,直接在不同训练生态里切换。比如算法横向对比时用 VOC,正式训 YOLO 时直接用 YOLO 目录。

但双格式也有个隐患:两份标注可能不同步。打包的人可能更新了 VOC 里的 XML,忘了同步 YOLO 的 TXT。所以训练前先做一次计数比对,下面的命令能快速发现数量不一致:

find VOC/Annotations -name "*.xml" | wc -l find VOC/JPEGImages -name "*.jpg" | wc -l find YOLO/images/train -name "*.jpg" | wc -l find YOLO/labels/train -name "*.txt" | wc -l

正常情况下,图片数等于 XML 数(允许个别纯背景图没有 XML),YOLO 目录里的标签数和图片数也应一致。如果发现标签数明显少于图片数,说明有图片没有标注,这些图片在 YOLO 训练里会被当成纯背景;如果缺陷图片没标注,就相当于漏标正样本,训练出的模型会在这些图上漏检。

提示:双格式之间的差异排查只要花两分钟,但能排掉一大半后续“莫名其妙指标不对”的玄学问题。两个目录的 train/val 划分也必须对齐,否则验证集污染会直接抬高 mAP,后面第 5 章再细说。

3. 把 VOC 转 YOLO:自写转换脚本与四个边界坑

3.1 为什么自己写:格式转换不能只靠在线工具

很多在线转换工具需要上传数据,药丸缺陷图片往往涉及生产环境,不宜外传;而且在线工具对错误标注只能简单跳过,无法知道为什么跳。我一般会在本地用 Python 写一个一次性脚本,也就几十行,还能针对越界框、异常框做定制处理。这里给一个能直接跑的版本,它读取 VOC 的Annotations,生成 YOLO 训练所需的labels。

import os import xml.etree.ElementTree as ET from PIL import Image voc_annotations = "VOC/Annotations" image_dir = "VOC/JPEGImages" label_dir = "YOLO/labels" class_names = ["chip", "crack", "stain"] # 必须和最终data.yaml一致 os.makedirs(label_dir, exist_ok=True) for xml_file in sorted(os.listdir(voc_annotations)): if not xml_file.endswith(".xml"): continue tree = ET.parse(os.path.join(voc_annotations, xml_file)) root = tree.getroot() img_name = os.path.basename(root.find("filename").text) img_path = os.path.join(image_dir, img_name) img = Image.open(img_path) img_w, img_h = img.size lines = [] for obj in root.iter("object"): name = obj.find("name").text if name not in class_names: print(f"跳过未知类别 {name} 在 {xml_file}") continue cls_idx = class_names.index(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) center_x = (xmin + xmax) / 2.0 / img_w center_y = (ymin + ymax) / 2.0 / img_h width = (xmax - xmin) / img_w height = (ymax - ymin) / img_h if width <= 0 or height <= 0: print(f"跳过异常框 {xml_file} 的 {name}") continue lines.append(f"{cls_idx} {center_x:.6f} {center_y:.6f} {width:.6f} {height:.6f}") out_name = os.path.splitext(xml_file)[0] + ".txt" with open(os.path.join(label_dir, out_name), "w", encoding="utf-8") as f: f.write("\n".join(lines)) print(f"转换完成,共处理 {len(os.listdir(voc_annotations))} 个XML")

这个脚本的核心逻辑是:先取filename找图片,用 PIL 读真实宽高;再遍历每个object,把类别名映射成索引,把绝对坐标除以宽高转为归一化坐标;最后把每个框写成一个 txt 行。class_names的顺序是唯一的映射来源,顺序一旦变了,所有类别索引都会变,因此这里要与后面data.yaml里的names严格一致。脚本里跳过未知类别和异常框,如果跳过数量很多,需要打印统计信息,不要静默处理。

3.2 边界坑一:类别名和索引错位,训练不报错但结果全乱

这个坑在 2.3 提过,这里展开讲。VOC 的 XML 里name是字符串,YOLO 的 TXT 里是整数,转换脚本里class_names的顺序决定了每个字符串对应哪个索引。如果顺序写错,模型训练过程中 loss 不会异常,甚至 mAP 可能还不错,但实际推理时类别名和位置对不上。比如真正的裂纹被预测成污点,产线判级就会出错。

更隐蔽的错位发生在你追加新类别时。比如原始 3 个类别是 chip、crack、stain,你为了实验又往 XML 里加了其他类别,但class_names没有同步增加,转换脚本会把所有新类别当成未知类别跳过,静默丢失一部分框。所以脚本里最好不要用list.index这种方式,而是先扫描所有 XML,动态建立“类别名到索引”的映射字典,并输出一份classes.txt。这样每次转换后比对classes.txt和data.yaml,能手动确认有没有错位。

还有一个常见乌龙:XML 里的类别名带前后空格,比如chip,直接拿来比较会匹配不上。写脚本时对name.strip()是基本操作,不要省。

3.3 边界坑二:越界框和非正框,训练时产生 nan

药丸图片里缺陷靠近边缘很常见。标注时为了框住完整缺陷,很容易把 xmax 标到图片外面。这种框直接转 YOLO,归一化后坐标可能大于 1,YOLO 训练时不一定报错,但损失计算会异常。处理办法是 clip 到边界内,然后判断有效尺寸。

xmin = max(0.0, min(xmin, img_w - 1)) ymin = max(0.0, min(ymin, img_h - 1)) xmax = max(0.0, min(xmax, img_w - 1)) ymax = max(0.0, min(ymax, img_h - 1)) if xmax <= xmin or ymax <= ymin: print(f"过滤无效框: {xml_file} {name}") continue

这段代码放在归一化之前,把坐标限制在图片像素范围内。注意min(xmax, img_w - 1)而不是img_w,是为了避免像素索引等于宽度时转成归一化坐标 1.0,在数据增强的随机缩放里容易出问题。clip 后如果框宽或高被压缩到 0,说明原始标注质量太差,直接丢弃。

还有一个容易被忽略的点:VOC 坐标是像素角点坐标,xmin=10、xmax=20 表示框宽 10 像素,算宽度时要用xmax - xmin,不要画蛇添足加 1。YOLO 归一化时中心点用(xmin + xmax) / 2,这是标准做法。如果把 +1 带进去,所有框都会偏移半个像素,缺陷框小的时候影响会被放大,训练出的框边缘会普遍贴近缺陷一边。

3.4 边界坑三:目录划分不一致导致验证集污染

VOC 的ImageSets/Main里有 train.txt、val.txt,YOLO 目录里也分了 train、val。这两份划分如果来源不同,可能出现同一张图既在训练又在验证,mAP 虚高。比如 VOC 的 ImageSets 按时间先后划分,YOLO 目录里却是随机划分,两边比例不一致。转换脚本只负责生成标签,不会自动纠正划分。

解决办法是统一以 VOC 的ImageSets/Main下的 txt 为准,根据它把图片拷贝到 YOLO 的 images/train 或 val,再根据图片文件名把对应标签拷入 labels。一个简单的 bash 做法如下:

for split in train val; do while read line; do cp VOC/JPEGImages/$line.jpg YOLO/images/$split/ cp YOLO/labels/$line.txt YOLO/labels/$split/ done < VOC/ImageSets/Main/${split}.txt done

解释:读一行文件名,把 jpg 和同名的 txt 拷过去。注意这里的$line不带扩展名,如果你的 ImageSets 里带 .jpg,需要先去后缀。这个脚本会覆盖 YOLO 目录原本的划分,确保两边一致。跑完后再用 2.4 的比对命令检查 train 和 val 的文件数,额外用comm -12检查两个列表有没有交集,确认没有同一张图同时出现在 train 和 val。

3.5 转换后自检:类别计数和框尺寸分布

转换完还要做一次自检。我习惯写一个很短的统计脚本,确认各类别的实例数、空标签数量、框尺寸范围。

import os from collections import Counter label_dir = "YOLO/labels" counter = Counter() box_sizes = [] empty = 0 for f in os.listdir(label_dir): path = os.path.join(label_dir, f) if not f.endswith(".txt"): continue with open(path, "r", encoding="utf-8") as fh: lines = fh.readlines() if len(lines) == 0: empty += 1 continue for line in lines: parts = line.strip().split() if len(parts) != 5: continue counter[int(parts[0])] += 1 box_sizes.append((float(parts[3]), float(parts[4]))) print("类别索引计数:", counter) print("空标签图片数:", empty) if box_sizes: print("最小归一化框尺寸:", min(box_sizes)) print("最大归一化框尺寸:", max(box_sizes))

这里要注意:归一化框尺寸是指框宽在整张图宽度中的占比。药丸缺陷如果本身很小,min 会低于 0.01,此时训练时最好开高分辨率输入或者做针对性增强。如果某个类别框数为 0,说明类别映射或源标注有问题;如果空标签图片数特别多,说明大量图片没有缺陷,训练时要保留作为背景,但也要意识到模型可能会更倾向于预测“无缺陷”。

4. 用 YOLOv8 训练药丸缺陷模型:数据集配置与参数选型

4.1 写 data.yaml:路径、类别名、类别数

YOLOv8 使用 YAML 文件描述数据集。最简配置是 path、train、val、names 四项。下面这份能直接用:

path: ./pill_defect train: YOLO/images/train val: YOLO/images/val names: 0: chip 1: crack 2: stain

没有写nc,YOLOv8 会根据 names 长度推断。path是相对路径,train和val是图片目录的路径。需要特别留意的是,YOLOv8 加载标签时默认从 images 路径的同级 labels 目录找,也就是images/train对应labels/train。如果你把标签放在别处,可以在 yaml 里额外指定,但我不建议这么做,保持默认能减少很多路径排查时间。

这份 yaml 里的类别名称顺序,必须和转换脚本里的class_names顺序完全一致。如果转换脚本里是["chip", "crack", "stain"],yaml 里也必须按同名顺序写。建议把classes.txt放在数据集根目录,每次训练前 cat 出来和 yaml 对照一遍。

4.2 训练命令与关键参数:先跑 n 再换 s

在 YOLOv8 的权重系列里,n、s、m 对应网络深度和宽度递增。2759 张图的规模不算大,我通常先用yolov8n跑通流程,再用yolov8s看效果上限。训练命令:

yolo train data=pill_defect.yaml model=yolov8s.pt epochs=100 batch=16 imgsz=640 device=0 seed=0

命令参数:data指向 yaml;model表示基础权重,第一次运行会自动下载预训练模型到缓存目录;epochs是训练轮数;batch是单卡批大小;imgsz是输入分辨率;device指定显卡;seed固定随机种子,保证可复现。对于显存只有 8G 的显卡,batch=16 可能爆显存,降到 8 或 4 即可。如果小目标缺陷比较多,imgsz提到 704 或 768 通常能提升召回,但训练时间会明显变长。

为什么先选yolov8n?因为缺陷检测的第一目标是判断数据是否可用,而不是刷榜单。yolov8n 训练一轮很快,能快速看出 loss 曲线是否正常、mAP 有没有上升趋势。如果 n 的基础结果太差,再换 s 或 m,而不是一开始就上大模型。数据本身只有 2759 张,大模型容易过拟合,val mAP 反而可能下降。

4.3 训练过程的常见报错:bn 崩溃、loss 为 nan、显存不足

这一节是给新手排雷的。三类最常见的报错现象与处置如下:

第一,显存不足(CUDA out of memory)。报错出现在第一个 epoch 开始时。解决顺序是:先降 batch 到 8 或 4,再不动 batch 降 imgsz 到 512,如果还不行只能换更大显存。不建议用梯度累积替代,因为梯度累积只是降低更新频率,显存峰值并没有降下来。

第二,loss 变成 nan。现象是训练日志里 loss 首次出现 nan,之后一直 nan。原因多数是标签坐标出现了 inf 或 nan,或者输入图片本身全黑、全白、损坏。解决:先用自检脚本扫一遍标签数值;然后检查图片是否完整,用 PIL 打开并转成 numpy 数组,判断数组的最大最小值是否正常。如果数据没问题,再考虑学习率太高,把初始学习率降到 0.001 以内重试。

第三,bn 崩溃。YOLO 的 BN 层在训练中会因为某个 batch 的统计量异常而输出 nan,常见原因是某个 batch 里恰好全是空标签图片,或者图片尺寸差异过大。解决:把 batch 调大一点,让每个 batch 里正负样本更均衡;同时关闭过强的数据增强,特别是 Mosaic,在数据量不足时 Mosaic 后小目标被裁剪,BN 统计容易出错。这个小数据集上确实有点玄学,但多发生在这种样本量不够大的场景里。

还有一类报错是训练开始前提示找不到标签文件。现象是日志里出现大量WARNING: impossible to load或No labels found。原因多半是 yaml 里的train路径写错,或者标签目录不是 images 同级的 labels。解决:回到 2.4 的比对命令,确认标签文件都在,再检查 yaml 的 path 是不是相对于当前执行目录。这个问题最多,也最不值得浪费一晚上。

4.4 训练完先看验证集结果图,再决定是否调参

训练结束后,不要只盯 mAP。用 best 权重跑一遍验证集预测:

yolo predict model=runs/train/exp/weights/best.pt source=YOLO/images/val save_txt=True conf=0.25

conf默认 0.25,预测结果会存到runs/detect/exp下。打开这些结果图,人工看一圈,重点关注:有没有漏检明显的缺陷、有没有把反光误检为缺陷、框是否贴合边缘。这一步能发现许多 mAP 体现不了的问题。比如有些框虽然 IoU 高,但中心点偏了,产线机械手去抓就很难对准。

还可以统计验证集上每个类别的平均置信度。如果某个类别的置信度普遍偏低,说明模型对这个类别的特征还没学会,下一轮训练时考虑增加该类别样本的增强权重,或者补充样本,而不是继续加训练轮数。训练轮数堆太多,往往是过拟合,验证集 loss 已经开始反弹了。

5. 缺陷检测场景避坑指南:标注、反光与样本不均衡

5.1 标注框偏移让 mAP 虚高,独立验证才能露馅

现象:训练时验证集 mAP50 高达 90%,部署到现场后错漏明显。原因是标注框存在系统性偏移,比如标注统一偏左 2 个像素,模型学到了这个偏移,在同一个数据分布下的验证集上指标好看,到新产线就失效。解决:训练前随机抽 10 张图,用 OpenCV 把标签框画上去人工核对;训练后再抽 10 张预测图,对比预测框和真实框。画框脚本:

import cv2 img = cv2.imread("VOC/JPEGImages/pill_0001.jpg") box = (120, 80, 180, 130) # xmin, ymin, xmax, ymax cv2.rectangle(img, (box[0], box[1]), (box[2], box[3]), (0, 0, 255), 2) cv2.imwrite("check_box.jpg", img)

画出来的框如果明显没有包住整个缺陷,就需要重新评估这个数据集的标注质量。缺陷检测和通用目标检测不同,缺陷框小,边缘稍微偏一点,IoU 就从 0.9 掉到 0.5。这也是为什么这类数据集训练后指标的绝对值通常没有通用检测高。如果发现几十张图都有系统性偏移,最有效的做法不是写脚本平移标签,而是返回标注工具里做一次整体修正。

5.2 药丸反光被识别成缺陷:先从光照入手

现象:推理时药丸表面高光区域产生大量预测框,而这些区域实际是灯打出来的反光,不是裂纹。原因:训练数据里反光样本少,模型把高光纹理当成缺陷特征。解决分两步。

第一步,在训练数据中加入不同光源角度的反光阴性样本,让模型学会区分反光和裂纹。第二步,在数据预处理里做光照归一化,例如把图片转成灰度后计算直方图均值和标准差,再决定是否做 CLAHE 对比度均衡。OpenCV 的createCLAHE能压掉过强的高光,但参数要控制:clipLimit设到 2 以下,否则药丸本身的纹理也会消失。这条经验来自药丸检测项目里的血泪踩坑:换模型远不如把光照问题在数据层面解决来得彻底。

如果只是快速验证,也可以临时在推理阶段给图片外侧加一个遮罩,把固定光源造成的高光区域排除掉,但这是治标不治本。产线换一套光源后,遮罩位置就失效了,还是要在训练数据里覆盖足够多的光照角度。

5.3 类别样本不均衡:先复采样,再考虑加权

现象:三个类别里某个类别样本很少,模型对这个类别的召回率始终上不去。原因:少数类在总样本中占比过低,损失被多数类主导。解决顺序建议:先统计每个类别的框数,如果少数类占比低于 10%,先做类别复采样,在每次 epoch 里对少数类图片做重复抽样,而不是直接改 Loss。

YOLO 训练没有直接暴露 class weights 参数,盲目加权很难找到合适尺度,反而会过拟合少数类。另一种做法是针对少数类做基于缺陷框的局部增强:对框区域做小角度旋转、亮度扰动、轻微平移,生成更多训练样本。需要注意的是,增强幅度要小,药丸缺陷的形态和位置都很敏感,扭曲太大会让缺陷变成另一种东西。

如果做了复采样和增强后少数类还是不行,再考虑最粗暴的办法:多收集真实缺陷样本,尤其是不常见的那一类。缺陷检测的数据集不像通用物体目标检测那样能靠爬虫补充,只能从产线积累,这也是这类数据集的真实成本所在。

5.4 固定随机种子,否则你分不清改动是提升还是玄学

现象:同一份数据、同一套参数,只换一次随机种子,mAP 变化 2 个点,有时候类别 A 的召回涨了但类别 B 暴跌。原因:训练过程中的数据加载顺序、Mosaic 增强的随机采样都没固定。解决:在训练命令里加seed=0,并固定数据加载线程和 shuffle 的种子;更严格一点,在训练脚本开头调用random.seed、numpy.random.seed、torch.manual_seed。

这个习惯看起来简单,但在小数据集上特别重要,因为样本少,随机波动比大数据集大得多。固定种子后,每次实验只改变一个变量,调参才有意义。否则你很难判断 mAP 的提升是模型改动带来的,还是某次随机采样恰好抽到了更简单的验证图片。

6. 从 mAP 到产线验收:先看混淆矩阵,再算漏杀和过杀

6.1 混淆矩阵里看漏检,而不是只看 mAP

mAP 是排序指标,对低置信度预测有一定宽容,但产线只看最终判决:缺陷有没有被框出来、框是不是对准了。训练完跑一次验证集,生成混淆矩阵,重点看两处:一是每个类别被漏检成了哪一类,二是背景被误检成缺陷的比例。药丸缺陷里裂纹和反光的混淆最典型,如果矩阵里大量“裂纹被判成污点”,说明这两个类别的特征边界没有拉开,要么加样本,要么考虑合并类别重新标注。混淆矩阵建议用验证集生成,不要用训练集,训练集上的混淆矩阵几乎没有参考价值。

6.2 漏杀和过杀的成本,决定阈值怎么调

药丸质检通常漏杀成本远高于过杀:坏药丸流出去会出品质事故,好药丸被拦截最多是重新检测一次。因此部署时置信度阈值可以从默认的 0.25 下调到 0.15,多召回一些低置信度缺陷框;同时配合连续帧过滤,同一颗药丸在视野中出现多次,至少连续两帧都报缺陷才判为 NG,能明显降低偶发误检。这个组合拳比单独调模型参数更值得先做。如果现场过杀率仍高于线体要求,再逐步提高阈值,直到找到漏杀和过杀的平衡点。需要在产线连续运行一段时间后重新统计一次混淆矩阵,以真实样本为准。

我自己的习惯是,拿到任何缺陷检测数据集,先跑一轮基线,只调置信度阈值和 NMS 参数,记录下这两组数;如果效果不满足,再动训练参数和增强策略。这样能避免把数据和模型问题混在一起。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 8:36:58

VOC垃圾分类数据集详解:15000张真实场景图与YOLO训练实战

简介&#xff1a;VOC垃圾分类检测数据集面向需要训练目标检测模型的开发者、研究人员及学生&#xff0c;提供约一万五千张真实场景高质量标注图片&#xff0c;覆盖纸张、塑料、果皮、玻璃杯、易拉罐、厨余垃圾等常见类别&#xff0c;场景丰富、角度多样。全部图片以jpg格式保存…

作者头像 李华
网站建设 2026/10/2 8:36:57

Java个人博客系统毕业设计:从环境配置到部署答辩全流程指南

简介&#xff1a;基于Java的个人博客系统毕业设计资料包&#xff0c;面向高校计算机相关专业学生及Java Web入门开发者&#xff0c;适用于课程设计、毕业设计或项目实战。压缩包约178.52MB&#xff0c;包含项目报告、答辩PPT、源代码、数据库脚本及部署教学视频等主要文件类型&…

作者头像 李华
网站建设 2026/10/2 8:36:09

Claude Code实战:重构十年遗留系统的方法论

1. 这不是又一个“AI写代码”故事&#xff0c;而是给真实世界里那堆跑着十年的老系统续命的实操笔记我接手过三套平均年龄8岁的遗留系统&#xff1a;一套用VB6写的车间排产模块&#xff0c;数据库还是Access&#xff1b;一套Java Web项目&#xff0c;Spring版本停在2.5&#xf…

作者头像 李华
网站建设 2026/10/2 8:35:53

Java直播平台源码实战:从架构拆解到高并发部署全指南

简介&#xff1a;这是一套基于Java与Spring Boot构建的在线直播平台完整源码工程包&#xff0c;面向具备Java基础、希望学习企业级直播业务落地的开发者。项目采用前后端分离架构&#xff0c;涵盖腾讯云直播流接入、直播鉴黄、礼物打赏、支付宝充值提现、弹幕聊天室等核心模块&…

作者头像 李华
网站建设 2026/10/2 8:33:30

银行数据挖掘课程作业实战:分类与聚类全流程指南

简介&#xff1a;面向计算机专业学生和需要项目实战练习的学习者&#xff0c;这份数据仓库与数据挖掘课程高分期末大作业完整实现银行数据的分类与聚类任务&#xff0c;并配套翔实的实验报告。项目由导师指导并评审认可&#xff0c;得分99分&#xff0c;代码结构清晰、依赖完整…

作者头像 李华
网站建设 2026/10/2 8:33:05

机器学习多因子选股实战:从因子处理到组合构建全流程

简介&#xff1a;这份资源面向计算机、人工智能及金融工程方向的学生与量化爱好者&#xff0c;提供一套基于机器学习方法构建多因子选股模型的完整项目源码与文档&#xff0c;适合作为毕业设计参考或量化选股入门实战。压缩包共38个文件&#xff0c;约14.71MB&#xff0c;包含1…

作者头像 李华