- src/: 最终交付物(solve.py base64 API、method_l_shape.py 核心算法、verify_result.py 验证工具) - docs/: 方案文档与实验演进记录 - try/: 历史实验脚本(A~K 方法) - 10/10 样本求解成功,3 个独立真值锚点偏差 <=4px
102 lines
5.1 KiB
Markdown
102 lines
5.1 KiB
Markdown
# 实验记录与最终结论
|
||
|
||
> 本文为历史实验日志,经验总结已沉淀至 `docs/solution.md` 与
|
||
> `docs/experiments.md`,以 docs 为准。
|
||
|
||
## 任务
|
||
|
||
对「拖动重叠」验证码:给定背景大图(552×344)与 mark 小图(110×110 RGBA),
|
||
离线求出 mark 应拖动重叠的目标区域偏移。
|
||
|
||
## 关键发现(决定技术路线)
|
||
|
||
1. **mark 的 RGB 是"捐赠补丁"**:其内部是场景纹理,与洞内内容无像素关系。
|
||
实测真掩码 NCC 全图任意位置 ≤0.57(若"洞=该处照片变暗"则真目标应≈1.0),
|
||
因此**一切基于 RGB/灰度的模板匹配(方法 A/A2/C)原理上不可行**,
|
||
早期 0.7 的高分全是小尺度纹理巧合。
|
||
2. **洞是叠加在照片上的实心暗色几何覆盖物**:形状 = mark 的 alpha 轮廓,
|
||
尺度 ≈1.0、旋转 ≈0;干扰项是同形的缩放/旋转实例。
|
||
因此唯一可靠信号是 **alpha 轮廓 + 尺度 + 旋转**。
|
||
3. 照片纹理会产生大量虚假"贴合":纯倒角距离会被草地等密纹理击败
|
||
(早期方法 D/E 失败的根因),必须加方向约束与洞内部特征。
|
||
|
||
## 方法演进(均位于 try/,输出 try/out/<方法字母>/)
|
||
|
||
| 方法 | 思路 | 结论 |
|
||
| --- | --- | --- |
|
||
| A | 蒙版 CCORR 多尺度 | 废弃:不减均值、跨尺度不公平 |
|
||
| A2 | 蒙版 CCOEFF + 峰显著度 | 基线可用但会锁纹理(41ac 分歧样本的来源) |
|
||
| B | SIFT + RANSAC | 仅 2 个纹理丰富样本可用(4db9/d7a7,作为真值锚点保留) |
|
||
| C | 旋转感知 NCC | 第一阶段候选即错,旋转校验无法挽回 |
|
||
| D/E/F/G | Chamfer / 覆盖率 / 通用轮廓 / 连通域 | 小尺度纹理饱和 / 背景轮廓合并 |
|
||
| H/I/J/K | alpha 轮廓 + 局部对比度 / 暗目标分割 | 阈值敏感,误检集中在照片纹理 |
|
||
| **L** | **方向感知倒角 + 洞内部特征 + 局部旋转扫描** | **最终方案,10/10 OK** |
|
||
|
||
## 最终方案(src/method_l_shape.py)
|
||
|
||
1. **粗扫**:尺度 0.85–1.15(步长 0.025)× 全图位置,评分:
|
||
`方向感知倒角DT + 20×内部边缘密度 + 0.5×max(0, 内-环亮度差)`
|
||
- 倒角带方向:边界点只匹配同法向桶(9 桶×20°)的 Canny 边缘,
|
||
草地等无方向纹理被自然抑制;
|
||
- 内部边缘密度:洞内部实心平坦(≈0),纹理区内部边缘多;
|
||
- 内-环亮度差:洞比周围暗(实测 -40~-104),误检区不暗(+6)。
|
||
2. **NMS 取 top-5 候选**。
|
||
3. **局部旋转扫描**:每候选 36 角(步长 10°)× ±3px 平移,得最佳旋转角
|
||
rot*与精修分;近并列(±0.15)角中取离 0 最近者为 rot*
|
||
(兼容星形等旋转对称形状)。
|
||
4. **选择**:`|rot*|≤12° 且 0.96≤s≤1.05` 的候选中取精修分最低者;
|
||
否则取 |rot*| 最小并标 AMBIGUOUS。
|
||
|
||
实测判别力:真目标 rot*=0 且 rot=0 拟合分明显低于干扰项
|
||
(干扰项 rot*≠0 或 rot=0 分数高 1~2 分)。
|
||
|
||
## 最终结果(offset = mark 110×110 画布左上角应放置的位置)
|
||
|
||
| 样本 | offset | 洞 bbox 左上角 | 尺度 | rot* | 精修分 | 备注 |
|
||
| --- | --- | --- | --- | --- | --- | --- |
|
||
| 2a313202f58c | (370,114) | (373,125) | 1.025 | 0° | 4.04 | |
|
||
| 41ac8781f7e9 | (398,151) | (409,153) | 1.000 | 0° | 4.40 | 右月牙;左月牙为干扰 |
|
||
| 444d0ea7c8bb | (178,148) | (183,160) | 1.000 | 0° | 4.50 | 轮廓分析交叉验证 ✓ |
|
||
| 4db94793ec6d | (297,143) | (306,146) | 1.000 | 0° | 2.43 | SIFT 真值 (295.8,142.1) ✓ |
|
||
| 632f84299d75 | (113,136) | (116,147) | 1.025 | 0° | 6.82 | 拟合最弱,置信度中 |
|
||
| 6a53f4529063 | (166,152) | (170,155) | 1.025 | 0° | 4.97 | |
|
||
| 87276de26640 | (153,134) | (157,137) | 1.025 | 0° | 3.94 | 星形(椭圆角不可用,旋转扫描解决) |
|
||
| d6cd0ebb7eed | (200,55) | (209,58) | 1.000 | 0° | 5.82 | |
|
||
| d7a7f80c4554 | (171,146) | (174,157) | 1.025 | 0° | 3.11 | SIFT 真值 (167.8,146.4) ✓ |
|
||
| f4fc5aa426ce | (298,68) | (310,70) | 1.050 | 0° | 4.79 | |
|
||
|
||
可视化:`src/out/L/<前缀>-match.png`(红框=目标,其余=候选,标注 s/rot)。
|
||
|
||
## API 封装
|
||
|
||
`src/solve.py`:传入两张图片的 base64,返回拖动距离与目标位置。
|
||
|
||
```python
|
||
from solve import solve
|
||
result = solve(big_image_b64, mark_image_b64)
|
||
# result = {"ok": true, "distance_px": 297, "x": 297, "y": 143,
|
||
# "scale": 1.0, "rot": 0.0, "score": 2.429,
|
||
# "confidence": "OK", "candidates": [...]}
|
||
```
|
||
|
||
命令行:`python src/solve.py <大图路径> <mark路径>`。
|
||
|
||
- `distance_px` = mark 110x110 画布左上角应到达的 x 偏移;若拖动 UI 的
|
||
mark 初始位置不在 x=0,用 `x` 减去初始 x。
|
||
- mark 图必须含 alpha 通道(PNG),否则返回 `ok=false`。
|
||
|
||
## 复现
|
||
|
||
```bash
|
||
.venv/bin/python src/method_l_shape.py
|
||
```
|
||
|
||
## 已知边界
|
||
|
||
- 632f 的拟合分 6.82 明显高于其余样本(2.4–5.8),建议对该类样本
|
||
保留人工复核或结合更多样本校准阈值;
|
||
- 洞若与 mark 非同色/同明度或叠加深色照片上,"内-环亮度差"约束会减弱,
|
||
届时可提高方向倒角权重;
|
||
- 无 ground truth 的样本中,444d(轮廓分析)、41ac(bbox 与 alpha 尺寸
|
||
完全一致 88×106)已通过方法间交叉验证。
|