174 lines
7.5 KiB
C#
174 lines
7.5 KiB
C#
|
|
using MainShell.Common;
|
|||
|
|
using MainShell.Log;
|
|||
|
|
using MainShell.Vision;
|
|||
|
|
using System;
|
|||
|
|
using System.Threading;
|
|||
|
|
using System.Threading.Tasks;
|
|||
|
|
using System.Windows;
|
|||
|
|
|
|||
|
|
namespace MainShell.Motion
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 中心识别实现
|
|||
|
|
/// 通过模板匹配服务识别目标中心
|
|||
|
|
/// </summary>
|
|||
|
|
public class CenterRecognizer : ICenterRecognizer
|
|||
|
|
{
|
|||
|
|
private readonly IFindTemplateService _findTemplateService;
|
|||
|
|
private readonly IFindEdgeCircleService _findEdgeCircleService;
|
|||
|
|
|
|||
|
|
public CenterRecognizer(
|
|||
|
|
IFindTemplateService findTemplateService,
|
|||
|
|
IFindEdgeCircleService findEdgeCircleService)
|
|||
|
|
{
|
|||
|
|
_findTemplateService = findTemplateService ?? throw new ArgumentNullException(nameof(findTemplateService));
|
|||
|
|
_findEdgeCircleService = findEdgeCircleService ?? throw new ArgumentNullException(nameof(findEdgeCircleService));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 识别图像中心坐标
|
|||
|
|
/// </summary>
|
|||
|
|
public Task<(double CenterX, double CenterY)?> RecognizeCenterAsync(
|
|||
|
|
CameraType camera,
|
|||
|
|
int timeoutMilliseconds,
|
|||
|
|
CancellationToken cancellationToken)
|
|||
|
|
{
|
|||
|
|
return RecognizeCenterAsync(
|
|||
|
|
camera,
|
|||
|
|
timeoutMilliseconds,
|
|||
|
|
new CenterRecognitionParameters(),
|
|||
|
|
cancellationToken);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 识别图像中心坐标
|
|||
|
|
/// </summary>
|
|||
|
|
public async Task<(double CenterX, double CenterY)?> RecognizeCenterAsync(
|
|||
|
|
CameraType camera,
|
|||
|
|
int timeoutMilliseconds,
|
|||
|
|
CenterRecognitionParameters parameters,
|
|||
|
|
CancellationToken cancellationToken)
|
|||
|
|
{
|
|||
|
|
if (parameters == null)
|
|||
|
|
{
|
|||
|
|
throw new ArgumentNullException(nameof(parameters));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
using (CancellationTokenSource cts = new CancellationTokenSource(timeoutMilliseconds))
|
|||
|
|
using (CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cts.Token))
|
|||
|
|
{
|
|||
|
|
string.Format(
|
|||
|
|
"CenterRecognizer: Starting template recognition from camera '{0}' (timeout={1}ms, template='{2}', minScore={3}).",
|
|||
|
|
camera,
|
|||
|
|
timeoutMilliseconds,
|
|||
|
|
parameters.TemplatePath,
|
|||
|
|
parameters.MinScore).LogInfo();
|
|||
|
|
VisionProcessResult result = null;
|
|||
|
|
double centerX = 0;
|
|||
|
|
double centerY = 0;
|
|||
|
|
switch (parameters.Type)
|
|||
|
|
{
|
|||
|
|
case CenterRecognitionType.Template:
|
|||
|
|
{
|
|||
|
|
FindTemplateRequest request = BuildFindTemplateRequest(camera, timeoutMilliseconds,parameters);
|
|||
|
|
var templateResult = await _findTemplateService.ProcessAsync(request,linkedCts.Token).ConfigureAwait(false);
|
|||
|
|
if (templateResult.Succeeded && templateResult.Data != null)
|
|||
|
|
{
|
|||
|
|
centerX = templateResult.Data.CenterX;
|
|||
|
|
centerY = templateResult.Data.CenterY;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
string.Format(
|
|||
|
|
"CenterRecognizer: Template recognition failed for camera '{0}': {1}",
|
|||
|
|
camera,
|
|||
|
|
templateResult.Message).LogSysError();
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
case CenterRecognitionType.EdgeCircle:
|
|||
|
|
{
|
|||
|
|
FindEdgeCircleRequest request = BuildFindEdgeCircleRequest(camera,timeoutMilliseconds, parameters);
|
|||
|
|
var circleResult = await _findEdgeCircleService.ProcessAsync(request,linkedCts.Token).ConfigureAwait(false);
|
|||
|
|
if (circleResult.Succeeded && circleResult.Data != null)
|
|||
|
|
{
|
|||
|
|
centerX = circleResult.Data.CenterX;
|
|||
|
|
centerY = circleResult.Data.CenterY;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
string.Format(
|
|||
|
|
"CenterRecognizer: Edge circle recognition failed for camera '{0}': {1}",
|
|||
|
|
camera,
|
|||
|
|
circleResult.Message).LogSysError();
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
string.Format(
|
|||
|
|
"CenterRecognizer: Recognition completed: X={0:F4}, Y={1:F4}",
|
|||
|
|
centerX,
|
|||
|
|
centerY).LogInfo();
|
|||
|
|
|
|||
|
|
return (centerX, centerY);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (OperationCanceledException)
|
|||
|
|
{
|
|||
|
|
string.Format(
|
|||
|
|
"CenterRecognizer: Template recognition timed out for camera '{0}'.",
|
|||
|
|
camera).LogSysError();
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
string.Format(
|
|||
|
|
"CenterRecognizer: Template recognition failed for camera '{0}': {1}",
|
|||
|
|
camera,
|
|||
|
|
ex.Message).LogSysError();
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static FindTemplateRequest BuildFindTemplateRequest(
|
|||
|
|
CameraType camera,
|
|||
|
|
int timeoutMilliseconds,
|
|||
|
|
CenterRecognitionParameters parameters)
|
|||
|
|
{
|
|||
|
|
FindTemplateParameters findTemplateParameters = new FindTemplateParameters();
|
|||
|
|
findTemplateParameters.MinScore = parameters.MinScore;
|
|||
|
|
findTemplateParameters.TemplatePath = parameters.TemplatePath;
|
|||
|
|
findTemplateParameters.UseRoi = parameters.UseRoi;
|
|||
|
|
findTemplateParameters.RoiName = parameters.RoiName;
|
|||
|
|
|
|||
|
|
FindTemplateRequest request = new FindTemplateRequest();
|
|||
|
|
request.CameraSource = camera;
|
|||
|
|
request.CaptureOptions = CameraCaptureOptions.CreateStream(timeoutMilliseconds);
|
|||
|
|
request.Parameters = findTemplateParameters;
|
|||
|
|
request.TimeoutMilliseconds = timeoutMilliseconds;
|
|||
|
|
return request;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static FindEdgeCircleRequest BuildFindEdgeCircleRequest(
|
|||
|
|
CameraType camera,
|
|||
|
|
int timeoutMilliseconds,
|
|||
|
|
CenterRecognitionParameters parameters)
|
|||
|
|
{
|
|||
|
|
FindEdgeCircleParameters findEdgeCircleParameters = new FindEdgeCircleParameters();
|
|||
|
|
findEdgeCircleParameters.RoiRect = parameters.rectangle;
|
|||
|
|
|
|||
|
|
FindEdgeCircleRequest request = new FindEdgeCircleRequest();
|
|||
|
|
request.CameraSource = camera;
|
|||
|
|
request.CaptureOptions = CameraCaptureOptions.CreateStream(timeoutMilliseconds);
|
|||
|
|
request.Parameters = findEdgeCircleParameters;
|
|||
|
|
request.TimeoutMilliseconds = timeoutMilliseconds;
|
|||
|
|
return request;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|