using MainShell.Log; using MainShell.Models; using MaxwellFramework.Core.Attributes; using System; using System.Threading; using System.Threading.Tasks; namespace MainShell.Vision { /// /// 中心识别服务实现。 /// [Singleton] public class FindCenterService : IFindCenterService { private readonly IImageCaptureService _imageCaptureService; public FindCenterService(IImageCaptureService imageCaptureService) { _imageCaptureService = imageCaptureService ?? throw new ArgumentNullException(nameof(imageCaptureService)); } public async Task> ProcessAsync( FindCenterRequest request, CancellationToken cancellationToken = default(CancellationToken)) { if (request == null) { throw new ArgumentNullException(nameof(request)); } ImageCaptureResult captureResult = null; MxImage image = null; try { captureResult = await _imageCaptureService.CaptureAsync( request.CameraSource, request.CaptureOptions, cancellationToken).ConfigureAwait(false); if (captureResult == null) { string message = string.Format( "FindCenterService: image capture returned null result for camera '{0}'.", request.CameraSource); message.LogSysError(); return VisionProcessResult.Failure(message); } if (!captureResult.Succeeded) { return VisionProcessResult.Failure(captureResult.Message, captureResult.Exception); } image = captureResult.Image; if (image == null) { string message = string.Format( "FindCenterService: image capture succeeded but returned null image for camera '{0}'.", request.CameraSource); message.LogSysError(); return VisionProcessResult.Failure(message); } FindCenterImageRequest imageRequest = new FindCenterImageRequest(); imageRequest.TimeoutMilliseconds = request.TimeoutMilliseconds; imageRequest.Parameters = request.Parameters; return await ProcessImageAsync(image, imageRequest, cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException ex) { string message = "FindCenterService: process was cancelled."; message.LogInfo(); return VisionProcessResult.Failure(message, ex); } catch (Exception ex) { string message = string.Format("FindCenterService: process failed. {0}", ex.Message); message.LogSysError(); return VisionProcessResult.Failure(message, ex); } finally { if (image != null) { image.Dispose(); } } } public Task> ProcessImageAsync( MxImage image, FindCenterImageRequest request, CancellationToken cancellationToken = default(CancellationToken)) { if (image == null) { throw new ArgumentNullException(nameof(image)); } if (request == null) { throw new ArgumentNullException(nameof(request)); } FindCenterImageRequest normalizedRequest = NormalizeRequest(request); VisionProcessResult validationResult = ValidateRequest(normalizedRequest); if (validationResult != null) { return Task.FromResult(VisionProcessResult.Failure(validationResult.Message, validationResult.Exception)); } try { cancellationToken.ThrowIfCancellationRequested(); string message = string.Format( "FindCenterService: algorithm is not implemented. RoiName={0}, UseRoi={1}, MinScore={2}.", normalizedRequest.Parameters != null ? normalizedRequest.Parameters.RoiName : null, normalizedRequest.Parameters != null && normalizedRequest.Parameters.UseRoi, normalizedRequest.Parameters != null ? normalizedRequest.Parameters.MinScore : 0.0); message.LogSysError(); return Task.FromResult(VisionProcessResult.Failure(message)); } catch (OperationCanceledException ex) { string message = string.Format( "FindCenterService: process image was cancelled. Timeout={0} ms.", normalizedRequest.TimeoutMilliseconds); message.LogInfo(); return Task.FromResult(VisionProcessResult.Failure(message, ex)); } catch (Exception ex) { string message = string.Format("FindCenterService: process image failed. {0}", ex.Message); message.LogSysError(); return Task.FromResult(VisionProcessResult.Failure(message, ex)); } } private static FindCenterImageRequest NormalizeRequest(FindCenterImageRequest request) { FindCenterImageRequest normalizedRequest = new FindCenterImageRequest(); normalizedRequest.TimeoutMilliseconds = request.TimeoutMilliseconds > 0 ? request.TimeoutMilliseconds : 3000; normalizedRequest.Parameters = CloneParameters(request.Parameters); return normalizedRequest; } private static VisionProcessResult ValidateRequest(FindCenterImageRequest request) { if (request.Parameters == null) { return VisionProcessResult.Failure("FindCenterService: parameters cannot be null."); } if (request.TimeoutMilliseconds <= 0 || request.TimeoutMilliseconds > 60000) { return VisionProcessResult.Failure( string.Format("FindCenterService: TimeoutMilliseconds {0} is invalid. Expected range is [1, 60000].", request.TimeoutMilliseconds)); } if (request.Parameters.MinScore <= 0d || request.Parameters.MinScore > 1d) { return VisionProcessResult.Failure( string.Format("FindCenterService: MinScore {0} is invalid. Expected range is (0, 1].", request.Parameters.MinScore)); } if (request.Parameters.UseRoi && string.IsNullOrWhiteSpace(request.Parameters.RoiName)) { return VisionProcessResult.Failure("FindCenterService: RoiName cannot be empty when UseRoi is true."); } return null; } private static FindCenterParameters CloneParameters(FindCenterParameters parameters) { if (parameters == null) { return new FindCenterParameters(); } FindCenterParameters clone = new FindCenterParameters(); clone.UseRoi = parameters.UseRoi; clone.RoiName = parameters.RoiName; clone.MinScore = parameters.MinScore; return clone; } } }