check point
This commit is contained in:
418
Hawkeye.VisionBuilder/MainWindow.cs
Normal file
418
Hawkeye.VisionBuilder/MainWindow.cs
Normal file
@@ -0,0 +1,418 @@
|
||||
using Compunet.YoloV8;
|
||||
using Hawkeye.VisionBuilder.Features.ColorProgileGenerator;
|
||||
using Hawkeye.VisionBuilder.Features.ImagePreview;
|
||||
using Hawkeye.VisionBuilder.Features.ImagesStrip;
|
||||
using Hawkeye.VisionBuilder.Features.ToolEditor;
|
||||
using Hawkeye.VisionBuilder.Features.VisionSteps;
|
||||
using Hawkeye.VisionBuilder.Features.Yolo;
|
||||
using Hawkeye.VisionBuilder.Panels;
|
||||
using Hawkeye.VisionBuilder.Workflow;
|
||||
using Hawkeye.VisionBuilder.Workflow.ColorStudioClasses;
|
||||
using Hawkeye.VisionBuilder.Workflow.Configuration;
|
||||
using Hawkeye.VisionBuilder.Workflow.Datatypes;
|
||||
using Hawkeye.VisionBuilder.Workflow.Operations.AI;
|
||||
using Hawkeye.VisionBuilder.Workflow.Operations.Filters;
|
||||
using Hawkeye.VisionBuilder.Workflow.Operations.Memory;
|
||||
|
||||
using Inspectron.Settings.WindowsWizard;
|
||||
using Inspectron.Settings.WindowsWizard.Controls;
|
||||
using Microsoft.WindowsAPICodePack.Dialogs;
|
||||
using OpenCvSharp;
|
||||
using OpenCvSharp.Extensions;
|
||||
using System.Windows.Forms;
|
||||
using Hawkeye.VisionBuilder.Features.ImageStatistics;
|
||||
using Size = OpenCvSharp.Size;
|
||||
|
||||
namespace Hawkeye.VisionBuilder
|
||||
{
|
||||
public partial class MainWindow : Form
|
||||
{
|
||||
private readonly WorkflowList _workflowList;
|
||||
private readonly OperationDiscoveryService _discoveryService;
|
||||
private readonly ToolConfigurationPanel _toolConfigurationPanel;
|
||||
private readonly ImagePreviewPanel _previewPanel;
|
||||
private readonly VisionStepsPanel _visionStepsPanel;
|
||||
private ImageStripPanel _imagesStripPanel;
|
||||
public MainWindow(WorkflowList workflowList, OperationDiscoveryService discoveryService)
|
||||
{
|
||||
_workflowList = workflowList;
|
||||
_discoveryService = discoveryService;
|
||||
InitializeComponent();
|
||||
|
||||
|
||||
{
|
||||
_previewPanel = new ImagePreviewPanel();
|
||||
_previewPanel.MdiParent = this;
|
||||
_previewPanel.Show();
|
||||
}
|
||||
{
|
||||
_visionStepsPanel = new VisionStepsPanel(workflowList, discoveryService, _previewPanel);
|
||||
_visionStepsPanel.MdiParent = this;
|
||||
_visionStepsPanel.Show();
|
||||
}
|
||||
{
|
||||
_toolConfigurationPanel = new ToolConfigurationPanel(workflowList, _visionStepsPanel);
|
||||
_toolConfigurationPanel.MdiParent = this;
|
||||
_toolConfigurationPanel.Show();
|
||||
}
|
||||
{
|
||||
ReinitCameraPanel(workflowList);
|
||||
}
|
||||
_visionStepsPanel.OperationSelected += operation =>
|
||||
{
|
||||
_toolConfigurationPanel.SetOperation(operation);
|
||||
|
||||
};
|
||||
|
||||
//var codeEditor = new ScriptEditorPanel();
|
||||
//codeEditor.MdiParent = this;
|
||||
//codeEditor.Show();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void ReinitCameraPanel(WorkflowList workflowList)
|
||||
{
|
||||
if (_imagesStripPanel != null)
|
||||
{
|
||||
_imagesStripPanel.Close();
|
||||
_imagesStripPanel.Dispose();
|
||||
_imagesStripPanel = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
_imagesStripPanel = new ImageStripPanel();
|
||||
|
||||
_workflowList.ImageSource= _imagesStripPanel;
|
||||
|
||||
_imagesStripPanel.ImageSelected += data =>
|
||||
{
|
||||
if (_imagesStripPanel is ImageStripPanel imagesStripPanel)
|
||||
{
|
||||
if (imagesStripPanel.IsExecutingWorkflow)
|
||||
{
|
||||
_visionStepsPanel.ExecuteWorkflow();
|
||||
var result = _visionStepsPanel.WorkflowList.Operations.All(x => x.Result == true);
|
||||
ProcessResult(result);
|
||||
(_imagesStripPanel as ImageStripPanel).InformImageProcessed(result);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_visionStepsPanel.ProcessRowSelection();
|
||||
var selectedOperation = _visionStepsPanel.GetSelectedOperation();
|
||||
if (selectedOperation != null)
|
||||
{
|
||||
ProcessResult(selectedOperation.Result);
|
||||
(_imagesStripPanel as ImageStripPanel).InformImageProcessed(selectedOperation.Result);
|
||||
}
|
||||
|
||||
};
|
||||
if(Directory.Exists(_workflowList.Configuration.EmulationPath))
|
||||
_imagesStripPanel.LoadImages(_workflowList.Configuration.EmulationPath);
|
||||
|
||||
_imagesStripPanel.MdiParent = this;
|
||||
_imagesStripPanel.Show();
|
||||
}
|
||||
|
||||
string _saveErrorDirectory = null;
|
||||
void ProcessResult(bool result)
|
||||
{
|
||||
if (_statisticsDialog != null)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
_statisticsDialog.AddGoodImage((_imagesStripPanel as ImageStripPanel).GetImagePath());
|
||||
}
|
||||
else
|
||||
{
|
||||
_statisticsDialog.AddBadImage((_imagesStripPanel as ImageStripPanel).GetImagePath(), _visionStepsPanel.WorkflowList.Operations.Where(x=>x.Result==false).Select(x=>x.Label).ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
if (!copyOnStopToolStripMenuItem.Checked) return;
|
||||
var shouldSaveOnError = (_imagesStripPanel as ImageStripPanel).StopOnErrors;
|
||||
var shouldSaveOnNoError = (_imagesStripPanel as ImageStripPanel).StopOnNoErrors;
|
||||
if ((!result && shouldSaveOnError) || (result && shouldSaveOnNoError))
|
||||
{
|
||||
var resultFile = Path.Combine(_saveErrorDirectory, Path.GetFileName((_imagesStripPanel as ImageStripPanel).GetImagePath()));
|
||||
if (!File.Exists(resultFile))
|
||||
{
|
||||
File.Copy((_imagesStripPanel as ImageStripPanel).GetImagePath(), Path.Combine(_saveErrorDirectory, Path.GetFileName((_imagesStripPanel as ImageStripPanel).GetImagePath())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected override void OnShown(EventArgs e)
|
||||
{
|
||||
base.OnShown(e);
|
||||
OrganizeWindows(null, null);
|
||||
}
|
||||
|
||||
private void OrganizeWindows(object sender, EventArgs e)
|
||||
{
|
||||
_previewPanel.Left = 0;
|
||||
_previewPanel.Top = 0;
|
||||
_previewPanel.Width = this.ClientSize.Width / 2;
|
||||
_previewPanel.Height = (this.ClientSize.Height - 40) - 30 - _imagesStripPanel.Height;
|
||||
|
||||
_imagesStripPanel.Top = _previewPanel.Height;
|
||||
_imagesStripPanel.Left = 0;
|
||||
_imagesStripPanel.Width = _previewPanel.Width;
|
||||
|
||||
|
||||
_toolConfigurationPanel.Top = 0;
|
||||
_toolConfigurationPanel.Left = this.ClientSize.Width / 2;
|
||||
_toolConfigurationPanel.Width = this.ClientSize.Width / 2 - 10;
|
||||
_toolConfigurationPanel.Height = (this.ClientSize.Height - 40) / 2;
|
||||
|
||||
_visionStepsPanel.Top = (this.ClientSize.Height - 40) / 2;
|
||||
_visionStepsPanel.Left = this.ClientSize.Width / 2;
|
||||
_visionStepsPanel.Width = this.ClientSize.Width / 2 - 10;
|
||||
_visionStepsPanel.Height = (this.ClientSize.Height - 40) / 2 - 30;
|
||||
|
||||
}
|
||||
|
||||
private void loadRecipeToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
OpenFileDialog dialog = new OpenFileDialog();
|
||||
dialog.Filter = "*.hrcp|*.hrcp";
|
||||
PrepareDialog(dialog);
|
||||
|
||||
if (dialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
var path = dialog.FileName;
|
||||
LoadRecipe(path);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void PrepareDialog(FileDialog dialog)
|
||||
{
|
||||
if (_loadedPath != null)
|
||||
{
|
||||
dialog.InitialDirectory = Path.GetDirectoryName(Path.GetFullPath(_loadedPath));
|
||||
dialog.FileName = Path.GetFileNameWithoutExtension(_loadedPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetFullPath(@"..\Data\Recipes"));
|
||||
dialog.InitialDirectory = Path.GetFullPath(@"..\Data\Recipes");
|
||||
}
|
||||
}
|
||||
|
||||
private string _loadedPath = null;
|
||||
|
||||
|
||||
public void LoadRecipe(string path)
|
||||
{
|
||||
_loadedPath = path;
|
||||
var bytes = File.ReadAllBytes(path);
|
||||
MemoryStream stream = new MemoryStream(bytes);
|
||||
BinaryReader reader = new BinaryReader(stream);
|
||||
|
||||
|
||||
_workflowList.PythonMissing += _workflowList_PythonMissing;
|
||||
_workflowList.Load(reader, _discoveryService);
|
||||
ReinitCameraPanel(_workflowList);
|
||||
OrganizeWindows(null, null);
|
||||
_visionStepsPanel.RefreshWorkflow();
|
||||
}
|
||||
|
||||
private void _workflowList_PythonMissing()
|
||||
{
|
||||
SetupConfig();
|
||||
|
||||
}
|
||||
|
||||
private void saveRecipeToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
SaveFileDialog dialog = new SaveFileDialog();
|
||||
dialog.Filter = "*.hrcp|*.hrcp";
|
||||
PrepareDialog(dialog);
|
||||
if (dialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
BinaryWriter bw = new BinaryWriter(ms);
|
||||
|
||||
_workflowList.RecipeImage = _workflowList.Context.LastCameraImage.ImageData;
|
||||
_workflowList.Save(bw);
|
||||
ms.Close();
|
||||
File.WriteAllBytes(dialog.FileName, ms.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
private void toolBtnConfiguration_Click(object sender, EventArgs e)
|
||||
{
|
||||
SetupConfig();
|
||||
ReinitCameraPanel(_workflowList);
|
||||
OrganizeWindows(null, null);
|
||||
}
|
||||
|
||||
private void SetupConfig()
|
||||
{
|
||||
SetupPage.Begin("Camera", "Configuration")
|
||||
.AddItem<EnumEditor>(_workflowList.Configuration, nameof(_workflowList.Configuration.RuntimeCameraType))
|
||||
.AddItem<EnumEditor>(_workflowList.Configuration,
|
||||
nameof(_workflowList.Configuration.DevelopmentCameraType))
|
||||
.AddItem<PathEditor>(_workflowList.Configuration, nameof(_workflowList.Configuration.EmulationPath),
|
||||
editor => editor.FolderPick = true)
|
||||
.Next("Recipe selection")
|
||||
.AddItem<CheckEditor>(_workflowList.Configuration.RecipeSelectionConfig, nameof(RecipeSelectionConfig.SerialEnabled))
|
||||
.AddItem<StringEditor>(_workflowList.Configuration.RecipeSelectionConfig, nameof(RecipeSelectionConfig.ComPort))
|
||||
.Next("Outputs")
|
||||
.AddItem<EnumEditor>(_workflowList.Configuration, nameof(_workflowList.Configuration.Outputs))
|
||||
.AddItem<NumberEditor>(_workflowList.Configuration, nameof(_workflowList.Configuration.ResultPin))
|
||||
.AddItem<StringEditor>(_workflowList.Configuration, nameof(_workflowList.Configuration.SerialPort))
|
||||
.AddItem<NumberEditor>(_workflowList.Configuration, nameof(_workflowList.Configuration.Delay), editor => editor.Max = 1000)
|
||||
.Next("Python")
|
||||
.AddItem<PathEditor>(_workflowList.Configuration, nameof(_workflowList.Configuration.PythonPath),
|
||||
editor => editor.FolderPick = false)
|
||||
.Next("Bad tweak")
|
||||
.AddItem<CheckEditor>(_workflowList.Configuration.BadTweakLearning, nameof(BadTweakLearning.Enabled))
|
||||
.AddItem<NumberEditor>(_workflowList.Configuration.BadTweakLearning, nameof(BadTweakLearning.ThresholdLevel),
|
||||
editor =>
|
||||
{
|
||||
editor.Min = 0;
|
||||
editor.Max = 255;
|
||||
})
|
||||
.Next("Statistics")
|
||||
.ShowSetupDialog();
|
||||
}
|
||||
|
||||
private void generateFromColorProfileToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var tool = new ColorProfileSelection(_workflowList);
|
||||
tool.ShowDialog();
|
||||
_visionStepsPanel.RefreshWorkflow();
|
||||
}
|
||||
|
||||
private void updateAllToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var dialog = new OpenFileDialog();
|
||||
dialog.Filter = "*.colorprofile|*.colorprofile";
|
||||
if (dialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
var path = dialog.FileName;
|
||||
var operations = _workflowList.Operations;
|
||||
foreach (var operation in operations)
|
||||
{
|
||||
if (operation is ColorProfileOperation colorProfileOperation)
|
||||
{
|
||||
colorProfileOperation.ColorProfilePath.Path = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void copyPathToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (_imagesStripPanel is not ImageStripPanel panel) return;
|
||||
var imagePath = panel.GetImagePath();
|
||||
if (imagePath == null) return;
|
||||
Clipboard.SetText(imagePath);
|
||||
}
|
||||
|
||||
private void copyOnErrorToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
FolderBrowserDialog dialog = new FolderBrowserDialog();
|
||||
if (dialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
_saveErrorDirectory = dialog.SelectedPath;
|
||||
return;
|
||||
}
|
||||
copyOnStopToolStripMenuItem.Checked = false;
|
||||
}
|
||||
|
||||
private void generateFromYoloToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
// pick yolo file
|
||||
OpenFileDialog dialog = new OpenFileDialog();
|
||||
dialog.Filter = "*.onnx|*.onnx";
|
||||
dialog.InitialDirectory = Path.GetFullPath(@"..\Data\Models");
|
||||
if (dialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
var path = dialog.FileName;
|
||||
var predictor = YoloV8Predictor.Create(path);
|
||||
var classes = predictor.Metadata.Names;
|
||||
foreach (var cls in classes)
|
||||
{
|
||||
{
|
||||
var operation = new YoloPickDetected();
|
||||
operation.Label = cls.Name;
|
||||
operation.TypeId = cls.Id + 1;
|
||||
_workflowList.Operations.Add(operation);
|
||||
}
|
||||
}
|
||||
_visionStepsPanel.RefreshWorkflow();
|
||||
}
|
||||
}
|
||||
|
||||
private void massSetAttributeToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
AttributeSetter setter = new AttributeSetter(_workflowList);
|
||||
if (setter.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
_visionStepsPanel.RefreshWorkflow();
|
||||
}
|
||||
}
|
||||
|
||||
private string? _saveAsPath = null;
|
||||
|
||||
private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (_imagesStripPanel is not ImageStripPanel panel) return;
|
||||
|
||||
var path = GetSaveAsPath();
|
||||
if (path == null) return;
|
||||
var imagePath = panel.GetImagePath();
|
||||
if (imagePath == null) return;
|
||||
var bytes = File.ReadAllBytes(imagePath);
|
||||
File.WriteAllBytes(Path.Combine(path, Path.GetFileName(imagePath)), bytes);
|
||||
}
|
||||
|
||||
string GetSaveAsPath()
|
||||
{
|
||||
if (_saveAsPath == null)
|
||||
{
|
||||
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
|
||||
dialog.IsFolderPicker = true;
|
||||
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
|
||||
{
|
||||
_saveAsPath = dialog.FileName;
|
||||
}
|
||||
}
|
||||
return _saveAsPath;
|
||||
}
|
||||
|
||||
ImageStatisticsDialog _statisticsDialog = null;
|
||||
private void imageStatisticsToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (_statisticsDialog!=null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_statisticsDialog = new ImageStatisticsDialog();
|
||||
_statisticsDialog.Show(this);
|
||||
_statisticsDialog.FormClosed +=
|
||||
(s, args) =>
|
||||
{
|
||||
_statisticsDialog = null;
|
||||
};
|
||||
_statisticsDialog.FileSelected += _statisticsDialog_FileSelected;
|
||||
}
|
||||
|
||||
private void _statisticsDialog_FileSelected(string file)
|
||||
{
|
||||
(_imagesStripPanel as ImageStripPanel).SelectImage(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user