726:zoffset

1

复制代码
1个像素代表几微米
值越小,放大倍率越大

即:imgResolution (μm/pixel) ↓ → 同物理尺寸对应更多像素 → 放大倍率 ↑ → 细节更精细

2

Zoffset

元件级 zoffset → BaseZ

com_zoffset 是每个元件所在 FOV 的真实 Z 高度,跟全局填的 ZOffset 做差:

复制代码
差值(mm) ÷ 分辨率(mm/层) = 层偏移量

然后用这个偏移修正算法 BaseZ------从基准层往上或往下挪几个像素层,保证搜索起点对准实际位置。

就这么简单。

对,因为板子有翘曲,不同位置的元件实际 Z 高度不一样。

复制代码
全局 ZOffset = 1.5  ← 用户填的,假设整板是平的

实际:
  左边翘起来了 → 左边元件实际 Z = 1.8  → component_zoffset = 1.8
  右边塌下去了 → 右边元件实际 Z = 1.2  → component_zoffset = 1.2

如果全用全局 1.5 算 BaseZ,左边元件搜偏低了(找不着基准层),右边元件搜偏高了(也找不着)。

所以路径规划给每个元件算自己的 zoffset,一键配置时逐个换算成各自的 BaseZ,消除翘曲影响。

3


1. Shape(形状)

PCB 上一切可检测的图形元素,是系统的最小操作单元。

复制代码
Shape = 图形(能画出来) + 检测数据(能算出来)
  • Board:基板,PCB 的物理边界
  • PadCircle:检测窗,划定一个圆形/椭圆形检测区域

--

2. 坐标

同一位置有两套坐标表达:

坐标类型 含义 类比
物理坐标 (StartX, EndX, mm) PCB 上的真实位置 现实世界的位置
像素坐标 (PixelStartX, PixelEndX, px) 图像上的位置 照片上的位置

通过 Matrix(变换矩阵)互相转换。


3. Status(状态)

每个 Shape 在检测过程中会经历一系列阶段,用位标志叠加表示:

复制代码
待检测 → 扫描中 → 扫描完 → 重建中 → 重建完 → 检测中 → 结果(OK/NG)
状态 含义
ReadyToExecute 准备好了,等待执行
Scaning 正在拍照扫描
Reconstructing 正在 CT 算法重建 3D 图像
Detecting 正在分析检测
ResultOK 检测通过 ✅
ResultNG 检测不通过 ❌

UI 根据 Status 自动变色

4. CT(计算机断层扫描)

用 X 光从不同角度拍摄,重建出物体内部的 3D 图像

三个关键参数:

参数 含义 单位
imgResolution 分辨率,每个像素代表多大 mm/pixel
zoffset Z 轴偏移,焦平面上下移动 mm
层数 重建多少层切片
复制代码
imgResolution 越小 → 放大倍率越高 → 看得越精细
zoffset 正 → 焦平面上移;负 → 焦平面下移

6. Drill(钻孔)

PCB 上需要检测的孔位,分两种:

类型 说明
通孔 (Through Hole) 从上面钻穿到下面
背钻 (Backdrill) 钻到某一层就停,不钻穿

背钻根据方向再分:上钻 (从上面钻)、下钻 (从下面钻)、上下都钻

DrillStandard = 同一个钻孔规格 { 深度, 半径 },同类钻孔归为一组,共用检测算法。


概念关系总图

复制代码
Board(基板,PCB 物理边界)
 │
 ├─ Component(元件)
 │    └─ 一组相关的检测窗
 │
 ├─ PadCircle(检测窗)
 │    ├── 坐标(物理 ↔ 像素)
 │    ├── CT 参数(分辨率 + Z偏移)
 │    ├── Status(检测生命周期状态 → 驱动颜色)
 │    ├── AlgorithmViewShapes(子形状)
 │    └── 检测结果
 │
 ├─ DrillData(钻孔数据)
 │    └── 孔类型(通孔/背钻)+ 钻深 + 层厚
 │
 └─ Template(检测模板)
      └── 复用配置到同类 Shape

一句话总结

Shape 是基本单元,通过 CT 重建 (分辨率 + Z 偏移)获取内部图像,经历 Status 生命周期(扫描→重建→检测→结果),UI 随状态)。

3

三个全局 SemaphoreSlim,全部并发数 = 1:

复制代码
_reconstructLock   (1)  →  重建:engine.setupResolver → 提交投影 → pollReconDone
_extractGlobalLock (1)  →  提取:CT 体数据从 C++ 引擎拉到内存
_detectGlobalLock  (1)  →  检测:ExecuteAlgoProcess 调 C++ 算法

为什么都设成 1?

C++ 重建/提取/算法引擎底层不是线程安全的,多个 Job 同时调会崩。所以每个阶段同一时刻只允许一个 Job 在跑。

实际跑法:

扫图完了之后,10 个 Job 并行跑,但每到重建/提取/检测这仨环节,谁先抢到锁谁先进,剩下的 await 排队:

复制代码
Job1 重建 ──┐
Job2 重建 ──┤ → _reconstructLock.WaitAsync() → 抢到的先跑,其他排队
Job3 重建 ──┘
              ↓
Job1 提取 → Job2 提取 → Job3 提取  (_extractGlobalLock 排队)
              ↓
(保存体数据 和 检测 并行)
Job1 检测 → Job2 检测 → Job3 检测  (_detectGlobalLock 排队)

保存体数据不依赖 C++ 引擎,所以不和检测抢锁,直接并行跑。

跟同事一句话:C++ 引擎不线程安全,三个全局锁各管一个阶段,保证同一时刻只有一个 Job 在调引擎。

相关推荐
向夏威夷 梦断明暄4 小时前
C# 弃元模式:从语法糖到性能利器的深度解析
服务器·数据库·c#
rick9775 小时前
C# × Python 互操不再难:DotNetPy 让两大生态真正融合
c#
ellis19706 小时前
C#/Unity清理非托管资源
unity·c#
吴可可12319 小时前
C#用OpenCVSharp提取轮廓生成CAD多段线
c#
玖玥拾1 天前
Unity 3D 笔记(十四)Unity/C# Socket 网络笔记3
服务器·网络·unity·c#
玖玥拾1 天前
Unity 3D 笔记(十七)Unity/C# Socket 网络笔记6
服务器·网络·unity·c#
geovindu1 天前
CSharp: Iterative Algorithms
开发语言·后端·算法·c#·.net·迭代算法
影寂ldy1 天前
C# HttpClient 分片下载、断点续传、暂停取消(完整项目知识点)
开发语言·c#
code bean1 天前
【C#】 主构造函数(Primary Constructors)的来龙去脉
开发语言·c#