添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
|
||||
namespace MainShell.Vision
|
||||
{
|
||||
/// <summary>
|
||||
/// 抓圆图像请求
|
||||
/// </summary>
|
||||
public class FindEdgeCircleImageRequest
|
||||
{
|
||||
public FindEdgeCircleImageRequest()
|
||||
{
|
||||
TimeoutMilliseconds = 3000;
|
||||
Parameters = new FindEdgeCircleParameters();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 算法超时时间(毫秒)
|
||||
/// </summary>
|
||||
public int TimeoutMilliseconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 抓圆参数
|
||||
/// </summary>
|
||||
public FindEdgeCircleParameters Parameters { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using SemiconductorVisionAlgorithm.SemiParams;
|
||||
|
||||
namespace MainShell.Vision
|
||||
{
|
||||
/// <summary>
|
||||
/// 抓圆参数
|
||||
/// </summary>
|
||||
public class FindEdgeCircleParameters : VisionAlgorithmParameters
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否启用 ROI
|
||||
/// </summary>
|
||||
public bool UseRoi { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ROI 名称或标识
|
||||
/// </summary>
|
||||
public string RoiName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 算法文件目录
|
||||
/// </summary>
|
||||
public string FileDirectory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 相机ID
|
||||
/// </summary>
|
||||
public string CameraId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ROI 矩形区域(可选)
|
||||
/// </summary>
|
||||
public Rectangle1 RoiRect { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using MainShell.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MainShell.Vision
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认抓圆请求。
|
||||
/// </summary>
|
||||
public class FindEdgeCircleRequest
|
||||
{
|
||||
private CameraCaptureOptions _captureOptions;
|
||||
|
||||
public FindEdgeCircleRequest()
|
||||
{
|
||||
_captureOptions = new CameraCaptureOptions();
|
||||
TimeoutMilliseconds = 3000;
|
||||
Parameters = new FindEdgeCircleParameters();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 相机来源。
|
||||
/// </summary>
|
||||
public CameraType CameraSource { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 采图选项。
|
||||
/// </summary>
|
||||
public CameraCaptureOptions CaptureOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
return _captureOptions;
|
||||
}
|
||||
set
|
||||
{
|
||||
_captureOptions = value ?? new CameraCaptureOptions();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 算法超时时间(毫秒)。
|
||||
/// </summary>
|
||||
public int TimeoutMilliseconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 抓圆参数。
|
||||
/// </summary>
|
||||
public FindEdgeCircleParameters Parameters { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
|
||||
namespace MainShell.Vision
|
||||
{
|
||||
/// <summary>
|
||||
/// 抓圆结果
|
||||
/// </summary>
|
||||
public class FindEdgeCircleResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 圆心 X 坐标
|
||||
/// </summary>
|
||||
public double CenterX { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 圆心 Y 坐标
|
||||
/// </summary>
|
||||
public double CenterY { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 圆半径
|
||||
/// </summary>
|
||||
public double Radius { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 置信度分数
|
||||
/// </summary>
|
||||
public double Score { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
using MainShell.Common;
|
||||
using MainShell.Log;
|
||||
using MainShell.Models;
|
||||
using MainShell.Vision.Common;
|
||||
using MaxwellFramework.Core.Attributes;
|
||||
using SemiconductorVisionAlgorithm.SemiCalib;
|
||||
using SemiconductorVisionAlgorithm.SemiParams;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MainShell.Vision
|
||||
{
|
||||
/// <summary>
|
||||
/// 抓圆服务实现
|
||||
/// </summary>
|
||||
[Singleton]
|
||||
public class FindEdgeCircleService : IFindEdgeCircleService
|
||||
{
|
||||
private readonly IImageCaptureService _imageCaptureService;
|
||||
|
||||
public FindEdgeCircleService(IImageCaptureService imageCaptureService)
|
||||
{
|
||||
_imageCaptureService = imageCaptureService ?? throw new ArgumentNullException(nameof(imageCaptureService));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 采集图像并执行抓圆
|
||||
/// </summary>
|
||||
public async Task<VisionProcessResult<FindEdgeCircleResult>> ProcessAsync(
|
||||
FindEdgeCircleRequest request,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
}
|
||||
|
||||
FindEdgeCircleImageRequest imageRequest = CreateImageRequest(request);
|
||||
return await ExecuteWithCaptureAsync(
|
||||
request.CameraSource,
|
||||
request.CaptureOptions,
|
||||
imageRequest,
|
||||
ProcessImageAsync,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基于已有图像直接执行抓圆
|
||||
/// </summary>
|
||||
public Task<VisionProcessResult<FindEdgeCircleResult>> ProcessImageAsync(
|
||||
MxImage image,
|
||||
FindEdgeCircleImageRequest request,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (image == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(image));
|
||||
}
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
}
|
||||
|
||||
FindEdgeCircleImageRequest normalizedRequest = NormalizeRequest(request);
|
||||
VisionProcessResult validationResult = ValidateRequest(normalizedRequest);
|
||||
if (validationResult != null)
|
||||
{
|
||||
return Task.FromResult(CreateFailureResult(validationResult));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
VisionProcessResult<FindEdgeCircleResult> result = ExecuteEdgeCircle(image, normalizedRequest);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
result.Message.LogSysError();
|
||||
}
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
string message = $"FindEdgeCircleService: process image was cancelled.Timeout ={ normalizedRequest.TimeoutMilliseconds}ms.";
|
||||
message.LogInfo();
|
||||
return Task.FromResult(VisionProcessResult<FindEdgeCircleResult>.Failure(
|
||||
VisionFailureCategory.Cancelled,
|
||||
VisionErrorCode.OperationCancelled,
|
||||
null,
|
||||
MessageKey.VisionOperationCancelled,
|
||||
message,
|
||||
ex));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string message = $"FindEdgeCircleService: process image failed. {ex.Message}";
|
||||
message.LogSysError();
|
||||
return Task.FromResult(VisionProcessResult<FindEdgeCircleResult>.Failure(
|
||||
VisionFailureCategory.Algorithm,
|
||||
VisionErrorCode.CommonAlgorithmExecutionFailed,
|
||||
VisionAlarmIds.CommonAlgorithmExecutionFailed,
|
||||
MessageKey.VisionCommonAlgorithmExecutionFailed,
|
||||
message,
|
||||
ex));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行边缘圆检测算法
|
||||
/// </summary>
|
||||
private static VisionProcessResult<FindEdgeCircleResult> ExecuteEdgeCircle(
|
||||
MxImage image,
|
||||
FindEdgeCircleImageRequest request)
|
||||
{
|
||||
Camera camera = image.Image;
|
||||
if (camera == null)
|
||||
{
|
||||
return VisionProcessResult<FindEdgeCircleResult>.Failure(
|
||||
VisionFailureCategory.Algorithm,
|
||||
VisionErrorCode.ImageNull,
|
||||
VisionAlarmIds.ImageNull,
|
||||
MessageKey.VisionImageIsNull,
|
||||
"FindEdgeCircleService: input image does not contain a valid camera object.");
|
||||
}
|
||||
|
||||
var parameters = request.Parameters;
|
||||
double[] hv_Parameter;
|
||||
bool flag;
|
||||
|
||||
if (parameters.RoiRect != null)
|
||||
{
|
||||
// 使用 ROI 区域进行抓圆
|
||||
flag = CalibManager.Instance.calib_edge_circle_by_roi(
|
||||
camera,
|
||||
parameters.CameraId,
|
||||
0,
|
||||
parameters.RoiRect,
|
||||
parameters.FileDirectory,
|
||||
out hv_Parameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 不使用 ROI 进行抓圆
|
||||
flag = CalibManager.Instance.calib_edge_circle(
|
||||
camera,
|
||||
parameters.CameraId,
|
||||
0,
|
||||
parameters.FileDirectory,
|
||||
out hv_Parameter);
|
||||
}
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
return VisionProcessResult<FindEdgeCircleResult>.Failure(
|
||||
VisionFailureCategory.Algorithm,
|
||||
VisionErrorCode.CommonAlgorithmExecutionFailed,
|
||||
VisionAlarmIds.CommonAlgorithmExecutionFailed,
|
||||
MessageKey.VisionCommonAlgorithmExecutionFailed,
|
||||
"FindEdgeCircleService: algorithm calib_edge_circle returned false.");
|
||||
}
|
||||
|
||||
if (hv_Parameter == null || hv_Parameter.Length < 2)
|
||||
{
|
||||
return VisionProcessResult<FindEdgeCircleResult>.Failure(
|
||||
VisionFailureCategory.Algorithm,
|
||||
VisionErrorCode.CommonAlgorithmExecutionFailed,
|
||||
VisionAlarmIds.CommonAlgorithmExecutionFailed,
|
||||
MessageKey.VisionCommonAlgorithmExecutionFailed,
|
||||
"FindEdgeCircleService: algorithm returned invalid parameters.");
|
||||
}
|
||||
|
||||
FindEdgeCircleResult result = new FindEdgeCircleResult();
|
||||
result.CenterX = hv_Parameter[0];
|
||||
result.CenterY = hv_Parameter[1];
|
||||
return VisionProcessResult<FindEdgeCircleResult>.Success(result);
|
||||
}
|
||||
|
||||
private static FindEdgeCircleImageRequest NormalizeRequest(FindEdgeCircleImageRequest request)
|
||||
{
|
||||
FindEdgeCircleImageRequest normalizedRequest = new FindEdgeCircleImageRequest();
|
||||
normalizedRequest.TimeoutMilliseconds = request.TimeoutMilliseconds > 0 ? request.TimeoutMilliseconds :3000;
|
||||
normalizedRequest.Parameters = CloneParameters(request.Parameters);
|
||||
return normalizedRequest;
|
||||
}
|
||||
|
||||
private static VisionProcessResult ValidateRequest(FindEdgeCircleImageRequest request)
|
||||
{
|
||||
if (request.Parameters == null)
|
||||
{
|
||||
return VisionProcessResult.Failure(
|
||||
VisionFailureCategory.Validation,
|
||||
VisionErrorCode.RequestInvalid,
|
||||
VisionAlarmIds.RequestInvalid,
|
||||
MessageKey.VisionRequestInvalid,
|
||||
"FindEdgeCircleService: parameters cannot be null.");
|
||||
}
|
||||
|
||||
if (request.TimeoutMilliseconds <= 0 || request.TimeoutMilliseconds > 60000)
|
||||
{
|
||||
return VisionProcessResult.Failure(
|
||||
VisionFailureCategory.Validation,
|
||||
VisionErrorCode.TimeoutInvalid,
|
||||
VisionAlarmIds.RequestInvalid,
|
||||
MessageKey.VisionTimeoutInvalid,
|
||||
string.Format("FindEdgeCircleService: TimeoutMilliseconds {0} is invalid. Expected range is [1,60000].", request.TimeoutMilliseconds));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.Parameters.FileDirectory))
|
||||
{
|
||||
return VisionProcessResult.Failure(
|
||||
VisionFailureCategory.Validation,
|
||||
VisionErrorCode.RequestInvalid,
|
||||
VisionAlarmIds.RequestInvalid,
|
||||
MessageKey.VisionRequestInvalid,
|
||||
"FindEdgeCircleService: FileDirectory cannot be empty.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.Parameters.CameraId))
|
||||
{
|
||||
return VisionProcessResult.Failure(
|
||||
VisionFailureCategory.Validation,
|
||||
VisionErrorCode.RequestInvalid,
|
||||
VisionAlarmIds.RequestInvalid,
|
||||
MessageKey.VisionRequestInvalid,
|
||||
"FindEdgeCircleService: CameraId cannot be empty.");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static FindEdgeCircleParameters CloneParameters(FindEdgeCircleParameters parameters)
|
||||
{
|
||||
if (parameters == null)
|
||||
{
|
||||
return new FindEdgeCircleParameters();
|
||||
}
|
||||
|
||||
FindEdgeCircleParameters clone = new FindEdgeCircleParameters();
|
||||
clone.UseRoi = parameters.UseRoi;
|
||||
clone.RoiName = parameters.RoiName;
|
||||
clone.FileDirectory = parameters.FileDirectory;
|
||||
clone.CameraId = parameters.CameraId;
|
||||
clone.RoiRect = parameters.RoiRect;
|
||||
return clone;
|
||||
}
|
||||
|
||||
private static FindEdgeCircleImageRequest CreateImageRequest(FindEdgeCircleRequest request)
|
||||
{
|
||||
FindEdgeCircleImageRequest imageRequest = new FindEdgeCircleImageRequest();
|
||||
imageRequest.TimeoutMilliseconds = request.TimeoutMilliseconds;
|
||||
imageRequest.Parameters = CloneParameters(request.Parameters);
|
||||
return imageRequest;
|
||||
}
|
||||
|
||||
private async Task<VisionProcessResult<FindEdgeCircleResult>> ExecuteWithCaptureAsync(
|
||||
CameraType cameraSource,
|
||||
CameraCaptureOptions captureOptions,
|
||||
FindEdgeCircleImageRequest imageRequest,
|
||||
Func<MxImage, FindEdgeCircleImageRequest, CancellationToken,
|
||||
Task<VisionProcessResult<FindEdgeCircleResult>>> imageProcessor,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
ImageCaptureResult captureResult = null;
|
||||
MxImage image = null;
|
||||
|
||||
try
|
||||
{
|
||||
captureResult = await _imageCaptureService.CaptureAsync(
|
||||
cameraSource,
|
||||
captureOptions,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (captureResult == null)
|
||||
{
|
||||
return VisionProcessResult<FindEdgeCircleResult>.Failure(
|
||||
VisionFailureCategory.Capture,
|
||||
VisionErrorCode.NoFrame,
|
||||
VisionAlarmIds.NoFrame,
|
||||
MessageKey.VisionNoFrameReturned,
|
||||
string.Format(
|
||||
"FindEdgeCircleService: image capture returned null result for camera '{0}'.",
|
||||
cameraSource));
|
||||
}
|
||||
|
||||
if (!captureResult.Succeeded)
|
||||
{
|
||||
return CreateFailureResult(VisionResultMapper.CreateCaptureFailure(captureResult));
|
||||
}
|
||||
|
||||
image = captureResult.Image;
|
||||
if (image == null)
|
||||
{
|
||||
string message = string.Format(
|
||||
"FindEdgeCircleService: image capture succeeded but returned null image for camera '{0}'.",
|
||||
cameraSource);
|
||||
message.LogSysError();
|
||||
return VisionProcessResult<FindEdgeCircleResult>.Failure(
|
||||
VisionFailureCategory.Capture,
|
||||
VisionErrorCode.ImageNull,
|
||||
VisionAlarmIds.ImageNull,
|
||||
MessageKey.VisionImageIsNull,
|
||||
message);
|
||||
}
|
||||
|
||||
return await imageProcessor(image, imageRequest, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
string message = $"FindEdgeCircleService: capture orchestration was cancelled for camera '{cameraSource}'.";
|
||||
message.LogInfo();
|
||||
return VisionProcessResult<FindEdgeCircleResult>.Failure(
|
||||
VisionFailureCategory.Cancelled,
|
||||
VisionErrorCode.OperationCancelled,
|
||||
null,
|
||||
MessageKey.VisionOperationCancelled,
|
||||
message,
|
||||
ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string message = $"FindEdgeCircleService: capture orchestration failed for camera '{cameraSource}'. { ex.Message} ";
|
||||
message.LogSysError();
|
||||
return VisionProcessResult<FindEdgeCircleResult>.Failure(
|
||||
VisionFailureCategory.Algorithm,
|
||||
VisionErrorCode.CommonAlgorithmExecutionFailed,
|
||||
VisionAlarmIds.CommonAlgorithmExecutionFailed,
|
||||
MessageKey.VisionCommonAlgorithmExecutionFailed,
|
||||
message,
|
||||
ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (image != null)
|
||||
{
|
||||
image.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static VisionProcessResult<FindEdgeCircleResult> CreateFailureResult(VisionProcessResult result)
|
||||
{
|
||||
return VisionProcessResult<FindEdgeCircleResult>.Failure(
|
||||
result.FailureCategory,
|
||||
result.ErrorCode,
|
||||
result.AlarmId,
|
||||
result.UserMessageKey,
|
||||
result.Message,
|
||||
result.Exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using MainShell.Models;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MainShell.Vision
|
||||
{
|
||||
/// <summary>
|
||||
/// 抓圆服务接口
|
||||
/// </summary>
|
||||
public interface IFindEdgeCircleService
|
||||
{
|
||||
/// <summary>
|
||||
/// 采集图像并执行抓圆
|
||||
/// </summary>
|
||||
Task<VisionProcessResult<FindEdgeCircleResult>> ProcessAsync(
|
||||
FindEdgeCircleRequest request,
|
||||
CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// 基于已有图像直接执行抓圆
|
||||
/// </summary>
|
||||
Task<VisionProcessResult<FindEdgeCircleResult>> ProcessImageAsync(
|
||||
MxImage image,
|
||||
FindEdgeCircleImageRequest request,
|
||||
CancellationToken cancellationToken = default(CancellationToken));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user