Vision 模块使用文档
1. 文档范围
本文档说明当前 MainShell/Vision 模块在“一个算法一个文件夹”的结构下的职责划分和推荐使用方式,重点覆盖:
IImageCaptureService/ImageCaptureService:负责按当前已准备好的相机模式执行采图IFindTemplateService/FindTemplateService:负责模板匹配算法的采图与处理VisionParController:负责视觉前置硬件参数准备,包括相机参数、触发模式和抓流状态FindTemplateRequest/FindTemplateImageRequest:负责模板匹配请求建模VisionProcessResult/VisionProcessResult<TData>:负责承载通用处理状态与强类型算法结果ImageCaptureResult/ImageCaptureStatus:负责承载采图状态、消息与图像对象
当前目录划分如下:
Common/:共享结果模型与算法参数基类ImageCapture/:采图接口、实现与采图相关模型FindTemplate/:模板匹配算法接口、实现、请求、参数、结果FindMark/:Mark 识别参数与后续算法扩展入口FindDie/:Die 定位参数与后续算法扩展入口FindCenter/:中心识别草稿算法骨架
2. 当前模块职责边界
2.1 VisionParController
负责视觉前置硬件准备:
- 设置曝光和增益
- 设置触发模式
- 设置触发源
- 设置触发延时
- 启动或停止抓流
- 设置光源参数
2.2 ImageCaptureService
只负责执行采图动作:
- 不再自动切换触发模式
- 不再自动切换触发源
- 不再自动设置触发延时
- 不再自动启停抓流
- 同一相机的采图请求在服务内部按相机粒度串行执行
- 通过
ImageCaptureResult返回成功、取消、无帧或设备状态异常等结果
调用方必须在采图前通过 VisionParController 或其他上层硬件控制流程准备好相机状态。
2.3 FindTemplateService
负责:
- 模板匹配参数校验
- 模板匹配采图流程组织
- 单个模板匹配结果构建
- 多个模板匹配结果集合构建
- 返回
VisionProcessResult<FindTemplateResult>或VisionProcessResult<FindTemplatesResult>
当前模板匹配算法本体仍为占位实现,尚未接入真实视觉算法库。当前占位实现会明确返回失败,避免上层流程误判为识别成功。
3. 当前推荐结构
当前推荐使用“一个算法一个实现”的结构,即:
- 每个算法拥有独立接口,例如
IFindTemplateService - 每个算法拥有独立实现,例如
FindTemplateService - 每个算法拥有独立请求、参数、结果模型
- 不再使用统一算法总入口服务
推荐未来新增算法继续按相同方式组织,例如:
FindMark/IFindMarkService.csFindMark/FindMarkService.csFindMark/FindMarkRequest.csFindMark/FindMarkResult.cs
如果算法需要“已有图像直接处理”的场景,可按需再增加 XXXImageRequest.cs。
4. 推荐调用顺序
推荐顺序如下:
- 先通过
VisionParController准备相机与光源参数 - 再通过
IImageCaptureService执行采图,或由具体算法服务内部采图 - 最后通过具体算法服务,例如
IFindTemplateService,执行算法
5. 采图前提说明
5.1 连续流采图
当 CameraCaptureMode.Stream 用于采图时,调用前应确保:
- 相机已打开
- 相机已处于 grabbing 状态
- 相机已被配置为适合连续流取图的工作模式
5.2 软触发采图
当 CameraCaptureMode.SoftTrigger 用于采图时,调用前应确保:
- 相机已打开
- 相机已处于 grabbing 状态
- 相机已被配置为软触发模式
- 触发源已设置为软件触发
如果上述前提不满足,ImageCaptureService 不会代替调用方修改硬件状态,而是直接失败并记录日志。
6. 请求模型
模板匹配当前使用独立请求模型:
FindTemplateRequest:用于“采图 + 算法”流程FindTemplateImageRequest:用于“已有图像 + 算法”流程
推荐新算法默认最小模型集为:
XXXRequestXXXResult
只有在算法确实需要时,再增加:
XXXParametersXXXImageRequest
7. 结果模型
当前结果模型已调整为四层:
VisionProcessResult:仅承载成功/失败/异常/消息VisionProcessResult<TData>:承载强类型算法结果数据ImageCaptureResult:承载采图动作结果、状态、消息和图像对象VisionMatchResult:承载扩展匹配信息
模板匹配当前返回:
FindTemplateResult 当前包含:
CenterXCenterYScoreMatch
FindTemplatesResult 当前包含:
Items
8. 当前算法实现状态
当前状态如下:
- 采图服务已按新职责边界实现
- 模板匹配保持独立接口与独立服务实现
- 采图结果已区分成功、取消、设备状态错误、无帧和驱动异常
- 已不再使用统一视觉算法入口服务
FindTemplateService当前仍为占位实现,尚未接入真实算法- 已预留单个模板匹配与多个模板匹配两套接口
- 多个模板匹配当前已明确约定输出规则:保留底层原始顺序,不做得分筛选、不做去重、不做聚类合并
因此本模块当前适合作为:
- 视觉接入骨架
- 采图与参数联调骨架
- 按算法拆服务的长期结构基础
9. 取消与超时说明
ImageCaptureService 当前采图仍基于底层同步驱动接口。
这意味着:
CancellationToken主要控制外层任务流程- 取消仅能在进入驱动前或驱动返回后生效
- 不一定能真正中断驱动内部阻塞调用
- 软触发底层超时仍受驱动实现限制
FindTemplateService 当前会区分:
- 调用方主动取消
- 参数校验失败
- 算法未实现
- 采图阶段失败
10. 图像对象生命周期说明
- 通过
FindTemplateService.ProcessAsync()内部采集到的图像,由服务内部释放 - 通过
IFindTemplateService.ProcessImageAsync()或IFindTemplateService.ProcessMultipleImageAsync()传入的已有图像,由调用方负责释放 - 调用方不应在算法执行期间提前释放正在使用的图像对象
11. 多模板匹配规则
当前多个模板匹配算法接口约定如下:
- 输入一张图像和一组模板匹配参数
- 调用底层模板匹配能力,获取原始匹配结果集合
- 不按
MinScore做二次筛选 - 不做最佳值选优
- 不做结果去重
- 不做聚类合并
- 保持底层算法返回顺序
- 将原始匹配结果逐个映射为
FindTemplateResult并输出到FindTemplatesResult
12. 新增算法模板建议
推荐新增一个普通算法时,默认最小文件集合为:
IXXXService.csXXXService.csXXXRequest.csXXXResult.cs
复杂算法再按需增加:
XXXParameters.csXXXImageRequest.cs
这样可以兼顾:
- 一算法一实现的清晰边界
- 文件数量不过度膨胀
- 后续维护和问题定位的可读性
13. 代码使用示例
13.1 示例一:由算法服务内部采图后执行单个模板匹配
这是推荐的业务调用方式。先通过 VisionParController 准备相机状态,再调用 IFindTemplateService.ProcessAsync()。
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 示例二:对已有图像执行多个模板匹配
这个方式适合调试、联调或者需要复用同一帧图像的场景。
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 适合在上层做更细的失败分流。
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.csFindMark/FindMarkService.csFindMark/FindMarkRequest.csFindMark/FindMarkResult.cs
如果需要已有图像处理,再增加:
FindMark/FindMarkImageRequest.cs
如果参数较复杂,再增加:
FindMark/FindMarkParameters.cs
服务实现建议沿用 FindTemplateService 的结构:
ProcessAsync()负责“采图 + 单个模板匹配”ProcessImageAsync()负责“已有图像 + 单个模板匹配”ProcessMultipleAsync()负责“采图 + 多个模板匹配”ProcessMultipleImageAsync()负责“已有图像 + 多个模板匹配”NormalizeRequest()负责标准化ValidateRequest()负责参数校验CloneParameters()负责避免共享可变输入对象
这样可以保证不同算法之间结构一致,便于维护和扩展。