☰
零件表面高精度缺陷检测源码工程:从数据到调优的完整实战
2026/10/10 14:48:22 网站建设 项目流程

简介:这是一份基于Python实现的工具零件表面高精度缺陷检测项目源码包,面向计算机、人工智能、通信工程、自动化、电子信息等专业的在校学生、教师和企业研发人员,尤其适合作为毕业设计、课程设计、作业演示或工业视觉检测项目初期的可行性参考。代码已经过运行验证,功能完整、结构清晰,可在其基础上扩展,实现不同零件表面的缺陷识别任务。压缩包共8个文件,包含3个Python脚本、2个文本说明、1个配置文件和版本管理/打包清单等,覆盖训练、测试、依赖环境与基础工程配置,整体仅10KB,非常轻量,便于快速阅读和修改。目前已有386人学习下载。读者可以获得完整的缺陷检测工程骨架、训练与测试脚本、环境依赖说明和清晰的文件组织方式,既能帮助初学者理解图像预处理与缺陷分类流程,也可作为实际项目改造和二次开发的起点。

1. 零件表面高精度缺陷检测源码工程:它解决的不只是「能不能识别」

零件表面高精度缺陷检测这类基于 Python 的源码工程,最常见的落地姿势是:固定工位装一部工业相机,把拍到的轴承、机油盖、试管或机械零件表面图送进训练好的模型,自动圈出划痕、凹坑、麻点、缺料和裂纹,再按缺陷面积换算成品率。它解决的核心痛点是人工目检的漏检与疲劳——质检员连盯三小时铁面,漏检率会明显爬升,而机器可以稳定复读。这份源码适合三类人:想上线自动化质检的产线工程师、做机器视觉选型方案评估的人,以及拿真实工业数据集复现检测管线的学生。下面把这类工程从「怎么读、怎么跑」到「精度怎么调、坑在哪」完整讲透。

2. 高精度从哪来:缺陷检测的选型逻辑与数据流设计

拿到 zip 先别急着装依赖跑训练。一份能落地的缺陷检测源码,八成的时间花在数据组织和模型选型上,真正跑训练反而很快。先把目录结构、数据格式和模型骨架读懂,你才知道这份「高精度」是建立在什么基础上的。零件表面的检测和自然场景目标检测是两个物种,第一站就把底层逻辑理清。

2.1 零件表面缺陷为什么让通用目标检测翻车

通用目标检测的 benchmark 大多是 COCO 那种日常物体,最小目标也有几十像素;零件表面缺陷却是另一个物种。划痕的宽度可能只有 3~5 个像素,长度却横跨几百像素,检测框长宽比极端到像一条线,普通 anchor 很难匹配;凹坑和麻点是「小圆斑」,跟划痕混在同一张图上,一个模型要同时吃下「线」和「点」两种几何形状。类内差异也大,同一类「划痕」在不同光源角度下,可能呈现为亮线、暗线、断续线三种样子。

更大的麻烦是类间混淆。金属拉丝纹理、滚花、氧化色斑这类「背景」长得和真缺陷几乎一样,模型很容易把纹理当划痕、把反光当凹坑。数据分布同样不友好:合格件图上一片干净,缺陷件图上可能只有孤零零一个小框,正负样本严重失衡。所以高精度的第一道坎不是模型参数量,而是标注时脑子够不够清楚——哪些是必须揪出来的缺陷,哪些是允许存在的材质纹理。我见过不少工程在模型上砸钱换精度毫无起色,回头一看是标注规范里把「纹理」和「划伤」混为一谈,模型被训练得左右互搏。

2.2 三条技术路线怎么选:传统视觉、检测模型还是异常检测

我把这类源码工程里常见的算法路线分成三档,选型时先对照这张表:

路线定位精度标注成本推理速度最怕什么
传统图像处理(阈值+形态学)像素级无需最快光照晃动、纹理干扰
目标检测(YOLO/Faster R-CNN)框级中(每类几百框)快新缺陷类型没见过
异常检测(PatchCore/PaDiM)像素级只需正样本中良品库覆盖不全

传统视觉适合打光固定、零件材质统一、缺陷和背景对比度明确的场景,比如透明试管里的异物、深色金属上的亮划痕,用灰度阈值加 top-hat 变换就能稳定检出,而且不吃算力。检测模型适合缺陷要分类、要统计每种缺陷数量的场景,这也是当前工业落地的主流。异常检测是近几年的热门方向,它只学「好零件长什么样」,新出现的未知缺陷也能报出来,但产线良品变化多样时误报率容易压不住。

对「工具零件表面」这个场景,我的建议是默认走目标检测路线,把传统视觉放在预处理和面积测量环节。不要一上来就堆模型,检测精度和推理延迟在产线上是一对真实矛盾。很多源码工程会同时预留两条推理路径:一条纯传统视觉做快速粗筛,一条深度模型做细分,两条路按节拍并行,这在产线上是性价比很高的搭配。

2.3 一个典型源码工程的目录与数据流

这类源码的目录结构通常长这样,先花十分钟逐目录翻一遍再动手:

defect_detection/ ├── configs/ │ └── defect.yaml # 训练/推理参数,改这里而不是改代码 ├── data/ │ ├── images/ # 原始零件图,jpg/png/bmp 都常见 │ ├── annotations/ # VOC 格式 XML 标注 │ ├── labels/ # 转出的 YOLO 格式 txt │ ├── train.txt # 训练集文件列表 │ └── val.txt # 验证集文件列表 ├── models/ # 模型定义和预训练权重 ├── utils/ # 数据加载、增强、后处理、可视化 ├── train.py # 训练入口 ├── infer.py # 推理入口 └── requirements.txt # 依赖版本清单

读源码时我一般按「configs → utils → train.py → infer.py」的顺序走。configs 里的 defect.yaml 是最先要看的,它把输入分辨率、学习率、置信度阈值、类别名称写死在参数里,改配置比改代码安全得多。数据流是一条直线:读图 → 归一化与增强 → 送进网络 → 输出候选框 → NMS 去重 → 按置信度和面积过滤 → 可视化或写 JSON。这条线上每一环都有可能成为精度瓶颈:归一化方式不对会让模型对亮度敏感,NMS 阈值太严会把重叠的两个真实缺陷吞成一个,面积过滤设大了会把小凹坑全部滤掉。搞清楚这条线,后面调精度你才知道该动哪一个环节,而不是盲目换模型。

2.4 数据集从哪来:公开集打底、自采图定生死

复现这类工程最常用的公开集是 NEU-DET,钢材表面缺陷集,包含划痕、夹杂、斑块、凹坑、氧化铁皮和麻点六类缺陷,图片尺度和零件表面场景非常接近,拿来练手和验证管线很合适。但公开集只能证明算法通,产线能不能用,得看你自己的零件图。自采数据有三个要点:一是光源和产线保持一致,同一个零件在实验室和车间拍出来是两张图;二是缺陷类型宁可少分类也别合并,比如「划伤」和「碰伤」混成一类,模型会被训练得精神分裂;三是良品图必须单独留一批做负样本,这是最容易被忽略的。标注工具用 labelImg 或 labelme 都行,导出 VOC XML 或 COCO JSON 再转换格式,格式不匹配往往是源码跑不起来的第一大原因。

起步量级上,我一般建议每个缺陷类别至少 300 个实例,良品负样本占总量三成左右。实例数和图片数要区分开——一张图上可能有 10 个凹坑,那 30 张图就能到 300 个实例。这个量级下用预训练权重微调,就能把精度拉到可看的水平;真要逼近产线 95% 以上的召回,靠的是后面章节讲的调参和难例回喂,而不是无限堆图。

3. 从零跑通最小闭环:环境、数据转换与训练推理命令

标题点名的 Python 生态,注定这套工序可以在一台普通 Windows 或 Linux 机器上复现。我的习惯是先花半小时把环境钉死,再准备数据,最后才碰训练命令。顺序别乱,乱了你会在「环境有问题还是数据有问题」之间来回折腾,浪费的时间足够把整个管线重写一遍。

3.1 先把 Python 环境钉死:版本、CUDA 与三个依赖坑

Python 版本建议 3.8~3.10。装环境时最容易翻车的就是 Python 版本和 numpy、cv2 版本不匹配,我的做法是建一个干净虚拟环境再按 requirements 装,python 安装 numpy 库的方法不要用系统 pip 直接怼,否则后面 opencv 的 numpy 版本冲突能把你折腾一晚上。

conda create -n defect python=3.8 -y conda activate defect pip install opencv-python==4.8.1.78 # 含 cv2,Windows/Linux 通用 pip install numpy==1.24.4 # 与 py3.8 和 opencv 均兼容 pip install torch==2.0.1 --index-url https://download.pytorch.org/whl/cu118 pip install -r requirements.txt

这里的版本不是唯一正解,但要领很明确:opencv 和 numpy 存在官方绑定关系,numpy 版本过新会导致 cv2 报错;torch 的 cu118 表示 CUDA 11.8,装之前先nvidia-smi确认驱动支持。cv2 下载不下来的场景很常见,优先换国内镜像,把 pip 源指到镜像站就能解决大半问题。安装完立刻跑一行python -c "import cv2, numpy, torch; print(cv2.__version__, numpy.__version__, torch.__version__)",三行版本号打印出来才算过关。这一步别跳过,很多声称「环境装好了」的机器,实际一跑就报ImportError,卡在第一关的人比想象中多。

3.2 把 VOC 标注转成 YOLO 格式:转换脚本与四个边界坑

源码工程对标注格式通常有明确偏好,YOLO 系列要的是每个目标一行的 txt:类id cx cy w h,坐标全按图宽高归一化到 0~1。下面这份转换脚本可以直接抄,我把它拆开讲清楚每个参数为什么这么写:

import os, xml.etree.ElementTree as ET def voc_to_yolo(xml_path, out_dir, class_names, min_size=2): 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.findall("object"): name = obj.find("name").text if name not in class_names: # 出现未登记类别直接跳过 continue box = obj.find("bndbox") x1, y1 = float(box.find("xmin").text), float(box.find("ymin").text) x2, y2 = float(box.find("xmax").text), float(box.find("ymax").text) w, h = x2 - x1, y2 - y1 if w < min_size or h < min_size: # 小于2像素的高精度缺陷靠人工补标 continue cx, cy = (x1 + x2) / 2 / img_w, (y1 + y2) / 2 / img_h lines.append(f"{class_names.index(name)} {cx:.6f} {cy:.6f} {w/img_w:.6f} {h/img_h:.6f}") with open(os.path.join(out_dir, os.path.basename(xml_path)[:-4] + ".txt"), "w") as f: f.write("\n".join(lines)) class_names = ["scratch", "dent", "pit", "stain"] # 按训练配置顺序写 voc_to_yolo("data/annotations/0001.xml", "data/labels", class_names)

逻辑拆开看:用size/width和size/height拿到图像原始宽高,所有归一化都依赖这两个值,写错会导致框整体偏移;w < min_size这个过滤是给高精度缺陷留的口子,太小的框归一化后不足 1 个像素,模型学不到,宁可不标也不喂脏数据。转换时最容易出的边界问题有三个:同名 xml 和图片不在一个目录、类别名顺序和训练配置不一致、某些标注工具导出的 xmin 大于 xmax 的异常框。所以转完先随机挑 5 个 txt,在原图上把框画出来核对一遍再进训练,这五分钟能省下后面一整天的排错。

3.3 训练命令与关键参数:一次跑通的基准线

环境通了、数据格式对了,下一步就是跑通一次完整训练。以常见的目标检测工程为例,最小可复现的基准命令长这样:

python train.py --data data/defect.yaml --weights yolov8n.pt \ --epochs 200 --batch 8 --imgsz 1280 --workers 4 --device 0

--imgsz 1280是我坚持的习惯:零件表面缺陷属于小目标,640 输入在多数工程里会把细微划痕缩没;显存不够时优先降 batch 而不是降分辨率。--weights用预训练权重而不是随机初始化,工业数据量通常只有几千张,从头训收敛很慢且精度天花板低。--workers 4是数据加载线程数,Windows 上经常出现 0 号进程报错,改为 2 或 0 往往能绕开。训练日志里重点看三类信息:loss 曲线、验证集 mAP、每类缺陷的 recall。mAP 会被大类拉高掩盖小类问题,所以每类单独看 recall 更接近产线真实表现。如果 loss 前几轮不降反升,先确认学习率是不是太大;如果 loss 降了但 recall 纹丝不动,回到数据格式上找问题,而不是继续加轮数。

3.4 推理:一张零件图出来的是什么

训练结束后的推理命令往往不给全套参数,我补上一个完整用法,读完就能知道输出里每一项是什么意思:

python infer.py --source data/sample/defective_01.jpg \ --weights runs/train/exp/weights/best.pt --conf 0.15 \ --iou 0.45 --save-json --save-crop

--conf 0.15看起来低到不可思议,但这是工业质检的常规操作:先压低置信度保住召回率,再用后续的面积过滤和人工复核把误报压回去。产线漏检一个缺陷,比多报十个误检严重得多,这是质检和安防场景在参数上的本质差异。输出里.json文件存的每个框都有 class、confidence、bbox 四个坐标;--save-crop会把每个缺陷裁成小图,方便你一眼检查模型到底圈了什么。第一次推理发现框的位置完全对不上图,八成不是模型的问题,而是 3.2 节转换脚本里图像宽高取错了。跑完先看置信度分布直方图:如果所有框都挤在 0.9 以上,说明模型很自信,可以适当拉高阈值降误报;如果大片框压在 0.2 附近,说明训练没收敛,先回去调数据。

4. 参数调优实录:把精度从 70% 拉到 95% 的六个设置

训练能跑通只是起点,离「高精度」还差着一段距离。下面这些参数是我在类似工程里反复验证过、几乎每次都见效的设置。它们不一定全部适用,按顺序做,每做一步都用验证集看一次变化,别一次全上,否则出了问题你根本不知道是哪个设置搞的鬼。

4.1 分辨率与切图:小缺陷的底线是像素数量

先量化一个标准:缺陷最小宽度在输入图上必须大于 3 个像素,否则任何模型都学不到有效特征。640 输入下,一个真实 8 像素宽的划痕会被压到 2~3 像素,正好卡在悬崖边上。解法有两种:把imgsz提到 1280,或者做切图推理——把原图按 1024 窗口、20% 重叠切成多块分别检测再合并结果。切图的好处是缺陷相对尺寸变大,代价是推理时间翻倍,跨块同一缺陷会重复检测,需要按重叠区域做 NMS 合并。产线节拍允许的话,我一般优先 1280;节拍紧张就退到 960 加切图。这个参数值得专门做一组消融:同一份验证集分别跑 640、960、1280,画出 recall 随分辨率的变化曲线,提升 5~10 个点是很常见的,而它只是改一个数字的事。

4.2 数据增强:哪些加了有用,哪些加了翻车

工业场景的数据增强跟自然图像完全不同。适合的增强是轻度亮度抖动(模拟不同班次灯光老化)、高斯模糊(模拟对焦轻微失准)、随机擦除(模拟零件表面的油污遮挡)。不适合的有两类:随机翻转和强颜色扰动。带螺纹的零件翻转后螺纹方向在物理上不存在,模型会学会识别「不可能的方向」而不是缺陷本身;金属件轻微色差被饱和度和色相扰动放大后,会把良品造成次品。增强配置通常长这样:

augmentation: hue: 0.02 # 色调扰动,工业件压低再压低 saturation: 0.3 brightness: 0.4 # 亮度扰动对光源老化最有效 fliplr: 0.0 # 带方向性纹理的零件必须关掉 flipud: 0.0 blur: 0.1 # 高斯模糊概率 mosaic: 0.5 # 拼接增强对小目标有效,但也容易把图切碎

这里的每一条都有代价。mosaic 把四张图拼一起训练,能显著提升小目标召回,但会把边缘的缺陷截断、标注错位。常见的解法是训练后半段把 mosaic 概率调回 0 再微调几个 epoch,让模型适应完整图像,这是 YOLO 系工程的常用节奏,能挽回一部分被拼接副作用的精度。

4.3 正负样本不平衡:Focal Loss 与难例挖掘

零件表面缺陷的另一个特性是「缺陷少、背景多」。一张图上 99.9% 是正常表面,普通交叉熵损失会把注意力全浪费在大片易分的背景上。Focal Loss 的思路就是压低易分样本的权重,把梯度集中到难分的少数缺陷上,核心代码并不长:

import torch import torch.nn.functional as F def focal_loss(logits, targets, alpha=0.25, gamma=2.0): ce = F.binary_cross_entropy_with_logits(logits, targets, reduction="none") p_t = logits.sigmoid() * targets + (1 - logits.sigmoid()) * (1 - targets) factor = (1 - p_t) ** gamma # 易分样本 p_t 接近1,权重趋近0 alpha_t = alpha * targets + (1 - alpha) * (1 - targets) return (alpha_t * factor * ce).mean() loss = focal_loss(pred_cls, cls_targets, alpha=0.25, gamma=2.0)

逻辑说明:p_t是模型对正确类别的置信度,越接近 1 说明越好分,(1-p_t)^gamma会把它的损失权重压小;alpha=0.25在类别不平衡严重时给少数类一个固定抬升,alpha 太小少数类学不动,太大易分样本权重也起来了。gamma 默认 2.0 一般够用,gamma 太大难例权重过高会让训练震荡。另一个更土但同样有效的方案是难例挖掘:每轮训练结束后,把验证集上误检的图挑出来,人工确认后重新塞进训练集,迭代两三轮,误报率能明显下降。这个方法没有理论门槛,但对产线场景特别管用,因为现场的误报模式往往高度集中。

4.4 训练策略:预训练、余弦退火与 EMA

工业数据集量级通常撑不起从头训练,从公开预训练权重起步几乎是必须的。下面这张表是我在同一份零件数据集上对比过的推荐值:

参数推荐值说明
lr00.001~0.01预训练权重起步用 0.001,避免破坏特征
warmup3 epochs前 3 轮线性升温,稳住早期梯度
cos_lrTrue余弦退火收敛更稳,末期不震荡
ema_decay0.9999指数滑动平均,精度和稳定性双提升
patience30 epochs验证集不再提升就早停,省算力
freeze_layers10先冻结 backbone 跑 50 轮,再解冻全量微调

EMA 常被忽略,但它是免费的午餐:每步保存权重滑动平均值,推理时用平均权重通常比最终权重高一两个点,几乎不用调参。早停 patience 设 30 是为了防止训练把噪声也背下来——验证集 loss 连续回升就要果断停。freeze 的用法是先用冻结 backbone 保住预训练特征,解冻后学习率要同步降一个量级,否则会把预训练学到的东西冲掉。完整流程我一般是:预训练权重加载 → 冻结 backbone 50 轮 → 解冻全量 50 轮 → 看曲线决定是否继续。这套流程在多数零件数据集上都能收敛到稳定区间。

4.5 验证指标别只看 mAP:把漏检率放到第一位

mAP 是论文指标,产线考核的是「漏检率」和「误检数」。你应该专门准备一份「漏检测试集」,全部是能引起客户投诉的明显缺陷,跑完推理统计漏了多少条;漏检率要压到千分级,误检可以容忍但要有现场复核机制。具体调法是先按 recall 找阈值:把 conf 从 0.5 一路降到 0.1,画出 recall 曲线,找到 recall 不再提升的拐点,再把 conf 定在拐点上方一点;紧接着用面积阈值把小于 20 像素的小噪点滤掉,误报通常会成批消失。这套流程比盲目调模型参数划算得多,因为产线部署阶段真正要动的往往只是阈值,不是网络结构。文档上写的「高精度」如果没有这组数据支撑,客户验收时是不认的。

5. 避坑:高精度缺陷检测最常见的 5 个翻车现场

下面这几条是我在这个方向踩过最深的坑,基本是换来的血泪经验。每一条都按「现象 → 原因 → 解决」写,遇到类似症状可以直接对照排查。翻车不可怕,可怕的是翻完不知道翻在哪。

5.1 误报爆炸:模型把拉丝纹理当成划痕

现象:验证集精度很高,一上线连续误报,车间的普通纹理件几乎每张都被框出来。

原因:训练集里「无缺陷」的干扰纹理没有作为负样本进模型,或者标注时把纹理和缺陷混在一起,模型学到的是「有横纹就报划痕」。

解决:单独挑一批外观有纹理但判定合格的零件图,全部作为负样本参与训练;再把验证集误报图塞回训练集做一轮难例迭代。确认标注规范时记住一个原则:只有客户会投诉的外观异常才叫缺陷,材质本身的纹理和色差不是。很多工程的精度瓶颈不是模型能力,而是标注规范里没写清楚「不报什么」。

5.2 换个光源召回掉一半:模型过拟合了当时的打光

现象:同一台设备白天跑得好好的,夜班换班或灯泡老化后,缺陷召回率掉到不到一半。

原因:模型把亮度分布当成了特征的一部分。工业现场光源老化、电压波动、不同时段环境光是常态,而训练图往往只在一两个时段采集。

解决:在数据管线里固定加一步灰度归一化,输入模型前把图像均值和方差拉齐;增强配置里把 brightness 扰动调到 0.4~0.6;产线方案里给光源加稳压和定期标定。还有一条便宜好用的预处理:用 CLAHE 直方图均衡替代原始灰度,再观察模型有没有变稳。光源稳定性是工业质检的生命线,算法只能兜底,不能根治。

5.3 小缺陷在 640 输入下根本学不到

现象:训练 loss 掉不下去,小划痕类别的 recall 长期为零,放大看输出框全是空的。

原因:输入下采样把 3~5 像素宽的缺陷直接缩没了。640 输入下网络最深层的特征图下采样 32 倍,小目标几乎不占任何有效的神经元响应。

解决:把imgsz提到 1280,优先保住小缺陷的像素数量;网络层面用带 P2 低层特征的分支结构,低层特征图分辨率更高,对小目标更友好;显存撑不住就改切图推理,1024 窗口加 20% 重叠。最后用 4.1 节的方法量化确认缺陷有效像素数是否大于 3,这一步可以在训练前就做完,别等训完才发现方向错了。

5.4 显存不够 batch 降到 2,精度反而回退

现象:同一份数据从大显存换到 8GB 显卡训练,batch 从 8 降到 2,最终精度掉了五六个点。

原因:batch 太小时批归一化的统计量跟着单个 batch 抖,均值和方差估计不准,相当于每次前向都在不同分布上跑。这是显存不足最容易掉进去的坑。

解决:优先用梯度累积模拟大 batch,每 4 个小 batch 累积更新一次;或冻结 BN 层,只训练卷积权重和检测头;或干脆换成不含 BN 的轻量结构。注意用 EMA 权重做推理验证,它能掩盖一部分 BN 抖动带来的劣化,让最终评测更接近真实部署水平。

5.5 新零件型号上线,老模型成了玄学

现象:换了一个表面处理工艺的同类零件,同一套模型从 95% 精度跌到 70%,错法很随机,看着像玄学。

原因:新型号的纹理、颜色、反光特性都变了,数据分布发生漂移。模型在旧分布上学的特征,到了新分布上全是没见过的东西。

解决:工艺变更后不要直接上线,先在新型号上取 20~50 张带标注图微调,冻结 backbone 只训练 head,几十轮就能恢复大部分精度;上线前用灰度直方图对比新旧数据的分布,直方图形状差异显著就直接触发重新标注流程。把「数据漂移检查」做成固定步骤,就能把这类翻车提前拦下来。工业现场的变化永远比模型快,接受这一点,你的系统才会预留出应变的口子。

6. 进阶:用 Grad-CAM 与缺陷面积测量给「高精度」收尾验证

模型说「检测到了」不一定是真的在端到端层面看对了。我在交付这类工程时,会额外做两步验证和一步量化,这三步做完,才算敢说「高精度」有实据。第一步是 Grad-CAM 可视化,用 torchcam 这类库,取 backbone 最后一个卷积层的特征图,按类别权重叠加出热力图,叠加在原图上看模型的注意力集中在哪里。如果划痕检测的热力集中在纹理边缘或者反光带上,说明模型学的是干扰特征而不是缺陷本身,这种模型换线必翻车。

from torchcam.methods import GradCAM cam = GradCAM(model, target_layer="model.10", input_shape=(3, 1280, 1280)) with cam.record(): out = model(img.unsqueeze(0)) weights = cam.compute_cam(out.argmax(dim=1).item())

这段代码把训练好的模型包一层 GradCAM,自动算出一张与输入图同尺寸的热力图,越亮的区域就是模型决策的依据区。读图的要领是:热力图应该死死咬住缺陷本体,而不是散布在正常纹理上。

第二步是从「框」到「像素」的量测。检测只能告诉你有缺陷,品控还需要知道缺陷面积和尺寸。对每个检测框做局部二值化或边缘提取,再用连通域分析拿到精确的缺陷像素面积,配合标定好的像素-毫米比例换算成实际面积。

mask = cv2.inRange(gray_crop, low_thresh, 255) num, labels, stats, _ = cv2.connectedComponentsWithStats(mask, connectivity=8) area_px = max(stats[1:, cv2.CC_STAT_AREA], default=0) # 最大连通域面积 area_mm2 = area_px * (mm_per_px ** 2)

stats[1:, 4]里存的是每个连通域的像素数,取最大那个作为缺陷面积;mm_per_px由相机标定得到。这一步把「高精度」落实到了可测量的层面,也是客户验收时最认的交付物。

第三步是产线验收的三个固定动作:跑一遍专门准备的漏检测试集;把连续 8 小时采集的图全部过一遍看误报趋势;拿标定好的卡尺实测十个缺陷的尺寸,与模型输出的面积交叉比对。前两遍过了,这个模型才敢并线生产。我自己的教训是:不要因为训练集 mAP 好看就觉得大功告成,现场不满意的情况我遇到过不止一次,根源都在于没做上面这三步验证。每次交付前把它走一遍,已经能拦掉大部分线上问题。这个方向本身很值得投入,但它的价值在于验证闭环,而不在模型刷分。希望帮到你。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询