using MainShell.Common; using MainShell.Log; using MainShell.Vision; using System; using System.Threading; using System.Threading.Tasks; using System.Windows; namespace MainShell.Motion { /// /// 中心识别实现 /// 通过模板匹配服务识别目标中心 /// 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)); } /// /// 识别图像中心坐标 /// public Task<(double CenterX, double CenterY)?> RecognizeCenterAsync( CameraType camera, int timeoutMilliseconds, CancellationToken cancellationToken) { return RecognizeCenterAsync( camera, timeoutMilliseconds, new CenterRecognitionParameters(), cancellationToken); } /// /// 识别图像中心坐标 /// 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; } } }