| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- using System;
- using System.Linq;
- using System.Threading;
- using System.Collections.Generic;
- using AutoFocusTool.Devices;
- using AutoFocusTool.Serial;
- using AutoFocusTool.Imaging;
- using AutoFocusTool.Calib;
- using SerialCamera = AutoFocusTool.Camera.Camera;
- namespace AutoFocusTool
- {
- /// <summary>
- /// 自动标定(连机):用 CalibrationEngine 对舱室的若干well做
- /// 居中→曝光→对焦,结果写 calibration.json。
- /// 用法:Calibrate.exe [houseSn=9] [wellFrom=1] [wellTo=2]
- /// </summary>
- internal class Calibrate
- {
- const int W = 2592, H = 1944; // MVC2000原生分辨率(参考图实测2592x1944),1600x1200会裁成中央块
- const string OutDir = @"C:\claudeFile\TL\AutoFocusTool\calib";
- const string JsonPath = @"C:\claudeFile\TL\AutoFocusTool\calibration.json";
- static void Main(string[] args)
- {
- Console.OutputEncoding = System.Text.Encoding.UTF8;
- void L(string m) => Console.WriteLine($"{DateTime.Now:HH:mm:ss} {m}");
- System.IO.Directory.CreateDirectory(OutDir);
- int houseSn = args.Length > 0 && int.TryParse(args[0], out int hs) ? hs : 9;
- int wFrom = args.Length > 1 && int.TryParse(args[1], out int a) ? a : 1;
- int wTo = args.Length > 2 && int.TryParse(args[2], out int b) ? b : 2;
- L($"==== 自动标定 舱{houseSn} well{wFrom}~{wTo} ====");
- var scanner = new DeviceScanner { Log = _ => { } };
- var houses = scanner.ScanAll();
- var h = houses.FirstOrDefault(x => x.HouseSn == houseSn && x.HasCamera);
- if (h == null) { L("未找到该舱或无相机"); return; }
- using var motor = new HouseMotor(h.PortName) { Log = _ => { }, MotorDelayMs = 1500 };
- motor.Open();
- using var cam = new SerialCamera(h.CcdIndex, W, H, 120);
- if (cam.Init() != 0) { L("相机初始化失败"); return; }
- cam.SetOpMode(0);
- motor.OpenLED();
- Thread.Sleep(300);
- var engine = new CalibrationEngine(motor, cam)
- {
- Log = L,
- OnFrame = b => { /* 命令行下不显示,GUI会用 */ },
- DebugSave = (b, name) => { try { Diag.SaveBmp(b, W, H, $@"C:\claudeFile\TL\AutoFocusTool\hscan\{name}.bmp"); } catch { } },
- };
- var houseCalib = new HouseCalib { House = houseSn, Port = h.PortName, CcdIndex = h.CcdIndex, CcdSn = h.CcdSn };
- int saveCounter = 0;
- for (int well = wFrom; well <= wTo; well++)
- {
- int hpos = motor.ReadWellHorizontalPos(well);
- int zZero = motor.ReadWellFocusZero(well);
- L($"\n── well{well} EEPROM: 水平={hpos} Z零点={zZero} ──");
- if (hpos < 0) { L("读well水平位置失败,跳过"); continue; }
- if (zZero < 0) zZero = 0;
- // 存关键帧:标定完well后存最终图
- engine.OnFrame = bb => { };
- var wc = engine.CalibrateWell(well, hpos, zZero);
- houseCalib.Wells.Add(wc);
- // 存最清晰层终图
- cam.SetExposure(wc.Exposure);
- motor.HorizontalMoveTo(wc.HorizontalPulse);
- motor.VerticalMoveTo(wc.FocusZ);
- Thread.Sleep(150); cam.GrabRgb();
- Diag.SaveBmp(cam.GetSourceBuffer(), W, H, $"{OutDir}\\cal_h{houseSn}_w{well}_FINAL.bmp");
- saveCounter++;
- }
- motor.CloseLED();
- // 写档案(合并已有)
- var file = new CalibrationFile { TlSn = $"house{houseSn}", Date = DateTime.Now.ToString("yyyy-MM-dd HH:mm") };
- file.Houses.Add(houseCalib);
- file.Save(JsonPath);
- L($"\n==== 标定完成,写入 {JsonPath} ====");
- foreach (var w in houseCalib.Wells)
- L($" well{w.Well}: 水平={w.HorizontalPulse} 曝光={w.Exposure} 对焦Z={w.FocusZ} 偏移={w.CenterOffsetPct:F1}% 峰比={w.PeakRatio:F2} {w.Note}");
- }
- }
- }
|