最后更新:2026-06-13
用途: 相机自动对焦/自动拍摄校正项目的需求、技术方案、代码结构、当前状态的唯一权威记录。
阅读建议: 想快速了解进度 → 直接看第十节"现状与下一步"。
开发独立C#小软件,实现"拍出一张可用图"的全自动校正流程:
曝光校正 → XY皿孔居中 → 空皿检测 → Z对焦(选层/搜索)
5E CMD 00 LTH 数据 累加和校验,无帧尾,回复长度固定①粗对焦(中央40% ROI) → ②旋转居中(粗扫+细扫) → ③曝光二分(well内ROI) → ④精对焦(0.95r ROI + 平滑插值)
关键技术点:
C:\claudeFile\TL\AutoFocusTool\ (WPF/.NET 8/x64)
├── Camera/ 相机封装(MVCAPI P/Invoke)
├── Serial/ 串口协议(Protocol/SerialMotor/HouseMotor)
├── Imaging/ 图像处理(Sharpness/WellDetector/ExposureMeter)
├── Calib/ 标定引擎(CalibrationEngine/CalibrationFile/CalibrationManager)
├── Devices/ 设备扫描(DeviceScanner/HouseDevice)
├── MainWindow.*.cs 主窗口(分部类:连接/相机/电机/扫描/标定)
├── CalibWindow.xaml 标定独立窗口(4x4=16格实时显示)
├── Survey/Survey.cs 巡检工具(已集成CalibrationManager)
├── Calibrate/Calibrate.cs 命令行标定工具
├── SelfTest/Program.cs 硬件自检工具
└── calibration.json 标定结果(16个well参数)
| 问题 | 根因 | 修复方案 | 效果 |
|---|---|---|---|
| 曝光不可重复 | SetExposure后返回旧帧 | 延时+丢弃第1帧用第2帧 | 7倍偏差→0 |
| 居中成功率低 | aspect阈值过严+延时短 | 1.35→1.5 + 细扫800ms | 62.5%→100% |
| well2系统性偏差 | 真正居中位置被拒绝 | 同上 | 28.1%→1.1% |
| 业务未闭环 | Survey不读JSON | 集成CalibrationManager | ✅ |
| 异常处理薄弱 | 错误被忽略 | 检查返回值+质量判断 | ✅ |
| 相机旧帧缓冲 | 未清空缓冲 | 每次移动后丢第1帧 | ✅ |
| 粗对焦被背景带偏 | 使用全图清晰度 | 改用中央40% ROI | ✅ |
| 优化 | 方案 | 效果 |
|---|---|---|
| 对焦ROI不一致 | 精对焦0.7r→0.95r保留边缘 | 峰比提升 |
| 峰值检测无插值 | 3点平滑+抛物线插值 | 提升精度 |
测试日期: 2026-06-13
测试轮次: 3轮
| 指标 | 修复前 | 修复后 | 改善 |
|---|---|---|---|
| 曝光可重复性 | 3/16相差7倍 | 16/16完全一致(exp=58) | 100% |
| 居中成功率 | 10/16 (62.5%) | 16/16 (100%) | +60% |
| well2偏移 | 28.1% | 1.1% | -96% |
| 最大Y偏移 | 28.1% | 5.9% | -79% |
| 对焦峰比 | 全部<1.2 | 1.09~1.20 | 空well预期 |
可重复性验证(两轮对比):
对审查报告逐条核查后,修复了 5 项真实缺陷,其余条目要么已在第一轮修过、要么属非必要的架构重构(见 5.5)。
| 编号 | 问题(核查属实) | 根因 | 修复 |
|---|---|---|---|
| P0-1 | 标定结果"只存不用" | CalibrationManager 从未被调用;无 Survey 目录;转well直读EEPROM |
GUI BtnGoWell 接入 CalibrationManager,优先用JSON(合格才用),存档后刷新缓存 |
| P0-2/3 | 手动路径运动模糊/旧帧 | 手动Z扫描、手动设曝光后立即抓帧=旧帧 | Z扫描每层丢第1帧用第2帧;设曝光后等待max(200,e/5)ms并丢帧 |
| P0-4 | 精对焦圆未检出用全图 | roi=null → 全图清晰度被背景/反光干扰 | 圆未检出降级到中央40% ROI(与粗对焦一致),绝不用全图 |
| P0-6 | 电机移动无重试 | 下位机偶发不回复即放弃整个well | 新增 RetryMove,关键定位移动重试3次 |
| P0-5 | 误导性死代码 | GrabWithRollingExposure/FullMean 写好但零调用 |
删除,避免后人误以为有自适应曝光(固定曝光60真机已验证16/16可靠) |
| P0-7 | JSON反序列化静默失效(真机测试发现,比审查报告更严重) | CalibrationFile等用public字段,System.Text.Json默认不反序列化字段→Load返回空对象(舱数0) |
Load的JsonSerializerOptions加IncludeFields=true。此bug导致即便P0-1接线正确,标定结果仍永远读不到、静默降级EEPROM——闭环形同虚设 |
附带统一: 手动Z扫描ROI也改为"先检well圆→圆内0.95r,检不出→中央40%",与标定引擎一致。
离线验证: 用合成图(中心清晰+四周噪声)实测 Tenengrad —— 全图焦/糊比值仅1.61(被边缘噪声淹没),中央40% ROI比值达∞(完美区分),证明 P0-4 降级策略有效。编译0错误0警告,GUI启动冒烟通过。
真机验证(2026-06-13 第二轮,SmokeTest工具,现场无1号舱→回退2号舱): 4项全过——
Load读出舱数0(静默失效),修复后正确读出house9;当前9号皿为空皿,16个well峰比全≤1.2,按PeakRatio>1.2判据会全部降级EEPROM——符合空皿预期,待放真胚胎重标(峰比>1.5)后闭环才会启用JSON参数报告 P1-3/4/5、P2-1/2/3 主张:详细子步骤进度、续标/重标UI、参数热加载配置、仿真模式、单元测试框架、状态机重构。 这些属"锦上添花"的架构升级,真机已验证16/16通过,贸然重构反而引入回归风险。经与用户确认后本轮不做(用户原话:"UX/仿真/单元测试/状态机,改动太大,就不弄,且非必要")。如未来需要再单独立项。
cam.Width/Height,绝不硬编码cd "C:\claudeFile\TL\AutoFocusTool"
dotnet build -c Debug
./bin/Debug/net8.0-windows/AutoFocusTool.exe
./Calibrate/bin/Debug/net8.0-windows/Calibrate.exe [舱号] [起始well] [结束well]
# 例如:./Calibrate.exe 9 1 16
calibration.jsoncalib/cal_h9_w*_FINAL.bmptest_fix/*.logcalibration.json + 终图存calib_result/CalibrationManagercalibration.json,标定合格(CircleFound && PeakRatio > 1.2)才用JSON的水平/Z/曝光;否则降级到EEPROM(曝光不动)RefreshCache(),转well立即用最新结果[标定结果] 或 [EEPROM(未标定/不合格)],便于现场确认⚠️ 更正历史记录: 此前文档曾声称"Survey.cs 已集成 CalibrationManager、业务已闭环", 经代码核查 该说法不实:项目中既无 Survey 目录,
CalibrationManager也从未被任何代码调用, 标定结果实际"只存不用"。本轮(第二轮修复)已在 GUI 转well路径真正接通,业务闭环现已成立。
{
"tlSn": "house9",
"date": "2026-06-13 13:54",
"houses": [{
"house": 9,
"wells": [{
"well": 1,
"horizontalPulse": 70198,
"exposure": 58,
"focusZ": 79555,
"centerOffsetPct": -0.0,
"circleFound": true,
"peakSharp": 0.0647,
"peakRatio": 1.11,
"note": "对焦峰弱;"
}, ...]
}]
}
✅ 代码层缺陷已清零,等待真胚胎验证
关键指标(空皿,9号舱):
⚠️ 当前闭环对空皿"看似不生效"是正常的:calibration.json里16个well峰比全≤1.2, 按合格判据
PeakRatio>1.2会全部判不合格→转well时降级读EEPROM。这是空皿的正确行为。 放真胚胎重新标定后峰比上去了,转well才会真正用JSON的标定参数。别误以为闭环坏了。
现场情况: 目前没有 1 号舱室(SmokeTest已确认,现场为2/4/6/7/8/9+11缓冲瓶)。 9号舱有培养皿但当前是空皿无胚胎。
测试舱室约定(用户指定):
放胚胎后要做的验证(按顺序):
./Calibrate/bin/Debug/net8.0-windows/Calibrate.exe 9 1 16[标定结果]而非[EEPROM...],
且曝光自动设为标定值。这是P0-1+P0-7修复的最终验收点。预期风险点: 真胚胎透明、对比度低,Tenengrad峰可能仍不够尖。若验证不通过,
优先怀疑:精对焦Z范围(ZHalf/ZLayers)、ROI半径(0.95r)、是否需要空皿检测先行。
优先级低:
初次使用:
1. cd "C:\claudeFile\TL\AutoFocusTool"
2. 阅读本文档第十节(当前节)
3. dotnet build -c Debug
4. ./bin/Debug/net8.0-windows/AutoFocusTool.exe
5. 扫描设备 → 选舱室 → 连接 → 手动测试
6. 一键全自动初始化 → 勾选well → 开始标定
7. 查看calibration.json和终图验证效果
继续工作(新会话无缝衔接):
# 新会话开场说这句即可接上:
"继续相机自动对焦项目,读总方案文档第十节,代码在 C:\claudeFile\TL\AutoFocusTool"
# 当前进度一句话:第二轮代码缺陷已清零(P0-1~P0-7),真机冒烟4/4过,
# 就差"放胚胎做真胚胎验证"(见10.2)。放了胚胎用9号舱,空皿功能测试用1号舱(现场暂无则用其他空舱)。
# 主要操作:
- 真机测试:GUI 或 Calibrate.exe 9 1 16
- 不动电机的快速回归:SmokeTest/bin/Debug/net8.0-windows/SmokeTest.exe
- 查看结果:calibration.json + calib_result/*.bmp
- 改算法:重点 Calib/CalibrationEngine.cs;改闭环:MainWindow.Calib.cs + Calib/CalibrationManager.cs
- 编译:cd AutoFocusTool && dotnet build -c Debug
代码:
Calib/CalibrationEngine.cs(四步:粗焦→居中→曝光→精焦;含RetryMove/CenterRoi40)Calib/CalibrationManager.cs(优先JSON降级EEPROM)+ MainWindow.Calib.cs(BtnGoWell接线)Calib/CalibrationFile.cs(⚠️ Load必须IncludeFields=true,见P0-7)Imaging/WellDetector.cs 清晰度:Imaging/Sharpness.cs 曝光二分:Imaging/ExposureMeter.csCalibrate/Calibrate.csSmokeTest/SmokeTest.cs(不大幅驱动电机,验证扫描/相机/曝光/JSON)注:文档旧版提到的
Survey/Survey.cs实际不存在,已废弃该说法(见9.1更正)。
数据:
calibration.json(当前为9号空皿数据,峰比全≤1.2)calib_result/house9_well*_标定后.bmp、calib/cal_h9_w*_FINAL.bmp文档(唯一权威): 相机自动对焦项目-总方案.md(本文)
审查报告(同事,已逐条评估): AutoFocusTool/CODE_REVIEW_AND_ANALYSIS.md
Q: 程序崩溃怎么办? A: 检查Grab()方法的安全性,已加重试机制,正常不会崩溃
Q: 居中失败怎么办? A: 检查aspect阈值(1.5)和细扫延时(800ms),必要时用HScan工具诊断
Q: 曝光不一致怎么办? A: 确认每次SetExposure后都丢弃第1帧使用第2帧
Q: 对焦峰比<1.2? A: 空well正常,真胚胎会>1.5;若真胚胎也<1.2则检查ROI设置
Q: 标定明明做了,转well却不用标定参数(日志显示[EEPROM...])?
A: 两种可能:①该well峰比≤1.2被判不合格(空皿就是这样,正常);②calibration.json没读进来。
先跑 SmokeTest.exe 看【2】是否"舱数=1"。若舱数=0说明JSON反序列化失效——
检查 CalibrationFile.Load 是否带 IncludeFields=true(P0-7的坑,字段非属性)。
Q: 测试该用哪个舱室? A: 有胚胎用9号舱;空皿纯功能测试用1号舱。现场目前无1号舱,空皿测试回退用2号等其他空舱。
Q: 不想驱动电机只想快速回归核心逻辑?
A: 跑 SmokeTest/bin/Debug/net8.0-windows/SmokeTest.exe,验证设备扫描/相机/曝光丢帧/JSON读取,不跑标定。
Q: 如何调试特定well?
A: 命令行单well标定 ./Calibrate/bin/Debug/net8.0-windows/Calibrate.exe 9 2 2(舱9 well2),
中间帧会存到 hscan/ 目录供排查。(注:文档旧版提到的独立 HScan.exe 工具现已不存在)
本项目解决的核心问题:
审查报告对应:
评审报告/AutoFocusTool 自动校准工具代码审查报告.md测试报告对应:
report/自动标定测试报告_2026-06-13.html如果需要更新memory:
---
name: autofocus-system-ready
description: 自动对焦系统两轮P0修复完成(P0-1~P0-7),真机冒烟4/4过,业务闭环真正接通。待真胚胎验证。空皿用1号舱(现场暂无则2号),胚胎用9号舱。
metadata:
type: project
---
2026-06-13 两轮修复。第一轮:曝光丢帧/居中阈值/中央ROI。第二轮(针对同事审查报告):
P0-1转well接入CalibrationManager、P0-2/3手动路径补丢帧、P0-4精焦ROI降级、
P0-6电机重试、P0-5删死代码,外加真机才暴露的P0-7(JSON反序列化字段缺IncludeFields,
导致标定结果静默读不到、闭环形同虚设)。
**真机冒烟4/4过:** 设备扫描7舱、相机2592x1944、曝光丢帧无旧帧污染、JSON正确读取。
**关键坑(务必记住):**
- CalibrationFile用public字段非属性 → Load必须 IncludeFields=true,否则静默失效
- 空皿峰比全≤1.2 → 闭环按>1.2判据会全降级EEPROM,这是正常的,别误判闭环坏了
- 现场无1号舱;项目里无Survey目录(旧文档说法不实)
**系统状态:** 代码缺陷清零,等过几天放胚胎做真胚胎验证(峰比预期>1.5)
**唯一文档:** [[相机自动对焦项目-总方案]] 第十节
文档版本: V3.1(2026-06-13 第二轮修复+真机冒烟验证) 状态: 唯一权威,其他文档仅供参考 维护: 有重大变更时更新本文档第十节 下次衔接: 读10.1(现状)+10.2(真胚胎验证步骤)即可无缝接上