Files
test_demo/MX-PD-盘古 - new/PanGu.DieBonderApp/MainShell/Vision/README.md

431 lines
16 KiB
Markdown
Raw Normal View History

# Vision 模块使用文档
## 1. 文档范围
本文档说明当前 [`MainShell/Vision`](MainShell/Vision) 模块在“一个算法一个文件夹”的结构下的职责划分和推荐使用方式,重点覆盖:
- [`IImageCaptureService`](MainShell/Vision/ImageCapture/IImageCaptureService.cs) / [`ImageCaptureService`](MainShell/Vision/ImageCapture/ImageCaptureService.cs):负责按当前已准备好的相机模式执行采图
- [`IFindTemplateService`](MainShell/Vision/FindTemplate/IFindTemplateService.cs:10) / [`FindTemplateService`](MainShell/Vision/FindTemplate/FindTemplateService.cs:14):负责模板匹配算法的采图与处理
- [`VisionParController`](MainShell/Models/VisionParController.cs):负责视觉前置硬件参数准备,包括相机参数、触发模式和抓流状态
- [`FindTemplateRequest`](MainShell/Vision/FindTemplate/FindTemplateRequest.cs:8) / [`FindTemplateImageRequest`](MainShell/Vision/FindTemplate/FindTemplateImageRequest.cs:6):负责模板匹配请求建模
- [`VisionProcessResult`](MainShell/Vision/Common/VisionProcessResult.cs:8) / [`VisionProcessResult<TData>`](MainShell/Vision/Common/VisionProcessResultOfT.cs:9):负责承载通用处理状态与强类型算法结果
- [`ImageCaptureResult`](MainShell/Vision/ImageCapture/ImageCaptureResult.cs:25) / [`ImageCaptureStatus`](MainShell/Vision/ImageCapture/ImageCaptureResult.cs:11):负责承载采图状态、消息与图像对象
当前目录划分如下:
- `Common/`:共享结果模型与算法参数基类
- `ImageCapture/`:采图接口、实现与采图相关模型
- `FindTemplate/`:模板匹配算法接口、实现、请求、参数、结果
- `FindMark/`Mark 识别参数与后续算法扩展入口
- `FindDie/`Die 定位参数与后续算法扩展入口
- `FindCenter/`:中心识别草稿算法骨架
## 2. 当前模块职责边界
### 2.1 [`VisionParController`](MainShell/Models/VisionParController.cs)
负责视觉前置硬件准备:
- 设置曝光和增益
- 设置触发模式
- 设置触发源
- 设置触发延时
- 启动或停止抓流
- 设置光源参数
### 2.2 [`ImageCaptureService`](MainShell/Vision/ImageCapture/ImageCaptureService.cs)
只负责执行采图动作:
- 不再自动切换触发模式
- 不再自动切换触发源
- 不再自动设置触发延时
- 不再自动启停抓流
- 同一相机的采图请求在服务内部按相机粒度串行执行
- 通过 [`ImageCaptureResult`](MainShell/Vision/ImageCapture/ImageCaptureResult.cs:25) 返回成功、取消、无帧或设备状态异常等结果
调用方必须在采图前通过 [`VisionParController`](MainShell/Models/VisionParController.cs) 或其他上层硬件控制流程准备好相机状态。
### 2.3 [`FindTemplateService`](MainShell/Vision/FindTemplate/FindTemplateService.cs:14)
负责:
- 模板匹配参数校验
- 模板匹配采图流程组织
- 单个模板匹配结果构建
- 多个模板匹配结果集合构建
- 返回 [`VisionProcessResult<FindTemplateResult>`](MainShell/Vision/Common/VisionProcessResultOfT.cs:9) 或 [`VisionProcessResult<FindTemplatesResult>`](MainShell/Vision/Common/VisionProcessResultOfT.cs:9)
当前模板匹配算法本体仍为占位实现,尚未接入真实视觉算法库。当前占位实现会明确返回失败,避免上层流程误判为识别成功。
## 3. 当前推荐结构
当前推荐使用“一个算法一个实现”的结构,即:
- 每个算法拥有独立接口,例如 [`IFindTemplateService`](MainShell/Vision/FindTemplate/IFindTemplateService.cs:10)
- 每个算法拥有独立实现,例如 [`FindTemplateService`](MainShell/Vision/FindTemplate/FindTemplateService.cs:14)
- 每个算法拥有独立请求、参数、结果模型
- 不再使用统一算法总入口服务
推荐未来新增算法继续按相同方式组织,例如:
- `FindMark/IFindMarkService.cs`
- `FindMark/FindMarkService.cs`
- `FindMark/FindMarkRequest.cs`
- `FindMark/FindMarkResult.cs`
如果算法需要“已有图像直接处理”的场景,可按需再增加 `XXXImageRequest.cs`
## 4. 推荐调用顺序
推荐顺序如下:
1. 先通过 [`VisionParController`](MainShell/Models/VisionParController.cs) 准备相机与光源参数
2. 再通过 [`IImageCaptureService`](MainShell/Vision/ImageCapture/IImageCaptureService.cs) 执行采图,或由具体算法服务内部采图
3. 最后通过具体算法服务,例如 [`IFindTemplateService`](MainShell/Vision/FindTemplate/IFindTemplateService.cs:10),执行算法
## 5. 采图前提说明
### 5.1 连续流采图
当 [`CameraCaptureMode.Stream`](MainShell/Vision/ImageCapture/CameraCaptureMode.cs) 用于采图时,调用前应确保:
- 相机已打开
- 相机已处于 grabbing 状态
- 相机已被配置为适合连续流取图的工作模式
### 5.2 软触发采图
当 [`CameraCaptureMode.SoftTrigger`](MainShell/Vision/ImageCapture/CameraCaptureMode.cs) 用于采图时,调用前应确保:
- 相机已打开
- 相机已处于 grabbing 状态
- 相机已被配置为软触发模式
- 触发源已设置为软件触发
如果上述前提不满足,[`ImageCaptureService`](MainShell/Vision/ImageCapture/ImageCaptureService.cs) 不会代替调用方修改硬件状态,而是直接失败并记录日志。
## 6. 请求模型
模板匹配当前使用独立请求模型:
- [`FindTemplateRequest`](MainShell/Vision/FindTemplate/FindTemplateRequest.cs:8):用于“采图 + 算法”流程
- [`FindTemplateImageRequest`](MainShell/Vision/FindTemplate/FindTemplateImageRequest.cs:6):用于“已有图像 + 算法”流程
推荐新算法默认最小模型集为:
- `XXXRequest`
- `XXXResult`
只有在算法确实需要时,再增加:
- `XXXParameters`
- `XXXImageRequest`
## 7. 结果模型
当前结果模型已调整为四层:
- [`VisionProcessResult`](MainShell/Vision/Common/VisionProcessResult.cs:8):仅承载成功/失败/异常/消息
- [`VisionProcessResult<TData>`](MainShell/Vision/Common/VisionProcessResultOfT.cs:9):承载强类型算法结果数据
- [`ImageCaptureResult`](MainShell/Vision/ImageCapture/ImageCaptureResult.cs:25):承载采图动作结果、状态、消息和图像对象
- [`VisionMatchResult`](MainShell/Vision/Common/VisionMatchResult.cs:6):承载扩展匹配信息
模板匹配当前返回:
- [`VisionProcessResult<FindTemplateResult>`](MainShell/Vision/Common/VisionProcessResultOfT.cs:9)
- [`VisionProcessResult<FindTemplatesResult>`](MainShell/Vision/Common/VisionProcessResultOfT.cs:9)
[`FindTemplateResult`](MainShell/Vision/FindTemplate/FindTemplateResult.cs:6) 当前包含:
- `CenterX`
- `CenterY`
- `Score`
- `Match`
[`FindTemplatesResult`](MainShell/Vision/FindTemplate/FindTemplatesResult.cs:6) 当前包含:
- `Items`
## 8. 当前算法实现状态
当前状态如下:
- 采图服务已按新职责边界实现
- 模板匹配保持独立接口与独立服务实现
- 采图结果已区分成功、取消、设备状态错误、无帧和驱动异常
- 已不再使用统一视觉算法入口服务
- [`FindTemplateService`](MainShell/Vision/FindTemplate/FindTemplateService.cs:14) 当前仍为占位实现,尚未接入真实算法
- 已预留单个模板匹配与多个模板匹配两套接口
- 多个模板匹配当前已明确约定输出规则:保留底层原始顺序,不做得分筛选、不做去重、不做聚类合并
因此本模块当前适合作为:
- 视觉接入骨架
- 采图与参数联调骨架
- 按算法拆服务的长期结构基础
## 9. 取消与超时说明
[`ImageCaptureService`](MainShell/Vision/ImageCapture/ImageCaptureService.cs) 当前采图仍基于底层同步驱动接口。
这意味着:
- `CancellationToken` 主要控制外层任务流程
- 取消仅能在进入驱动前或驱动返回后生效
- 不一定能真正中断驱动内部阻塞调用
- 软触发底层超时仍受驱动实现限制
[`FindTemplateService`](MainShell/Vision/FindTemplate/FindTemplateService.cs:14) 当前会区分:
- 调用方主动取消
- 参数校验失败
- 算法未实现
- 采图阶段失败
## 10. 图像对象生命周期说明
- 通过 [`FindTemplateService.ProcessAsync()`](MainShell/Vision/FindTemplate/FindTemplateService.cs:22) 内部采集到的图像,由服务内部释放
- 通过 [`IFindTemplateService.ProcessImageAsync()`](MainShell/Vision/FindTemplate/IFindTemplateService.cs:22) 或 [`IFindTemplateService.ProcessMultipleImageAsync()`](MainShell/Vision/FindTemplate/IFindTemplateService.cs:36) 传入的已有图像,由调用方负责释放
- 调用方不应在算法执行期间提前释放正在使用的图像对象
## 11. 多模板匹配规则
当前多个模板匹配算法接口约定如下:
1. 输入一张图像和一组模板匹配参数
2. 调用底层模板匹配能力,获取原始匹配结果集合
3. 不按 `MinScore` 做二次筛选
4. 不做最佳值选优
5. 不做结果去重
6. 不做聚类合并
7. 保持底层算法返回顺序
8. 将原始匹配结果逐个映射为 [`FindTemplateResult`](MainShell/Vision/FindTemplate/FindTemplateResult.cs:6) 并输出到 [`FindTemplatesResult`](MainShell/Vision/FindTemplate/FindTemplatesResult.cs:6)
## 12. 新增算法模板建议
推荐新增一个普通算法时,默认最小文件集合为:
- `IXXXService.cs`
- `XXXService.cs`
- `XXXRequest.cs`
- `XXXResult.cs`
复杂算法再按需增加:
- `XXXParameters.cs`
- `XXXImageRequest.cs`
这样可以兼顾:
- 一算法一实现的清晰边界
- 文件数量不过度膨胀
- 后续维护和问题定位的可读性
## 13. 代码使用示例
### 13.1 示例一:由算法服务内部采图后执行单个模板匹配
这是推荐的业务调用方式。先通过 [`VisionParController`](MainShell/Models/VisionParController.cs) 准备相机状态,再调用 [`IFindTemplateService.ProcessAsync()`](MainShell/Vision/FindTemplate/IFindTemplateService.cs:14)。
```csharp
using MainShell.Common;
using MainShell.Vision;
using System.Threading;
using System.Threading.Tasks;
public class VisionUsageExample
{
private readonly IFindTemplateService _findTemplateService;
public VisionUsageExample(IFindTemplateService findTemplateService)
{
_findTemplateService = findTemplateService;
}
public async Task ExecuteAsync(CancellationToken cancellationToken)
{
FindTemplateRequest request = new FindTemplateRequest();
request.CameraSource = CameraType.UpCamera;
request.TimeoutMilliseconds = 3000;
request.CaptureOptions.TimeoutMilliseconds = 2000;
request.CaptureOptions.CaptureMode = CameraCaptureMode.Stream;
request.Parameters.UseRoi = true;
request.Parameters.RoiName = "DieCenterRoi";
request.Parameters.TemplatePath = "Template/DieCenter";
request.Parameters.MinScore = 0.8d;
VisionProcessResult<FindTemplateResult> result = await _findTemplateService.ProcessAsync(
request,
cancellationToken).ConfigureAwait(false);
if (!result.Succeeded)
{
string failureMessage = result.Message;
return;
}
FindTemplateResult data = result.Data;
double centerX = data.CenterX;
double centerY = data.CenterY;
double score = data.Score;
}
}
```
### 13.2 示例二:对已有图像执行多个模板匹配
这个方式适合调试、联调或者需要复用同一帧图像的场景。
```csharp
using MainShell.Common;
using MainShell.Models;
using MainShell.Vision;
using System.Threading;
using System.Threading.Tasks;
public class VisionImageUsageExample
{
private readonly IImageCaptureService _imageCaptureService;
private readonly IFindTemplateService _findTemplateService;
public VisionImageUsageExample(
IImageCaptureService imageCaptureService,
IFindTemplateService findTemplateService)
{
_imageCaptureService = imageCaptureService;
_findTemplateService = findTemplateService;
}
public async Task ExecuteAsync(CancellationToken cancellationToken)
{
CameraCaptureOptions captureOptions = new CameraCaptureOptions();
captureOptions.TimeoutMilliseconds = 2000;
captureOptions.CaptureMode = CameraCaptureMode.Stream;
ImageCaptureResult captureResult = await _imageCaptureService.CaptureAsync(
CameraType.UpCamera,
captureOptions,
cancellationToken).ConfigureAwait(false);
if (!captureResult.Succeeded)
{
string captureFailureMessage = captureResult.Message;
return;
}
MxImage image = captureResult.Image;
try
{
FindTemplateImageRequest request = new FindTemplateImageRequest();
request.TimeoutMilliseconds = 3000;
request.Parameters.UseRoi = false;
request.Parameters.TemplatePath = "Template/DieCenter";
request.Parameters.MinScore = 0.8d;
VisionProcessResult<FindTemplatesResult> result = await _findTemplateService.ProcessMultipleImageAsync(
image,
request,
cancellationToken).ConfigureAwait(false);
if (!result.Succeeded)
{
string failureMessage = result.Message;
return;
}
FindTemplatesResult data = result.Data;
int count = data.Items.Count;
}
finally
{
if (image != null)
{
image.Dispose();
}
}
}
}
```
### 13.3 示例三:如何判断采图失败原因
[`ImageCaptureResult`](MainShell/Vision/ImageCapture/ImageCaptureResult.cs:25) 适合在上层做更细的失败分流。
```csharp
using MainShell.Common;
using MainShell.Vision;
using System.Threading;
using System.Threading.Tasks;
public class CaptureResultExample
{
private readonly IImageCaptureService _imageCaptureService;
public CaptureResultExample(IImageCaptureService imageCaptureService)
{
_imageCaptureService = imageCaptureService;
}
public async Task ExecuteAsync(CancellationToken cancellationToken)
{
ImageCaptureResult captureResult = await _imageCaptureService.CaptureAsync(
CameraType.UpCamera,
2000,
CameraCaptureMode.Stream,
cancellationToken).ConfigureAwait(false);
if (captureResult.Succeeded)
{
return;
}
switch (captureResult.Status)
{
case ImageCaptureStatus.Cancelled:
break;
case ImageCaptureStatus.CameraNotFound:
case ImageCaptureStatus.CameraNotOpen:
case ImageCaptureStatus.CameraNotGrabbing:
case ImageCaptureStatus.NoFrame:
case ImageCaptureStatus.DriverError:
string message = captureResult.Message;
break;
default:
break;
}
}
}
```
### 13.4 示例四:新增一个新算法时的推荐骨架
`FindMark` 为例,推荐至少准备:
- `FindMark/IFindMarkService.cs`
- `FindMark/FindMarkService.cs`
- `FindMark/FindMarkRequest.cs`
- `FindMark/FindMarkResult.cs`
如果需要已有图像处理,再增加:
- `FindMark/FindMarkImageRequest.cs`
如果参数较复杂,再增加:
- `FindMark/FindMarkParameters.cs`
服务实现建议沿用 [`FindTemplateService`](MainShell/Vision/FindTemplate/FindTemplateService.cs:14) 的结构:
- `ProcessAsync()` 负责“采图 + 单个模板匹配”
- `ProcessImageAsync()` 负责“已有图像 + 单个模板匹配”
- `ProcessMultipleAsync()` 负责“采图 + 多个模板匹配”
- `ProcessMultipleImageAsync()` 负责“已有图像 + 多个模板匹配”
- `NormalizeRequest()` 负责标准化
- `ValidateRequest()` 负责参数校验
- `CloneParameters()` 负责避免共享可变输入对象
这样可以保证不同算法之间结构一致,便于维护和扩展。