File size: 7,598 Bytes
b8f8211
 
 
 
 
 
 
 
 
 
 
 
41ff7b3
 
 
 
 
 
 
 
0e9808f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128b81a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41ff7b3
 
 
 
 
 
128b81a
 
 
 
 
41ff7b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128b81a
 
 
 
 
 
 
 
 
 
 
41ff7b3
128b81a
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
---
license: other
library_name: onnx
pipeline_tag: image-classification
tags:
- industrial
- defect-detection
- optical-filter
- quality-inspection
- onnx
---

# 滤光片外观质检 · 开箱即用推理包

暗场成像的 IR-CUT 滤光片裁片,判**良品 / 不良**,可选输出缺陷类型(划痕 / 麻点 / 崩边)。

推理端**不需要 PyTorch、不需要 timm、不需要 GPU**,只要 4 个 pip 包。

---

## 📚 完整文档

| 文件 | 内容 |
|---|---|
| [`docs/INDEX.md`](docs/INDEX.md) | **项目总索引**:四个仓库怎么选、三个核心结论、数据一览 |
| [`docs/REPRODUCE.md`](docs/REPRODUCE.md) | **完整复现指南**:环境、数据准备、逐个实验的命令与预期数字 |
| [`docs/FILES.md`](docs/FILES.md) | **逐文件使用说明**:41 个脚本、结果表字段、51 个训练产物目录 |
| [`docs/RESULTS.md`](docs/RESULTS.md) | **全部实验结果**:42 个模型完整榜单、分割 vs 分类同口径对决 |
| [`docs/AUDIT.md`](docs/AUDIT.md) | **诚实性审计**:四道审计的原理与结果,为什么这次的高分是真的 |
| [`docs/CAVEATS.md`](docs/CAVEATS.md) | ⚠ **已知问题与边界**,上线前必读(含我犯过的评估口径错误) |
| [`docs/REPOS.md`](docs/REPOS.md) | 四个仓库逐一说明与下载方式 |

---

---

## 三种用法,任选

### A. 零安装 —— 单个可执行文件(推荐)

目标机上**不需要 Python、不需要装任何东西**,下载一个文件就能跑。模型已打进二进制。

```bash
# CPU 版(145 MB,任何 x86_64 Linux 都能跑)
chmod +x binaries/filter-predict-cpu
./binaries/filter-predict-cpu -i 图片目录/ -o result.xlsx

# GPU 版(1.3 GB,自动用 CUDA;需要 NVIDIA 驱动 ≥ CUDA 12.x)
chmod +x binaries/filter-predict-gpu
./binaries/filter-predict-gpu -i 图片目录/ -o result.xlsx
```

实测速度:CPU **22 张/秒**,GPU(RTX 4090)**3608 张/秒**### B. Python 脚本(想改代码时用)

```bash
pip install -r requirements.txt          # onnxruntime numpy pillow openpyxl
python predict.py -i sample_images/ -o result.xlsx
```

### C. 只要 ONNX,自己接

`filter_binary.onnx` 输入 `float32[N,3,320,320]`,输出 `logits[N,2]`。
预处理必须与 `predict.py:preprocess()` 一致(等比缩放补零 → 灰世界白平衡 → 逐图 z-score),否则结果不可信。

### 单张图
```bash
python predict.py -i /path/to/filter_0001.png
```
```
  文件   : filter_0001.png
  判定   : 良品
  不良概率: 0.0060
```

### 整个目录 → xlsx(递归扫描子目录)
```bash
python predict.py -i /path/to/images/ -o result.xlsx
```
输出表格:`图片名 | 判定 | 不良概率 | 相对路径`

### 附带缺陷类型
```bash
python predict.py -i images/ -o result.xlsx --with-type
```
多两列:`缺陷类型 | 类型置信度`(只对判为不良的填)

### 不想装 openpyxl
输出写 `.csv` 即可(UTF-8 BOM,Excel 直接双击能开):
```bash
python predict.py -i images/ -o result.csv
```

---

## 调判废松紧

**只有一个参数可调:`--threshold`(不良概率的判废线)。**
调高 → 判不良的更少,不良桶更纯,但漏检多。调低 → 抓得全,但误杀更多良品。

标定表(阈值在 val 集上定,test 锁箱只评一次;「产线 10%」是按产线不良率 10% 换算的):

| 档位 | 阈值 | test 误报 | test 检出 | 不良桶混入良品 | 产线10%口径 | 每万片冤杀 | 每万片漏检 |
|---|---|---|---|---|---|---|---|
| 最严 | `0.787` | 4/185 | 95.5% | **1.83%** | 16.9% | 195 | 45 |
| 保守 | `0.509` | 8/185 | 98.7% | 3.49% | 28.3% | 389 | 13 |
| **平衡(默认)** | `0.459` | 8/185 | **99.1%** | 3.48% | 28.2% | 389 | 9 |
| 宽松 | `0.411` | 9/185 | 99.1% | 3.90% | 30.6% | 438 | 9 |
| 高召回 | `0.242` | 11/185 | 99.6% | 4.70% | 35.0% | 535 | 4 |

```bash
python predict.py -i images/ -o r.xlsx --threshold 0.787    # 最严
```

> **注意**:分数分布是双峰的,0.51~0.79 之间几乎是空的,所以中间档位区分度很低。
> 真正有意义的选择是「最严 0.787」和「平衡 0.459」两档。

---

## 模型与性能

| | 判废模型 | 类型模型 |
|---|---|---|
| 文件 | `filter_binary.onnx` (16.8 MB) | `filter_4class.onnx` (85.1 MB) |
| 骨干 | mobilenetv3_large_100 (4.2M) | resnet34 (21.3M) |
| 输入 | 320×320 | 320×320 |
| 输出 | 良品 / 不良 | 良品 / 划痕 / 麻点 / 崩边 |
| test AUROC | **0.9913 ± 0.0049** | 0.9867 |
| test 平衡准确率 | 0.9746 | **0.9213** |

**速度**(实测,纯 CPU,无 GPU):约 **20 张/秒**。有 GPU 会自动用(装 `onnxruntime-gpu` 即可),约 1500 张/秒。

四分类逐类召回(test):划痕 88.0% / 崩边 94.1% / 良品 95.1% / 麻点 91.3%

---

## 这个模型可信吗

**做过 4 道诚实性审计,全部通过:**

| 审计 | 结果 |
|---|---|
| 批次指纹强度 | 92% —— 图像里**确实**带着可区分批次的信息(有作弊空间) |
| **未见类「碎」检出** | **100%** —— 这一类整类从没进过训练,模型照样抓到 |
| 跨批次泛化 | 留整个批次当考卷,AUROC 0.9862 vs 同批次 0.9911,**只掉 0.005** |
| 冻结特征对照 | 只见良品的 kNN (0.9634) **打败** 用了标签的线性探针 (0.9461) —— 拿到标签没优势,说明没有可解锁的捷径 |

这套审计不是形式:本项目上一代的图级分类模型曾拿到 AUROC=1.0,一测就发现它认的是"这张图来自哪个压缩包",30 张目检干净的图全被打 0.999+。这一代是真的。

---

## 已知边界(务必阅读)

- **验证样本量有限**:test 只有 185 张良品。0 误报的 95% 置信上界是 1.61%,
  **无法证明产线级的低误杀率**。要证明误报率 <1%,需要约 300 张干净良品;<0.1% 需要约 3000 张。
- **「不良桶混入良品」随产线不良率剧烈变化**。表里 test 口径 1.83%,
  换算到产线不良率 10% 就是 16.9%。**这个指标不是模型属性,必须绑定你的实际不良率才有意义。**
- **色调漂移未做压力测试**。原始数据存在采集配置的色调漂移(B 通道逐日 15→8→5)。
  预处理里的逐图灰世界白平衡是为此设计的,但**没有在真实漂移上验证过**。
  上线建议固定白平衡,并监控良品分数分布。
- **不可擦拭脏污检出仅约 53%**。这一类"擦不擦得掉"是物理属性,
  单张图像原理上判不了,训练时已整类排除。
- **训练数据的良品标签本身约 3.3% 存疑**(漏标的真缺陷)。误报数字受此影响。
- 输入图假定是**已裁到单片边界的暗场图**,原始尺寸 300~360px 量级。整版图或明场图不适用。

---

## 文件清单

```
binaries/
  filter-predict-cpu    零安装可执行文件,145 MB,CPU,22 张/秒
  filter-predict-gpu    零安装可执行文件,1.3 GB,CUDA,3608 张/秒
predict.py              推理脚本(需自备 4 个 pip 包)
filter_binary.onnx      判废模型 + filter_binary.json(含阈值标定表)
filter_4class.onnx      类型模型 + filter_4class.json
requirements.txt        4 个 pip 包
sample_images/          22 张样例图(来自锁箱 test,从未参与训练)
weights/                PyTorch 原始权重(.pt,需 timm + torch 才能加载)
results/                全部实验结果表、训练曲线、逐图打分
README.md               本文件
```

配套数据集:**https://huggingface.co/datasets/daipath/filter-inspection-data**