before candybox editor update

This commit is contained in:
meelstorm
2025-09-16 10:42:43 +02:00
parent e5746ef766
commit dc12b3e51a
103 changed files with 96379 additions and 343 deletions

View File

@@ -1,5 +1,5 @@
using OpenCvSharp;
using VisionBuilder.UI.Common.RecipeProcessing;
using VisionBuilder.UI.Common.Processing;
namespace VisionBuilder.UI.Recipes.HawkeyeRecipe;

View File

@@ -5,14 +5,15 @@ using System.Threading.Tasks;
using Hawkeye.VisionBuilder.Workflow;
using Hawkeye.VisionBuilder.Workflow.Datatypes;
using Hawkeye.VisionBuilder.Workflow.Operations;
using OpenCvSharp;
using Serilog;
using VisionBuilder.UI.Common.Commands;
using VisionBuilder.UI.Common.RecipeProcessing;
using VisionBuilder.UI.Common.Processing;
using VisionBuilder.UI.Common.ViewModel.Classes;
namespace VisionBuilder.UI.Recipes.HawkeyeRecipe
{
public class HawkeyeRecognitionControl: IRecognitionControl
public class HawkeyeRecognitionControl: BaseRecognitionControl
{
private readonly IImageSource _imageSource;
private readonly HawkeyeRecognitionSettings _recognitionConfiguration;
@@ -21,14 +22,14 @@ namespace VisionBuilder.UI.Recipes.HawkeyeRecipe
private CancellationTokenSource _cts;
private Task _loopTask;
public HawkeyeRecognitionControl(IImageSource imageSource, HawkeyeRecognitionSettings recognitionConfiguration, ILoadingService loadingService)
public HawkeyeRecognitionControl(IImageSource imageSource, HawkeyeRecognitionSettings recognitionConfiguration, ILoadingService loadingService): base(recognitionConfiguration,loadingService)
{
_imageSource = imageSource;
_recognitionConfiguration = recognitionConfiguration;
_loadingService = loadingService;
}
public List<RecipeData> GetRecipesData()
public override List<RecipeData> GetRecipesData()
{
_loadingService.StartLoading($"Loading recipes for {_recognitionConfiguration.CameraName}...");
try
@@ -55,178 +56,58 @@ namespace VisionBuilder.UI.Recipes.HawkeyeRecipe
}
}
RecipeData _currentRecipe;
public void SetRecipe(RecipeData recipe)
{
// error if running
if (IsRunning)
{
throw new InvalidOperationException("Cannot change recipe while recognition is running.");
}
_currentRecipe = recipe;
}
public bool IsRunning { get; set; }
public bool IsPaused { get; set; }
private DateTime _startTime;
private WorkflowList _workflow;
public void Start()
{
if (_currentRecipe == null)
{
throw new InvalidOperationException("No recipe set.");
}
if (IsRunning)
{
throw new InvalidOperationException("Recognition is already running.");
}
_loadingService.StartLoading($"Starting recipe {_currentRecipe.RecipeName} on {_recognitionConfiguration.CameraName}...");
_workflow = WorkflowList.LoadJSONFromFile("..\\Data\\Recipes\\" + _currentRecipe.RecipeName + ".jhrcp");
_startTime = DateTime.Now;
IsRunning = true;
_cts = new CancellationTokenSource();
Log.Information($"Warming up");
protected override void Initialize(RecipeData currentRecipe)
{
_workflow = WorkflowList.LoadJSONFromFile("..\\Data\\Recipes\\" + currentRecipe.RecipeName + ".jhrcp");
}
protected override void WarmUp()
{
_workflow.ImageSource = new EmptyImageSource();
_workflow.Context = new Context();
_workflow.Context.CancellationToken = CancellationToken.None;
_workflow.Execute();
}
protected override (Mat originalImage, Mat analysisImage,TimeSpan processingTime, TimeSpan acquisitionTime, string[] errorNames)? ProcessImage(CancellationToken token)
{
var sw = Stopwatch.StartNew();
_workflow.Context.CancellationToken = token;
_workflow.ImageSource = _imageSource;
try
{
var swWarmup = Stopwatch.StartNew();
// warmup run
_workflow.ImageSource = new EmptyImageSource();
_workflow.Context = new Context();
_workflow.Context.CancellationToken = CancellationToken.None;
_workflow.Execute(); // Warmup run
swWarmup.Stop();
Log.Information($"Warmup run took {swWarmup.ElapsedMilliseconds} ms");
_workflow.Execute();
}
catch (Exception ex)
catch (Exception e) when (token.IsCancellationRequested)
{
Log.Error(ex, "Error during warmup run");
}
_loopTask = Task.Run(() => Loop(_cts.Token), _cts.Token);
SessionStarted?.Invoke(new SessionStartedEvent
{
RecipeName = _currentRecipe.RecipeName,
SessionStarted = _startTime,
});
_loadingService.StopLoading($"Starting recipe {_currentRecipe.RecipeName} on {_recognitionConfiguration.CameraName}...");
}
public void Stop()
{
if (!IsRunning)
return ;
_loadingService.StartLoading($"Stopping {_recognitionConfiguration.CameraName}");
_cts?.Cancel();
try
{
_loopTask?.Wait();
}
catch (AggregateException ex) when (ex.InnerExceptions.All(e => e is TaskCanceledException))
{
// Ignore cancellation exceptions
}
finally
{
IsRunning = false;
_cts?.Dispose();
_cts = null;
_loopTask = null;
}
SessionEnded?.Invoke(new SessionEndedEvent
{
SessionEnded = DateTime.Now
});
_loadingService.StopLoading($"Stopping {_recognitionConfiguration.CameraName}");
}
public void Pause()
{
IsPaused= true;
}
public void Resume()
{
IsPaused = false;
}
private async Task Loop(CancellationToken token)
{
// Start the recognition process using the Hawkeye library
while (!token.IsCancellationRequested)
{
if (IsPaused)
{
await Task.Delay(100, token);
continue;
}
var sw = Stopwatch.StartNew();
_workflow.Context.CancellationToken= token;
_workflow.ImageSource= _imageSource;
try
{
_workflow.Execute();
}
catch (Exception e) when(token.IsCancellationRequested)
{
sw.Stop();
return;
}
sw.Stop();
if (sw.ElapsedMilliseconds < _recognitionConfiguration.MinimumProcessingTime)
{
Thread.Sleep(_recognitionConfiguration.MinimumProcessingTime - (int)sw.ElapsedMilliseconds);
}
string[] errorNames = _workflow.Operations.Where(x => !x.Result).Select(x => x.Label).ToArray();
var annotated = _workflow.Context.ActiveImage.ImageData.Clone();
var canvas = new OpenCVCanvas(annotated);
_workflow.Context.GraphicsElements.ForEach(x => x.Draw(canvas));
TimeSpan cameraTime = TimeSpan.FromMilliseconds(0);
var cameraOperation = _workflow.Operations.FirstOrDefault(x => x is GetImageOperation);
if (cameraOperation != null)
{
cameraTime=cameraOperation.ExecutionTime;
}
var processingResult = new ImageProcessedEvent()
{
SessionStart = _startTime,
RecipeName = _currentRecipe.RecipeName,
AnalysisTime = sw.Elapsed- cameraTime,
ErrorNames = errorNames.ToList(),
HasError = errorNames.Length > 0,
ImageSource = _recognitionConfiguration.CameraName,
ImageOriginal = _workflow.Context.LastCameraImage.ImageData,
ImageAnalysis = annotated
};
var swProcessed = Stopwatch.StartNew();
ImageProcessed(processingResult);
swProcessed.Stop();
Log.Information($"ImageProcessed event handled in {swProcessed.ElapsedMilliseconds} ms");
return null;
}
sw.Stop();
var annotated = _workflow.Context.ActiveImage.ImageData.Clone();
var canvas = new OpenCVCanvas(annotated);
_workflow.Context.GraphicsElements.ForEach(x => x.Draw(canvas));
var originalImage = _workflow.Context.LastCameraImage.ImageData;
var analysisImage = _workflow.Context.ActiveImage.ImageData;
var cameraOperation = _workflow.Operations.FirstOrDefault(x => x is GetImageOperation);
TimeSpan cameraTime = TimeSpan.FromMilliseconds(0);
if (cameraOperation != null)
{
cameraTime = cameraOperation.ExecutionTime;
}
string[] errorNames = _workflow.Operations.Where(x => !x.Result).Select(x => x.Label).ToArray();
return (originalImage, analysisImage, sw.Elapsed, cameraTime, errorNames);
}
public event Action<ImageProcessedEvent> ImageProcessed = delegate{};
public event Action<SessionStartedEvent>? SessionStarted = delegate { };
public event Action<SessionEndedEvent>? SessionEnded = delegate { };
}
}

View File

@@ -1,22 +1,11 @@
using Inspectron.Settings;
using VisionBuilder.UI.Common;
using VisionBuilder.UI.Common.Processing;
namespace VisionBuilder.UI.Recipes.HawkeyeRecipe;
public class HawkeyeRecognitionSettings: ISettings
public class HawkeyeRecognitionSettings(string cameraName) : BaseRecognitionControlSettings(cameraName)
{
public string CameraName { get; }
public HawkeyeRecognitionSettings(string cameraName)
{
CameraName = cameraName;
}
public int MinimumProcessingTime { get; set; }
public string RecipeNameFilter { get; set; } = "*";
public void RegisterSettings(InspectronSettings settings)
{
settings.RegisterSimple(this, () => this.MinimumProcessingTime, CameraName+"/Hawkeye recognition", "Minimum processing time (ms)");
settings.RegisterSimple(this, () => this.RecipeNameFilter, CameraName + "/Hawkeye recognition", nameof(RecipeNameFilter));
}
}

View File

@@ -1,6 +1,6 @@
using Ninject.Extensions.ChildKernel;
using VisionBuilder.UI.Common;
using VisionBuilder.UI.Common.RecipeProcessing;
using VisionBuilder.UI.Common.Processing;
namespace VisionBuilder.UI.Recipes.HawkeyeRecipe;