Files
Shi.Ji e31d3560bb 添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
2026-05-18 11:43:09 +08:00

431 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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()` 负责避免共享可变输入对象
这样可以保证不同算法之间结构一致,便于维护和扩展。