| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- using System;
- using System.IO;
- using System.Linq;
- using AutoFocusTool.Imaging;
- namespace AutoFocusTool
- {
- /// <summary>
- /// 离线验证标定算法:读已存的BMP → WellDetector找圆心 → ExposureMeter评曝光。
- /// 不连机器,快速验证算法对真实图是否有效。
- /// 用法:CalibTest.exe [目录或文件glob]
- /// </summary>
- internal class CalibTest
- {
- static void Main(string[] args)
- {
- Console.OutputEncoding = System.Text.Encoding.UTF8;
- string dir = args.Length > 0 ? args[0] : @"C:\claudeFile\TL\AutoFocusTool\survey";
- string pat = args.Length > 1 ? args[1] : "h9_w2_*.bmp";
- var files = Directory.GetFiles(dir, pat).OrderBy(f => f).ToList();
- Console.WriteLine($"== 离线标定算法验证: {files.Count} 张图 ({pat}) ==");
- Console.WriteLine($"{"文件",-22} {"圆心X",6} {"圆心Y",6} {"半径",6} {"偏移X%",7} {"偏移Y%",7} {"完整",5} {"曝光均值",8} {"饱和%",6} {"曝光判定",8} {"清晰度",8}");
- foreach (var f in files)
- {
- var (buf, w, h) = ReadBmp24(f);
- if (buf == null) { Console.WriteLine($"{Path.GetFileName(f)}: 读取失败"); continue; }
- var circle = WellDetector.Detect(buf, w, h);
- var exp = ExposureMeter.Measure(buf, w, h, circle);
- double sharp = Sharpness.Compute(buf, w, h,
- circle.Found ? RoiOf(circle, w, h) : (System.Drawing.Rectangle?)null);
- string name = Path.GetFileNameWithoutExtension(f);
- if (circle.Found)
- Console.WriteLine($"{name,-22} {circle.Cx,6:F0} {circle.Cy,6:F0} {circle.Radius,6:F0} {circle.OffsetXPct,7:F1} {circle.OffsetYPct,7:F1} {(circle.Complete ? "是" : "否"),5} {exp.Mean,8:F0} {exp.SaturatedPct,6:F1} {exp.State,8} {sharp,8:F4}");
- else
- Console.WriteLine($"{name,-22} 未检出well圆 曝光均值={exp.Mean:F0} 拒绝原因[{circle.RejectReason}] 面积={circle.AreaPct:F1}%");
- }
- }
- // well圆内ROI(内部70%)做清晰度
- static System.Drawing.Rectangle RoiOf(WellCircle c, int w, int h)
- {
- int r = (int)(c.Radius * 0.7);
- int x = Math.Max(0, (int)c.Cx - r), y = Math.Max(0, (int)c.Cy - r);
- int ww = Math.Min(2 * r, w - x), hh = Math.Min(2 * r, h - y);
- return new System.Drawing.Rectangle(x, y, ww, hh);
- }
- /// <summary>读24bpp BMP → (BGR字节[自顶向下], 宽, 高)。我们存图时h>0自底向上,这里翻回自顶向下。</summary>
- static (byte[], int, int) ReadBmp24(string path)
- {
- try
- {
- byte[] all = File.ReadAllBytes(path);
- if (all.Length < 54 || all[0] != 'B' || all[1] != 'M') return (null, 0, 0);
- int off = BitConverter.ToInt32(all, 10);
- int w = BitConverter.ToInt32(all, 18);
- int h = BitConverter.ToInt32(all, 22);
- short bpp = BitConverter.ToInt16(all, 28);
- if (bpp != 24) return (null, 0, 0);
- bool bottomUp = h > 0; h = Math.Abs(h);
- int rowSize = ((w * 3 + 3) / 4) * 4;
- var buf = new byte[w * h * 3];
- for (int y = 0; y < h; y++)
- {
- int srcRow = off + (bottomUp ? (h - 1 - y) : y) * rowSize;
- Buffer.BlockCopy(all, srcRow, buf, y * w * 3, w * 3);
- }
- return (buf, w, h);
- }
- catch { return (null, 0, 0); }
- }
- }
- }
|