This commit is contained in:
meelstorm
2025-09-24 16:27:07 +02:00
parent 0ebe629922
commit 87c1145744
11 changed files with 59 additions and 41 deletions

View File

@@ -16,7 +16,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoCompleteMenu-ScintillaNET" Version="2.1.0" /> <PackageReference Include="AutoCompleteMenu-ScintillaNET" Version="2.1.0" />
<PackageReference Include="MathNet.Numerics" Version="5.0.0" /> <PackageReference Include="MathNet.Numerics" Version="5.0.0" />
<PackageReference Include="Microsoft.ML.OnnxRuntime.Gpu" Version="1.22.1" />
<PackageReference Include="OpenCvSharp4" Version="4.6.0.20220608" /> <PackageReference Include="OpenCvSharp4" Version="4.6.0.20220608" />
<PackageReference Include="OpenCvSharp4.Extensions" Version="4.6.0.20220608" /> <PackageReference Include="OpenCvSharp4.Extensions" Version="4.6.0.20220608" />
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.6.0.20220608" /> <PackageReference Include="OpenCvSharp4.runtime.win" Version="4.6.0.20220608" />

View File

@@ -40,6 +40,8 @@ public abstract class BaseRecognitionControl: IRecognitionControl
public RecipeData CurrentRecipe => _currentRecipe; public RecipeData CurrentRecipe => _currentRecipe;
public ILoadingService LoadingService => _loadingService;
private DateTime _startTime; private DateTime _startTime;
public void Start() public void Start()
@@ -141,7 +143,7 @@ public abstract class BaseRecognitionControl: IRecognitionControl
private async Task Loop(CancellationToken token) private async Task Loop(CancellationToken token)
{ {
// Start the recognition process using the Hawkeye library
while (!token.IsCancellationRequested) while (!token.IsCancellationRequested)
{ {

View File

@@ -3,6 +3,7 @@ using CommunityToolkit.Mvvm.Input;
using OpenCvSharp; using OpenCvSharp;
using VisionBuilder.UI.Common.Commands; using VisionBuilder.UI.Common.Commands;
using VisionBuilder.UI.Common.Commands.Interfaces; using VisionBuilder.UI.Common.Commands.Interfaces;
using VisionBuilder.UI.Common.Services;
using VisionBuilder.UI.Common.ViewModel.Classes; using VisionBuilder.UI.Common.ViewModel.Classes;
using VisionBuilder.UI.Common.ViewModel.Interfaces.UI; using VisionBuilder.UI.Common.ViewModel.Interfaces.UI;
using static System.Runtime.InteropServices.JavaScript.JSType; using static System.Runtime.InteropServices.JavaScript.JSType;
@@ -16,12 +17,14 @@ public partial class ErrorPreviewVM:ObservableObject
private ErrorData _errorData; private ErrorData _errorData;
private readonly ILearningTool _learningTool; private readonly ILearningTool _learningTool;
private readonly IPasswordInputService _passwordInputService;
[ObservableProperty] [ObservableProperty]
private string _recipeName; private string _recipeName;
private readonly UIConfiguration _uiConfiguration;
[ObservableProperty] [ObservableProperty]
private bool _learnButtonVisible; private bool _learnButtonVisible;
@@ -37,12 +40,14 @@ public partial class ErrorPreviewVM:ObservableObject
[ObservableProperty] [ObservableProperty]
private Mat _imageAnalysis; private Mat _imageAnalysis;
public ErrorPreviewVM(ErrorsVM errorsVm, ErrorData errorData, string recipeName, UIConfiguration uiConfiguration, ILearningTool learningTool) public ErrorPreviewVM(ErrorsVM errorsVm, ErrorData errorData, string recipeName, UIConfiguration uiConfiguration, ILearningTool learningTool, IPasswordInputService passwordInputService)
{ {
_errorsVm = errorsVm; _errorsVm = errorsVm;
_errorData = errorData; _errorData = errorData;
_recipeName = recipeName; _recipeName = recipeName;
_uiConfiguration = uiConfiguration;
_learningTool = learningTool; _learningTool = learningTool;
_passwordInputService = passwordInputService;
UpdateData(); UpdateData();
} }
@@ -95,6 +100,11 @@ public partial class ErrorPreviewVM:ObservableObject
[RelayCommand(CanExecute = nameof(LearnButtonVisible))] [RelayCommand(CanExecute = nameof(LearnButtonVisible))]
public void Learn() public void Learn()
{ {
if (string.IsNullOrEmpty(_uiConfiguration.AdminPassword))
{
var passwordOk= _passwordInputService.GetPassword()==_uiConfiguration.AdminPassword;
if (!passwordOk) return;
}
_learningTool.Learn(_errorData.RecipeName, _errorData.ImageOriginal); _learningTool.Learn(_errorData.RecipeName, _errorData.ImageOriginal);
} }

View File

@@ -1,6 +1,7 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using VisionBuilder.UI.Common.Commands; using VisionBuilder.UI.Common.Commands;
using VisionBuilder.UI.Common.Commands.Interfaces; using VisionBuilder.UI.Common.Commands.Interfaces;
using VisionBuilder.UI.Common.Services;
using VisionBuilder.UI.Common.ViewModel.Classes; using VisionBuilder.UI.Common.ViewModel.Classes;
using VisionBuilder.UI.Common.ViewModel.Interfaces.UI; using VisionBuilder.UI.Common.ViewModel.Interfaces.UI;
@@ -11,12 +12,14 @@ public class ErrorsVM:IEventHandler<ImageProcessedEvent>, IEventHandler<SessionS
private readonly UIConfiguration _uiConfiguration; private readonly UIConfiguration _uiConfiguration;
private readonly IImagePreviewService _imagePreviewService; private readonly IImagePreviewService _imagePreviewService;
private readonly ILearningTool _learningTool; private readonly ILearningTool _learningTool;
private readonly IPasswordInputService _passwordInputService;
public ErrorsVM(UIConfiguration uiConfiguration, IImagePreviewService imagePreviewService, ILearningTool learningTool) public ErrorsVM(UIConfiguration uiConfiguration, IImagePreviewService imagePreviewService, ILearningTool learningTool, IPasswordInputService passwordInputService)
{ {
_uiConfiguration = uiConfiguration; _uiConfiguration = uiConfiguration;
_imagePreviewService = imagePreviewService; _imagePreviewService = imagePreviewService;
_learningTool = learningTool; _learningTool = learningTool;
_passwordInputService = passwordInputService;
} }
@@ -26,7 +29,7 @@ public class ErrorsVM:IEventHandler<ImageProcessedEvent>, IEventHandler<SessionS
{ {
if (errorData == null) return; if (errorData == null) return;
var vm = new ErrorPreviewVM(this, errorData, errorData.RecipeName, _uiConfiguration, _learningTool); var vm = new ErrorPreviewVM(this, errorData, errorData.RecipeName, _uiConfiguration, _learningTool, _passwordInputService);
_imagePreviewService.ShowImagePreview(vm); _imagePreviewService.ShowImagePreview(vm);
} }

View File

@@ -5,6 +5,7 @@ using System.ComponentModel;
using VisionBuilder.UI.Common.Commands; using VisionBuilder.UI.Common.Commands;
using VisionBuilder.UI.Common.Commands.Interfaces; using VisionBuilder.UI.Common.Commands.Interfaces;
using VisionBuilder.UI.Common.Processing; using VisionBuilder.UI.Common.Processing;
using VisionBuilder.UI.Common.Services;
using VisionBuilder.UI.Common.ViewModel; using VisionBuilder.UI.Common.ViewModel;
using VisionBuilder.UI.Common.ViewModel.Classes; using VisionBuilder.UI.Common.ViewModel.Classes;
using VisionBuilder.UI.Common.ViewModel.Interfaces.UI; using VisionBuilder.UI.Common.ViewModel.Interfaces.UI;
@@ -78,12 +79,12 @@ namespace VisionBuilder.UI.Common
private RecipeData? _selectedRecipe; private RecipeData? _selectedRecipe;
public SingleCameraVM(CameraSettings cameraSettings, UIConfiguration uiConfiguration, IRecipeSelectionDialogService recipeSelectionDialogService, IRecognitionControl recognitionControl, IImagePreviewService imagePreviewService, ILearningTool learningTool) public SingleCameraVM(CameraSettings cameraSettings, UIConfiguration uiConfiguration, IRecipeSelectionDialogService recipeSelectionDialogService, IRecognitionControl recognitionControl, IImagePreviewService imagePreviewService, ILearningTool learningTool, IPasswordInputService passwordInputService)
{ {
_recipeSelectionDialogService = recipeSelectionDialogService; _recipeSelectionDialogService = recipeSelectionDialogService;
_recognitionControl = recognitionControl; _recognitionControl = recognitionControl;
ErrorsVm = new ErrorsVM(uiConfiguration, imagePreviewService, learningTool); ErrorsVm = new ErrorsVM(uiConfiguration, imagePreviewService, learningTool, passwordInputService);
StatisticsVm = new StatisticsVM(); StatisticsVm = new StatisticsVM();
PreviewVm = new PreviewVM(); PreviewVm = new PreviewVM();

View File

@@ -23,7 +23,7 @@ namespace VisionBuilder.UI.IOCommander.Windows
InitializeCheckboxes(); InitializeCheckboxes();
} }
public BitArray PinState { get; set; } = new BitArray(20); public BitArray PinState { get; set; } = new BitArray(10);
public event Action<int, bool>? OnPinChanged = delegate { }; public event Action<int, bool>? OnPinChanged = delegate { };
public void SetPins(int pin, bool state) public void SetPins(int pin, bool state)
@@ -35,7 +35,7 @@ namespace VisionBuilder.UI.IOCommander.Windows
{ {
// Set form properties // Set form properties
this.Text = "IO Commander Virtual Input"; this.Text = "IO Commander Virtual Input";
this.ClientSize = new Size(200, 500); this.ClientSize = new Size(200, 280);
this.FormBorderStyle = FormBorderStyle.FixedDialog; this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.MaximizeBox = false; this.MaximizeBox = false;
this.StartPosition = FormStartPosition.Manual; this.StartPosition = FormStartPosition.Manual;
@@ -50,11 +50,11 @@ namespace VisionBuilder.UI.IOCommander.Windows
this.Controls.Add(panel); this.Controls.Add(panel);
// Initialize checkboxes // Initialize checkboxes
_checkBoxes = new CheckBox[20]; _checkBoxes = new CheckBox[10];
for (int i = 0; i < 20; i++) for (int i = 0; i < 10; i++)
{ {
int pinNumber = i; // Pins are 1-indexed int pinNumber = i + 1; // Pins are 1-indexed (1-10)
_checkBoxes[i] = new CheckBox _checkBoxes[i] = new CheckBox
{ {
Text = pinNumber.ToString(), Text = pinNumber.ToString(),
@@ -77,8 +77,8 @@ namespace VisionBuilder.UI.IOCommander.Windows
int pin = (int)checkBox.Tag; int pin = (int)checkBox.Tag;
bool state = checkBox.Checked; bool state = checkBox.Checked;
// Update the BitArray // Update the BitArray (convert 1-based pin to 0-based index)
PinState.Set(pin, state); // Adjust for 0-based indexing in BitArray PinState.Set(pin - 1, state);
// Trigger the event // Trigger the event
OnPinChanged?.Invoke(pin, state); OnPinChanged?.Invoke(pin, state);

View File

@@ -38,25 +38,25 @@ namespace VisionBuilder.UI.IOCommander.Windows
this.ShowInTaskbar = false; this.ShowInTaskbar = false;
this.StartPosition = FormStartPosition.Manual; this.StartPosition = FormStartPosition.Manual;
this.Location = new Point(50, 50); this.Location = new Point(50, 50);
this.Size = new Size(280, 450); // Made wider to accommodate labels this.Size = new Size(400, 350); // Made wider and adjusted height for 10 rows
this.BackColor = Color.FromArgb(64, 64, 64); this.BackColor = Color.FromArgb(64, 64, 64);
this.MinimizeBox = false; this.MinimizeBox = false;
this.MaximizeBox = false; this.MaximizeBox = false;
// Create pin indicators for input pins 0-19 and output pins 0-19 (20 rows, 2 columns) // Create pin indicators for input pins 1-10 and output pins 1-10 (10 rows, 2 columns)
int pinSize = 18; int pinSize = 24; // Increased from 18
int spacing = 2; int spacing = 4; // Increased from 2
int centerX = 140; // Center the graphics in the wider form int centerX = 200; // Center the graphics in the wider form
int startY = 10; int startY = 15; // Slightly more margin
// Get label dictionaries for quick lookup // Get label dictionaries for quick lookup
var inputLabelDict = _settings.InputPinLabels?.ToDictionary(pl => pl.Pin, pl => pl.Label) ?? new Dictionary<int, string>(); var inputLabelDict = _settings.InputPinLabels?.ToDictionary(pl => pl.Pin, pl => pl.Label) ?? new Dictionary<int, string>();
var outputLabelDict = _settings.OutputPinLabels?.ToDictionary(pl => pl.Pin, pl => pl.Label) ?? new Dictionary<int, string>(); var outputLabelDict = _settings.OutputPinLabels?.ToDictionary(pl => pl.Pin, pl => pl.Label) ?? new Dictionary<int, string>();
for (int row = 0; row < 20; row++) for (int row = 0; row < 10; row++) // Changed from 20 to 10
{ {
int inputPin = row; // Input pins numbered 0-19 int inputPin = row + 1; // Input pins numbered 1-10
int outputPin = row; // Output pins numbered 0-19 int outputPin = row + 1; // Output pins numbered 1-10
// Left column (input pins) // Left column (input pins)
var leftIndicator = new PinIndicator(inputPin, true) var leftIndicator = new PinIndicator(inputPin, true)
@@ -81,9 +81,9 @@ namespace VisionBuilder.UI.IOCommander.Windows
var leftLabel = new Label var leftLabel = new Label
{ {
Text = inputLabelText, Text = inputLabelText,
Location = new Point(5, startY + (row * (pinSize + spacing)) + 2), Location = new Point(5, startY + (row * (pinSize + spacing)) + 4), // Adjusted vertical alignment
Size = new Size(centerX - pinSize - spacing * 3 - 5, 14), Size = new Size(centerX - pinSize - spacing * 3 - 5, 16), // Increased height from 14
Font = new Font("Arial", 6, FontStyle.Bold), Font = new Font("Arial", 8, FontStyle.Bold), // Increased from 6
ForeColor = Color.White, ForeColor = Color.White,
BackColor = Color.Transparent, BackColor = Color.Transparent,
TextAlign = ContentAlignment.MiddleRight TextAlign = ContentAlignment.MiddleRight
@@ -95,9 +95,9 @@ namespace VisionBuilder.UI.IOCommander.Windows
var rightLabel = new Label var rightLabel = new Label
{ {
Text = outputLabelText, Text = outputLabelText,
Location = new Point(centerX + pinSize + spacing * 3, startY + (row * (pinSize + spacing)) + 2), Location = new Point(centerX + pinSize + spacing * 3, startY + (row * (pinSize + spacing)) + 4), // Adjusted vertical alignment
Size = new Size(this.Width - (centerX + pinSize + spacing * 3) - 10, 14), Size = new Size(this.Width - (centerX + pinSize + spacing * 3) - 10, 16), // Increased height from 14
Font = new Font("Arial", 6, FontStyle.Bold), Font = new Font("Arial", 8, FontStyle.Bold), // Increased from 6
ForeColor = Color.White, ForeColor = Color.White,
BackColor = Color.Transparent, BackColor = Color.Transparent,
TextAlign = ContentAlignment.MiddleLeft TextAlign = ContentAlignment.MiddleLeft

View File

@@ -51,7 +51,7 @@ public class IOCommander : IIOCommander
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
if (arrcurrentPinsState[i] != arrreadState[i]) if (arrcurrentPinsState[i] != arrreadState[i])
OnPinChanged(i, arrreadState[i]); OnPinChanged(i+1, arrreadState[i]);
} }
} }
@@ -80,6 +80,7 @@ public class IOCommander : IIOCommander
public void SetPins(int pin, bool state) public void SetPins(int pin, bool state)
{ {
pin -= 1;
lock (this) lock (this)
{ {
//Log.Logger.ForContext<IOCommander>().Verbose("Setting pin {pin} to {state}", pin, state); //Log.Logger.ForContext<IOCommander>().Verbose("Setting pin {pin} to {state}", pin, state);

View File

@@ -28,10 +28,12 @@ public class IOCommanderSettings: ISettings
settings.RegisterSimple(this, () => Port, "IOCommander", nameof(Port)); settings.RegisterSimple(this, () => Port, "IOCommander", nameof(Port));
settings.RegisterSimple(this, () => PulseLength, "IOCommander", nameof(PulseLength)); settings.RegisterSimple(this, () => PulseLength, "IOCommander", nameof(PulseLength));
settings.RegisterSimple(this, () => ShowDebugView, "IOCommander", nameof(ShowDebugView)); settings.RegisterSimple(this, () => ShowDebugView, "IOCommander", nameof(ShowDebugView));
settings.RegisterSimple(this, () => Enabled, "IOCommander", nameof(Enabled));
foreach (IOCommanderProcessingEvent @event in GlobalEvents) foreach (IOCommanderProcessingEvent @event in GlobalEvents)
{ {
settings.RegisterSimple(@event, () => @event.Actions, "IOCommander/Global outputs/" + @event.Event.ToString(), nameof(@event.Actions)); settings.RegisterSimple(@event, () => @event.Actions,
"IOCommander/Global outputs/" + @event.Event.ToString(), nameof(@event.Actions));
} }
} }
} }

View File

@@ -17,7 +17,7 @@ namespace VisionBuilder.UI.Recipes.HawkeyeRecipe
{ {
private readonly IImageSource _imageSource; private readonly IImageSource _imageSource;
private readonly HawkeyeRecognitionSettings _recognitionConfiguration; private readonly HawkeyeRecognitionSettings _recognitionConfiguration;
private readonly ILoadingService _loadingService;
private CancellationTokenSource _cts; private CancellationTokenSource _cts;
private Task _loopTask; private Task _loopTask;
@@ -31,7 +31,7 @@ namespace VisionBuilder.UI.Recipes.HawkeyeRecipe
public override List<RecipeData> GetRecipesData() public override List<RecipeData> GetRecipesData()
{ {
_loadingService.StartLoading($"Loading recipes for {_recognitionConfiguration.CameraName}..."); LoadingService.StartLoading($"Loading recipes for {_recognitionConfiguration.CameraName}...");
try try
{ {
var files = WorkflowRecipeHelper.ListRecipeFiles(_recognitionConfiguration.RecipeNameFilter); var files = WorkflowRecipeHelper.ListRecipeFiles(_recognitionConfiguration.RecipeNameFilter);
@@ -52,7 +52,7 @@ namespace VisionBuilder.UI.Recipes.HawkeyeRecipe
} }
finally finally
{ {
_loadingService.StopLoading($"Loading recipes for {_recognitionConfiguration.CameraName}..."); LoadingService.StopLoading($"Loading recipes for {_recognitionConfiguration.CameraName}...");
} }
} }
@@ -95,7 +95,7 @@ namespace VisionBuilder.UI.Recipes.HawkeyeRecipe
_workflow.Context.GraphicsElements.ForEach(x => x.Draw(canvas)); _workflow.Context.GraphicsElements.ForEach(x => x.Draw(canvas));
var originalImage = _workflow.Context.LastCameraImage.ImageData; var originalImage = _workflow.Context.LastCameraImage.ImageData;
var analysisImage = _workflow.Context.ActiveImage.ImageData; var analysisImage = annotated;
var cameraOperation = _workflow.Operations.FirstOrDefault(x => x is GetImageOperation); var cameraOperation = _workflow.Operations.FirstOrDefault(x => x is GetImageOperation);
TimeSpan cameraTime = TimeSpan.FromMilliseconds(0); TimeSpan cameraTime = TimeSpan.FromMilliseconds(0);

View File

@@ -8,7 +8,7 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<ApplicationIcon>Inspectron icon-512.ico</ApplicationIcon> <ApplicationIcon>Inspectron icon-512.ico</ApplicationIcon>
<Deterministic>false</Deterministic> <Deterministic>false</Deterministic>
<Version>1.0.3</Version> <Version>1.0.4</Version>
</PropertyGroup> </PropertyGroup>