添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
This commit is contained in:
@@ -0,0 +1,669 @@
|
||||
using JM1Vision;
|
||||
using MainShell.Common;
|
||||
using MainShell.Log;
|
||||
using MainShell.Models;
|
||||
using MaxwellFramework.Core.Attributes;
|
||||
using SemiconductorVisionAlgorithm.SemiParams;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MainShell.Vision
|
||||
{
|
||||
/// <summary>
|
||||
/// Die 定位服务。
|
||||
/// </summary>
|
||||
public class FindDieService : IFindDieService
|
||||
{
|
||||
private readonly IImageCaptureService _imageCaptureService;
|
||||
|
||||
public FindDieService(IImageCaptureService imageCaptureService)
|
||||
{
|
||||
_imageCaptureService = imageCaptureService ?? throw new ArgumentNullException(nameof(imageCaptureService));
|
||||
}
|
||||
|
||||
public async Task<VisionProcessResult<FindDieResult>> ProcessAsync(
|
||||
FindDieRequest request,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
}
|
||||
|
||||
FindDieImageRequest imageRequest = CreateImageRequest(request);
|
||||
return await ExecuteWithCaptureAsync(
|
||||
request.CameraSource,
|
||||
request.CaptureOptions,
|
||||
imageRequest,
|
||||
ProcessImageAsync,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public Task<VisionProcessResult<FindDieResult>> ProcessImageAsync(
|
||||
MxImage image,
|
||||
FindDieImageRequest request,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (image == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(image));
|
||||
}
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
}
|
||||
|
||||
FindDieImageRequest normalizedRequest = NormalizeRequest(request);
|
||||
VisionProcessResult validationResult = ValidateRequest(normalizedRequest);
|
||||
if (validationResult != null)
|
||||
{
|
||||
return Task.FromResult(CreateFailureResult<FindDieResult>(validationResult));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
VisionProcessResult<FindDieResult> result = ExecuteSingleMatch(image, normalizedRequest);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
result.Message.LogSysError();
|
||||
}
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
string message = $"FindDieService: process image was cancelled. Timeout={normalizedRequest.TimeoutMilliseconds} ms.";
|
||||
message.LogInfo();
|
||||
return Task.FromResult(VisionProcessResult<FindDieResult>.Failure(
|
||||
VisionFailureCategory.Cancelled,
|
||||
VisionErrorCode.OperationCancelled,
|
||||
null,
|
||||
MessageKey.VisionOperationCancelled,
|
||||
message,
|
||||
ex));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string message = $"FindDieService: process image failed. {ex.Message}";
|
||||
message.LogSysError();
|
||||
return Task.FromResult(VisionProcessResult<FindDieResult>.Failure(
|
||||
VisionFailureCategory.Algorithm,
|
||||
VisionErrorCode.TemplateMatchFailed,
|
||||
VisionAlarmIds.TemplateMatchFailed,
|
||||
MessageKey.VisionTemplateMatchFailed,
|
||||
message,
|
||||
ex));
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<VisionProcessResult<FindDiesResult>> ProcessMultipleAsync(
|
||||
FindDieRequest request,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
}
|
||||
|
||||
FindDieImageRequest imageRequest = CreateImageRequest(request);
|
||||
return await ExecuteWithCaptureAsync(
|
||||
request.CameraSource,
|
||||
request.CaptureOptions,
|
||||
imageRequest,
|
||||
ProcessMultipleImageAsync,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public Task<VisionProcessResult<FindDiesResult>> ProcessMultipleImageAsync(
|
||||
MxImage image,
|
||||
FindDieImageRequest request,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (image == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(image));
|
||||
}
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
}
|
||||
|
||||
FindDieImageRequest normalizedRequest = NormalizeRequest(request);
|
||||
VisionProcessResult validationResult = ValidateRequest(normalizedRequest);
|
||||
if (validationResult != null)
|
||||
{
|
||||
return Task.FromResult(CreateFailureResult<FindDiesResult>(validationResult));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
VisionProcessResult<FindDiesResult> result = ExecuteMultipleMatch(image, normalizedRequest);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
result.Message.LogSysError();
|
||||
}
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
string message = $"FindDieService: multiple die process image was cancelled. Timeout={normalizedRequest.TimeoutMilliseconds} ms.";
|
||||
message.LogInfo();
|
||||
return Task.FromResult(VisionProcessResult<FindDiesResult>.Failure(
|
||||
VisionFailureCategory.Cancelled,
|
||||
VisionErrorCode.OperationCancelled,
|
||||
null,
|
||||
MessageKey.VisionOperationCancelled,
|
||||
message,
|
||||
ex));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string message = $"FindDieService: multiple die process image failed. {ex.Message}";
|
||||
message.LogSysError();
|
||||
return Task.FromResult(VisionProcessResult<FindDiesResult>.Failure(
|
||||
VisionFailureCategory.Algorithm,
|
||||
VisionErrorCode.TemplateMatchFailed,
|
||||
VisionAlarmIds.TemplateMatchFailed,
|
||||
MessageKey.VisionTemplateMatchFailed,
|
||||
message,
|
||||
ex));
|
||||
}
|
||||
}
|
||||
|
||||
private static FindDieImageRequest NormalizeRequest(FindDieImageRequest request)
|
||||
{
|
||||
FindDieImageRequest normalizedRequest = new FindDieImageRequest();
|
||||
normalizedRequest.TimeoutMilliseconds = request.TimeoutMilliseconds > 0 ? request.TimeoutMilliseconds : 3000;
|
||||
normalizedRequest.Parameters = CloneParameters(request.Parameters);
|
||||
return normalizedRequest;
|
||||
}
|
||||
|
||||
private static VisionProcessResult ValidateRequest(FindDieImageRequest request)
|
||||
{
|
||||
if (request.Parameters == null)
|
||||
{
|
||||
return VisionProcessResult.Failure(
|
||||
VisionFailureCategory.Validation,
|
||||
VisionErrorCode.RequestInvalid,
|
||||
VisionAlarmIds.RequestInvalid,
|
||||
MessageKey.VisionRequestInvalid,
|
||||
"FindDieService: parameters cannot be null.");
|
||||
}
|
||||
|
||||
if (request.TimeoutMilliseconds <= 0 || request.TimeoutMilliseconds > 60000)
|
||||
{
|
||||
return VisionProcessResult.Failure(
|
||||
VisionFailureCategory.Validation,
|
||||
VisionErrorCode.TimeoutInvalid,
|
||||
VisionAlarmIds.RequestInvalid,
|
||||
MessageKey.VisionTimeoutInvalid,
|
||||
$"FindDieService: TimeoutMilliseconds {request.TimeoutMilliseconds} is invalid. Expected range is [1, 60000].");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.Parameters.TemplatePath))
|
||||
{
|
||||
return VisionProcessResult.Failure(
|
||||
VisionFailureCategory.Validation,
|
||||
VisionErrorCode.TemplatePathEmpty,
|
||||
VisionAlarmIds.TemplatePathEmpty,
|
||||
MessageKey.VisionTemplatePathEmpty,
|
||||
"FindDieService: TemplatePath cannot be empty.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.Parameters.SerialNumber))
|
||||
{
|
||||
return VisionProcessResult.Failure(
|
||||
VisionFailureCategory.Validation,
|
||||
VisionErrorCode.RequestInvalid,
|
||||
VisionAlarmIds.RequestInvalid,
|
||||
MessageKey.VisionRequestInvalid,
|
||||
"FindDieService: SerialNumber cannot be empty.");
|
||||
}
|
||||
|
||||
if (request.Parameters.CurrentRuler == null)
|
||||
{
|
||||
return VisionProcessResult.Failure(
|
||||
VisionFailureCategory.Validation,
|
||||
VisionErrorCode.RequestInvalid,
|
||||
VisionAlarmIds.RequestInvalid,
|
||||
MessageKey.VisionRequestInvalid,
|
||||
"FindDieService: CurrentRuler cannot be null.");
|
||||
}
|
||||
|
||||
if (request.Parameters.DieWidth <= 0d || request.Parameters.DieHeight <= 0d)
|
||||
{
|
||||
return VisionProcessResult.Failure(
|
||||
VisionFailureCategory.Validation,
|
||||
VisionErrorCode.RequestInvalid,
|
||||
VisionAlarmIds.RequestInvalid,
|
||||
MessageKey.VisionRequestInvalid,
|
||||
$"FindDieService: DieWidth {request.Parameters.DieWidth} and DieHeight {request.Parameters.DieHeight} must be greater than 0.");
|
||||
}
|
||||
|
||||
if (request.Parameters.ScoreThreshold <= 0d || request.Parameters.ScoreThreshold > 1d)
|
||||
{
|
||||
return VisionProcessResult.Failure(
|
||||
VisionFailureCategory.Validation,
|
||||
VisionErrorCode.MinScoreInvalid,
|
||||
VisionAlarmIds.TemplateMinScoreInvalid,
|
||||
MessageKey.VisionTemplateMinScoreInvalid,
|
||||
$"FindDieService: ScoreThreshold {request.Parameters.ScoreThreshold} is invalid. Expected range is (0, 1].");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static FindDieParameters CloneParameters(FindDieParameters parameters)
|
||||
{
|
||||
if (parameters == null)
|
||||
{
|
||||
return new FindDieParameters();
|
||||
}
|
||||
|
||||
FindDieParameters clone = new FindDieParameters();
|
||||
clone.MinScore = parameters.MinScore;
|
||||
clone.TemplatePath = parameters.TemplatePath;
|
||||
clone.SerialNumber = parameters.SerialNumber;
|
||||
clone.CurrentRuler = parameters.CurrentRuler == null
|
||||
? null
|
||||
: new Point(parameters.CurrentRuler.X, parameters.CurrentRuler.Y);
|
||||
clone.OverlapX = parameters.OverlapX;
|
||||
clone.OverlapY = parameters.OverlapY;
|
||||
clone.DieWidth = parameters.DieWidth;
|
||||
clone.DieHeight = parameters.DieHeight;
|
||||
clone.ScoreThreshold = parameters.ScoreThreshold > 0d ? parameters.ScoreThreshold : parameters.MinScore;
|
||||
clone.AngleTolerance = parameters.AngleTolerance;
|
||||
return clone;
|
||||
}
|
||||
|
||||
private static FindDieImageRequest CreateImageRequest(FindDieRequest request)
|
||||
{
|
||||
FindDieImageRequest imageRequest = new FindDieImageRequest();
|
||||
imageRequest.TimeoutMilliseconds = request.TimeoutMilliseconds;
|
||||
imageRequest.Parameters = CloneParameters(request.Parameters);
|
||||
return imageRequest;
|
||||
}
|
||||
|
||||
private static VisionProcessResult<FindDieResult> ExecuteSingleMatch(MxImage image, FindDieImageRequest request)
|
||||
{
|
||||
VisionProcessResult<FindDiesResult> multipleResult = ExecuteMultipleMatch(image, request);
|
||||
if (!multipleResult.Succeeded)
|
||||
{
|
||||
return CreateFailureResult<FindDieResult>(multipleResult);
|
||||
}
|
||||
|
||||
FindDieResult result = SelectPrimaryResult(multipleResult.Data);
|
||||
if (result == null)
|
||||
{
|
||||
return VisionProcessResult<FindDieResult>.Failure(
|
||||
VisionFailureCategory.Algorithm,
|
||||
VisionErrorCode.TemplateResultInvalid,
|
||||
VisionAlarmIds.TemplateResultInvalid,
|
||||
MessageKey.VisionTemplateMatchFailed,
|
||||
$"FindDieService: no valid die result was found. TemplatePath={request.Parameters.TemplatePath}.");
|
||||
}
|
||||
|
||||
return VisionProcessResult<FindDieResult>.Success(result);
|
||||
}
|
||||
|
||||
private static VisionProcessResult<FindDiesResult> ExecuteMultipleMatch(MxImage image, FindDieImageRequest request)
|
||||
{
|
||||
Camera camera = image.Image;
|
||||
if (camera == null)
|
||||
{
|
||||
return VisionProcessResult<FindDiesResult>.Failure(
|
||||
VisionFailureCategory.Algorithm,
|
||||
VisionErrorCode.ImageNull,
|
||||
VisionAlarmIds.ImageNull,
|
||||
MessageKey.VisionImageIsNull,
|
||||
"FindDieService: input image does not contain a valid camera object.");
|
||||
}
|
||||
|
||||
double[] uniqueRows = null;
|
||||
double[] uniqueCols = null;
|
||||
double[] uniqueAngles = null;
|
||||
double[] overlapRows = null;
|
||||
double[] overlapCols = null;
|
||||
double[] overlapAngles = null;
|
||||
double[] pixelRows = null;
|
||||
double[] pixelCols = null;
|
||||
double[] pixelAngles = null;
|
||||
|
||||
bool succeeded = JM1Manager.Instance.get_target_pos_nodisp(
|
||||
camera,
|
||||
request.Parameters.TemplatePath,
|
||||
request.Parameters.SerialNumber,
|
||||
request.Parameters.CurrentRuler,
|
||||
request.Parameters.OverlapX,
|
||||
request.Parameters.OverlapY,
|
||||
request.Parameters.DieWidth,
|
||||
request.Parameters.DieHeight,
|
||||
request.Parameters.ScoreThreshold,
|
||||
out uniqueRows,
|
||||
out uniqueCols,
|
||||
out uniqueAngles,
|
||||
out overlapRows,
|
||||
out overlapCols,
|
||||
out overlapAngles,
|
||||
out pixelRows,
|
||||
out pixelCols,
|
||||
out pixelAngles);
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
return VisionProcessResult<FindDiesResult>.Failure(
|
||||
VisionFailureCategory.Algorithm,
|
||||
VisionErrorCode.TemplateMatchFailed,
|
||||
VisionAlarmIds.TemplateMatchFailed,
|
||||
MessageKey.VisionTemplateMatchFailed,
|
||||
$"FindDieService: die match failed. TemplatePath={request.Parameters.TemplatePath}.");
|
||||
}
|
||||
|
||||
if (!HasConsistentResult(uniqueRows, uniqueCols, uniqueAngles) ||
|
||||
!HasConsistentResult(overlapRows, overlapCols, overlapAngles) ||
|
||||
!HasConsistentResult(pixelRows, pixelCols, pixelAngles))
|
||||
{
|
||||
return VisionProcessResult<FindDiesResult>.Failure(
|
||||
VisionFailureCategory.Algorithm,
|
||||
VisionErrorCode.TemplateResultInvalid,
|
||||
VisionAlarmIds.TemplateResultInvalid,
|
||||
MessageKey.VisionTemplateMatchFailed,
|
||||
$"FindDieService: die match returned inconsistent result data. TemplatePath={request.Parameters.TemplatePath}.");
|
||||
}
|
||||
|
||||
if (uniqueRows.Length + overlapRows.Length == 0)
|
||||
{
|
||||
return VisionProcessResult<FindDiesResult>.Failure(
|
||||
VisionFailureCategory.Algorithm,
|
||||
VisionErrorCode.TemplateMatchFailed,
|
||||
VisionAlarmIds.TemplateMatchFailed,
|
||||
MessageKey.VisionTemplateMatchFailed,
|
||||
$"FindDieService: die match returned no results. TemplatePath={request.Parameters.TemplatePath}.");
|
||||
}
|
||||
|
||||
FindDiesResult result = CreateMultipleResult(uniqueRows, uniqueCols, uniqueAngles, overlapRows, overlapCols, overlapAngles, pixelRows, pixelCols, pixelAngles);
|
||||
ApplyAngleTolerance(result, request.Parameters.AngleTolerance);
|
||||
if (result.Items.Count == 0)
|
||||
{
|
||||
return VisionProcessResult<FindDiesResult>.Failure(
|
||||
VisionFailureCategory.Algorithm,
|
||||
VisionErrorCode.TemplateResultInvalid,
|
||||
VisionAlarmIds.TemplateResultInvalid,
|
||||
MessageKey.VisionTemplateMatchFailed,
|
||||
$"FindDieService: die results were empty after angle filtering. TemplatePath={request.Parameters.TemplatePath}.");
|
||||
}
|
||||
|
||||
return VisionProcessResult<FindDiesResult>.Success(result);
|
||||
}
|
||||
|
||||
private static FindDiesResult CreateMultipleResult(
|
||||
double[] uniqueRows,
|
||||
double[] uniqueCols,
|
||||
double[] uniqueAngles,
|
||||
double[] overlapRows,
|
||||
double[] overlapCols,
|
||||
double[] overlapAngles,
|
||||
double[] pixelRows,
|
||||
double[] pixelCols,
|
||||
double[] pixelAngles)
|
||||
{
|
||||
FindDiesResult result = new FindDiesResult();
|
||||
AppendDieResults(result.Items, uniqueRows, uniqueCols, uniqueAngles, false);
|
||||
AppendDieResults(result.Items, overlapRows, overlapCols, overlapAngles, true);
|
||||
AppendPixelResults(result.PixelItems, pixelRows, pixelCols, pixelAngles);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void AppendDieResults(
|
||||
IList<FindDieResult> destination,
|
||||
double[] rows,
|
||||
double[] cols,
|
||||
double[] angles,
|
||||
bool isOverlap)
|
||||
{
|
||||
if (destination == null || rows == null || cols == null || angles == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rows.Length; i++)
|
||||
{
|
||||
FindDieResult item = new FindDieResult();
|
||||
item.CenterX = cols[i];
|
||||
item.CenterY = rows[i];
|
||||
item.Angle = angles[i];
|
||||
item.PixelX = double.NaN;
|
||||
item.PixelY = double.NaN;
|
||||
item.IsOverlap = isOverlap;
|
||||
item.Match = CreateMatchResult(angles[i], isOverlap);
|
||||
destination.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
private static void AppendPixelResults(
|
||||
IList<FindDiePixelResult> destination,
|
||||
double[] rows,
|
||||
double[] cols,
|
||||
double[] angles)
|
||||
{
|
||||
if (destination == null || rows == null || cols == null || angles == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rows.Length; i++)
|
||||
{
|
||||
FindDiePixelResult item = new FindDiePixelResult();
|
||||
item.PixelX = cols[i];
|
||||
item.PixelY = rows[i];
|
||||
item.Angle = angles[i];
|
||||
destination.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
private static VisionMatchResult CreateMatchResult(double angle, bool isOverlap)
|
||||
{
|
||||
VisionMatchResult match = new VisionMatchResult();
|
||||
match.OffsetX = 0d;
|
||||
match.OffsetY = 0d;
|
||||
match.Angle = angle;
|
||||
match.Score = 0d;
|
||||
match.Tag = isOverlap ? "Overlap" : "Unique";
|
||||
return match;
|
||||
}
|
||||
|
||||
private static void ApplyAngleTolerance(FindDiesResult result, double? angleTolerance)
|
||||
{
|
||||
if (result == null || !angleTolerance.HasValue || angleTolerance.Value <= 0d)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<double> itemAngles = new List<double>();
|
||||
foreach (FindDieResult item in result.Items)
|
||||
{
|
||||
itemAngles.Add(item.Angle * 180.0d / Math.PI);
|
||||
}
|
||||
|
||||
if (itemAngles.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double averageAngle = itemAngles.Average();
|
||||
List<FindDieResult> filteredItems = new List<FindDieResult>();
|
||||
foreach (FindDieResult item in result.Items)
|
||||
{
|
||||
double angleDegree = item.Angle * 180.0d / Math.PI;
|
||||
if (Math.Abs(angleDegree - averageAngle) <= angleTolerance.Value)
|
||||
{
|
||||
filteredItems.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
List<FindDiePixelResult> filteredPixelItems = new List<FindDiePixelResult>();
|
||||
foreach (FindDiePixelResult item in result.PixelItems)
|
||||
{
|
||||
double angleDegree = item.Angle * 180.0d / Math.PI;
|
||||
if (Math.Abs(angleDegree - averageAngle) <= angleTolerance.Value)
|
||||
{
|
||||
filteredPixelItems.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
result.Items.Clear();
|
||||
foreach (FindDieResult item in filteredItems)
|
||||
{
|
||||
result.Items.Add(item);
|
||||
}
|
||||
|
||||
result.PixelItems.Clear();
|
||||
foreach (FindDiePixelResult item in filteredPixelItems)
|
||||
{
|
||||
result.PixelItems.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
private static FindDieResult SelectPrimaryResult(FindDiesResult result)
|
||||
{
|
||||
if (result == null || result.Items == null || result.Items.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (FindDieResult item in result.Items)
|
||||
{
|
||||
if (!item.IsOverlap)
|
||||
{
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return result.Items[0];
|
||||
}
|
||||
|
||||
private static bool HasConsistentResult(double[] rows, double[] cols, double[] angles)
|
||||
{
|
||||
if (rows == null || cols == null || angles == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rows.Length != cols.Length || rows.Length != angles.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rows.Length; i++)
|
||||
{
|
||||
if (double.IsNaN(rows[i]) || double.IsInfinity(rows[i]) ||
|
||||
double.IsNaN(cols[i]) || double.IsInfinity(cols[i]) ||
|
||||
double.IsNaN(angles[i]) || double.IsInfinity(angles[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<VisionProcessResult<TResult>> ExecuteWithCaptureAsync<TResult>(
|
||||
CameraType cameraSource,
|
||||
CameraCaptureOptions captureOptions,
|
||||
FindDieImageRequest imageRequest,
|
||||
Func<MxImage, FindDieImageRequest, CancellationToken, Task<VisionProcessResult<TResult>>> imageProcessor,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
ImageCaptureResult captureResult = null;
|
||||
MxImage image = null;
|
||||
|
||||
try
|
||||
{
|
||||
captureResult = await _imageCaptureService.CaptureAsync(
|
||||
cameraSource,
|
||||
captureOptions,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (captureResult == null)
|
||||
{
|
||||
return VisionProcessResult<TResult>.Failure(
|
||||
VisionFailureCategory.Capture,
|
||||
VisionErrorCode.NoFrame,
|
||||
VisionAlarmIds.NoFrame,
|
||||
MessageKey.VisionNoFrameReturned,
|
||||
$"FindDieService: image capture returned null result for camera '{cameraSource}'.");
|
||||
}
|
||||
|
||||
if (!captureResult.Succeeded)
|
||||
{
|
||||
return CreateFailureResult<TResult>(VisionResultMapper.CreateCaptureFailure(captureResult));
|
||||
}
|
||||
|
||||
image = captureResult.Image;
|
||||
if (image == null)
|
||||
{
|
||||
string message = $"FindDieService: image capture succeeded but returned null image for camera '{cameraSource}'.";
|
||||
message.LogSysError();
|
||||
return VisionProcessResult<TResult>.Failure(
|
||||
VisionFailureCategory.Capture,
|
||||
VisionErrorCode.ImageNull,
|
||||
VisionAlarmIds.ImageNull,
|
||||
MessageKey.VisionImageIsNull,
|
||||
message);
|
||||
}
|
||||
|
||||
return await imageProcessor(image, imageRequest, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
string message = $"FindDieService: capture orchestration was cancelled for camera '{cameraSource}'.";
|
||||
message.LogInfo();
|
||||
return VisionProcessResult<TResult>.Failure(
|
||||
VisionFailureCategory.Cancelled,
|
||||
VisionErrorCode.OperationCancelled,
|
||||
null,
|
||||
MessageKey.VisionOperationCancelled,
|
||||
message,
|
||||
ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string message = $"FindDieService: capture orchestration failed for camera '{cameraSource}'. {ex.Message}";
|
||||
message.LogSysError();
|
||||
return VisionProcessResult<TResult>.Failure(
|
||||
VisionFailureCategory.Algorithm,
|
||||
VisionErrorCode.TemplateMatchFailed,
|
||||
VisionAlarmIds.TemplateMatchFailed,
|
||||
MessageKey.VisionTemplateMatchFailed,
|
||||
message,
|
||||
ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (image != null)
|
||||
{
|
||||
image.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static VisionProcessResult<TData> CreateFailureResult<TData>(VisionProcessResult result)
|
||||
{
|
||||
return VisionProcessResult<TData>.Failure(
|
||||
result.FailureCategory,
|
||||
result.ErrorCode,
|
||||
result.AlarmId,
|
||||
result.UserMessageKey,
|
||||
result.Message,
|
||||
result.Exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user