From 1eb4e2409abbcffdab96b5e896cf71850ab13a01 Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Tue, 2 Apr 2019 11:58:55 +0300 Subject: Working on color capture module... --- .../Controls/IndexedUniformGrid.cs | 12 +- .../Graph/WpfGraphController.cs | 2 +- .../Models/BenchmarkItem.cs | 95 ++++ .../Models/CaptureItem.cs | 17 + .../Tango.MachineStudio.ColorCapture.csproj | 6 + .../Themes/Generic.xaml | 8 +- .../ViewModels/MainViewVM.cs | 103 ++++- .../Views/MainView.xaml | 497 ++++++++++++++------- 8 files changed, 561 insertions(+), 179 deletions(-) create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Models/BenchmarkItem.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Models/CaptureItem.cs (limited to 'Software/Visual_Studio/MachineStudio') diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Controls/IndexedUniformGrid.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Controls/IndexedUniformGrid.cs index af34e038d..93a5c07ab 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Controls/IndexedUniformGrid.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Controls/IndexedUniformGrid.cs @@ -16,7 +16,7 @@ namespace Tango.MachineStudio.ColorCapture.Controls set { SetValue(ColumnsProperty, value); } } public static readonly DependencyProperty ColumnsProperty = - DependencyProperty.Register("Columns", typeof(int), typeof(IndexedUniformGrid), new PropertyMetadata(0)); + DependencyProperty.Register("Columns", typeof(int), typeof(IndexedUniformGrid), new PropertyMetadata(0, (d, e) => (d as IndexedUniformGrid).Init())); public int Rows { @@ -24,7 +24,7 @@ namespace Tango.MachineStudio.ColorCapture.Controls set { SetValue(RowsProperty, value); } } public static readonly DependencyProperty RowsProperty = - DependencyProperty.Register("Rows", typeof(int), typeof(IndexedUniformGrid), new PropertyMetadata(0)); + DependencyProperty.Register("Rows", typeof(int), typeof(IndexedUniformGrid), new PropertyMetadata(0, (d, e) => (d as IndexedUniformGrid).Init())); public IndexedUniformGrid() { @@ -33,6 +33,14 @@ namespace Tango.MachineStudio.ColorCapture.Controls private void IndexedUniformGrid_Loaded(object sender, RoutedEventArgs e) { + Init(); + } + + private void Init() + { + ColumnDefinitions.Clear(); + RowDefinitions.Clear(); + for (int i = 0; i < Columns; i++) { ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) }); diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Graph/WpfGraphController.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Graph/WpfGraphController.cs index dd32cde93..63ce7035e 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Graph/WpfGraphController.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Graph/WpfGraphController.cs @@ -19,7 +19,7 @@ namespace Tango.MachineStudio.ColorCapture.Graph AddDataSeries(new WpfDataSeries() { StrokeThickness = 1, - Stroke = Colors.Black, + Stroke = Colors.DodgerBlue, }); var renderer = new GraphScrollingRenderer() diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Models/BenchmarkItem.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Models/BenchmarkItem.cs new file mode 100644 index 000000000..d7d33e437 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Models/BenchmarkItem.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media; +using Tango.Core; +using Tango.PMR.TCC; + +namespace Tango.MachineStudio.ColorCapture.Models +{ + public class BenchmarkItem : ExtendedObject + { + private int _Red; + public int Red + { + get { return _Red; } + set { _Red = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(Color)); } + } + + private int _Green; + public int Green + { + get { return _Green; } + set { _Green = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(Color)); } + } + + private int _Blue; + public int Blue + { + get { return _Blue; } + set { _Blue = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(Color)); } + } + + private double _L; + public double L + { + get { return _L; } + set { _L = value; RaisePropertyChangedAuto(); } + } + + private double _A; + public double A + { + get { return _A; } + set { _A = value; RaisePropertyChangedAuto(); } + } + + private double _B; + public double B + { + get { return _B; } + set { _B = value; RaisePropertyChangedAuto(); } + } + + public int Index { get; private set; } + + public Color Color + { + get { return Color.FromArgb(255, (byte)Red, (byte)Green, (byte)Blue); } + } + + public static BenchmarkItem FromDetectionBenchmark(DetectionBenchmark benchmark, int index) + { + BenchmarkItem item = new BenchmarkItem(); + + item.Red = benchmark.Red; + item.Green = benchmark.Green; + item.Blue = benchmark.Blue; + + item.L = benchmark.L; + item.A = benchmark.A; + item.B = benchmark.B; + + item.Index = index; + + return item; + } + + public DetectionBenchmark ToDetectionBenchmark() + { + DetectionBenchmark item = new DetectionBenchmark(); + + item.Red = Red; + item.Green = Green; + item.Blue = Blue; + + item.L = L; + item.A = A; + item.B = B; + + return item; + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Models/CaptureItem.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Models/CaptureItem.cs new file mode 100644 index 000000000..f997783ca --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Models/CaptureItem.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media; + +namespace Tango.MachineStudio.ColorCapture.Models +{ + public class CaptureItem + { + public DateTime Time { get; set; } + public Color CapturedColor { get; set; } + public Color ProcessedColor { get; set; } + public double DeltaE { get; set; } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Tango.MachineStudio.ColorCapture.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Tango.MachineStudio.ColorCapture.csproj index 4d0c0fae5..6bfe0938f 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Tango.MachineStudio.ColorCapture.csproj +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Tango.MachineStudio.ColorCapture.csproj @@ -91,6 +91,8 @@ + + Code @@ -140,6 +142,10 @@ {a34ee0f0-649d-41c8-8489-b6f1cc6924ee} Tango.Core + + {58e8825f-0c96-449c-b320-1e82b0aa876b} + Tango.CSV + {e4927038-348d-4295-aaf4-861c58cb3943} Tango.PMR diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Themes/Generic.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Themes/Generic.xaml index 0a2ebbca8..87a3f1bf2 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Themes/Generic.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Themes/Generic.xaml @@ -30,10 +30,10 @@ - - - - + + + + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/ViewModels/MainViewVM.cs index f21c403de..855d9c0c3 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/ViewModels/MainViewVM.cs @@ -1,5 +1,6 @@ using ColorMine.ColorSpaces; using ColorMine.ColorSpaces.Comparisons; +using Microsoft.Win32; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -9,11 +10,15 @@ using System.Text; using System.Threading.Tasks; using System.Windows.Media; using System.Windows.Media.Imaging; +using Tango.Core; using Tango.Core.Commands; +using Tango.CSV; using Tango.MachineStudio.ColorCapture.Graph; +using Tango.MachineStudio.ColorCapture.Models; using Tango.MachineStudio.Common; using Tango.MachineStudio.Common.Notifications; using Tango.MachineStudio.Common.Video; +using Tango.PMR.TCC; using Tango.TCC.BL; using Tango.Video.DirectCapture; @@ -24,6 +29,7 @@ namespace Tango.MachineStudio.ColorCapture.ViewModels private INotificationProvider _notification; private CardDetector _cardDetector; private int _sampleCounter; + private bool _abort; public IVideoCaptureProvider VideoProvider { get; set; } @@ -89,18 +95,83 @@ namespace Tango.MachineStudio.ColorCapture.ViewModels set { _measureB = value; RaisePropertyChangedAuto(); } } - public WpfGraphController CaptureDeltaEController { get; set; } public RelayCommand ToggleCameraCommand { get; set; } + public SynchronizedObservableCollection CaptureItems { get; set; } + + private ObservableCollection _benchmarks; + public ObservableCollection Benchmarks + { + get { return _benchmarks; } + set { _benchmarks = value; RaisePropertyChangedAuto(); } + } + + public RelayCommand ImportBenchmarksCommand { get; set; } + + public RelayCommand ExportBenchmarksCommand { get; set; } + public MainViewVM() { + CaptureItems = new SynchronizedObservableCollection(); + Benchmarks = new ObservableCollection(); _cardDetector = new CardDetector(); ToggleCameraCommand = new RelayCommand(ToggleCamera); CaptureDeltaEController = new WpfGraphController(); CaptureDeltaEController.Range.AutoY = true; CaptureDeltaEController.Range.MaximumX = 1000; + + ImportBenchmarksCommand = new RelayCommand(OpenBenchmarksFile); + ExportBenchmarksCommand = new RelayCommand(SaveBenchmarksFile); + } + + private void SaveBenchmarksFile() + { + SaveFileDialog dlg = new SaveFileDialog(); + dlg.Filter = "CSV Files|*.csv"; + if (dlg.ShowDialog().Value) + { + try + { + ExportBenchmarks(dlg.FileName); + _notification.ShowInfo("Benchmarks successfully saved."); + } + catch (Exception ex) + { + _notification.ShowError($"An error occurred while trying to export the benchmark file.\n{ex.FlattenMessage()}"); + } + } + } + + private void OpenBenchmarksFile() + { + OpenFileDialog dlg = new OpenFileDialog(); + dlg.Filter = "CSV Files|*.csv"; + if (dlg.ShowDialog().Value) + { + try + { + ImportBenchmarks(dlg.FileName); + _notification.ShowInfo("Benchmarks successfully loaded."); + } + catch (Exception ex) + { + _notification.ShowError($"An error occurred while trying to import the benchmark file.\n{ex.FlattenMessage()}"); + } + } + } + + private void ExportBenchmarks(String file) + { + ColorDetector.SaveBenchmarks(file, Benchmarks.ToList().Select(x => x.ToDetectionBenchmark())); + } + + private void ImportBenchmarks(String file) + { + var marks = ColorDetector.LoadBenchmarks(file).ToList(); + var benchmarks = marks.Select(x => BenchmarkItem.FromDetectionBenchmark(x,marks.IndexOf(x))).ToList(); + Benchmarks = new ObservableCollection(benchmarks); } public MainViewVM(IVideoCaptureProvider videoProvider, INotificationProvider notificationProvider) : this() @@ -116,10 +187,17 @@ namespace Tango.MachineStudio.ColorCapture.ViewModels { if (SelectedVideoDevice.IsStarted) { + _abort = true; SelectedVideoDevice.Stop(); + ProcessedColor = System.Windows.Media.Colors.Transparent; + CapturedColor = System.Windows.Media.Colors.Transparent; + Colors = null; + DetectedSource = null; + CaptureDeltaEController.Clear(); } else { + _abort = false; SelectedVideoDevice.Resolution = new Resolution(1280, 720); SelectedVideoDevice.Start(); } @@ -143,9 +221,14 @@ namespace Tango.MachineStudio.ColorCapture.ViewModels double deltaE = 0; private async void OnVideoFrameReceived(object sender, Video.DirectShow.EventArguments.FrameReceivedEventArgs args) { + if (_abort) return; + if (_cardDetector.CanDetect) { - var result = await _cardDetector.Detect(args.BitmapSource); + var result = await _cardDetector.Detect(args.BitmapSource, new CardDetectionConfig() + { + Benchmarks = Benchmarks.ToList().Select(x => x.ToDetectionBenchmark()).ToList(), + }); if (result.IsDetected) { @@ -166,11 +249,19 @@ namespace Tango.MachineStudio.ColorCapture.ViewModels CapturedColor = Color.FromArgb(255, (byte)result.ColorDetectionOutput.RawColor.R, (byte)result.ColorDetectionOutput.RawColor.G, (byte)result.ColorDetectionOutput.RawColor.B); ProcessedColor = Color.FromArgb(255, (byte)result.ColorDetectionOutput.ProcessedColor.R, (byte)result.ColorDetectionOutput.ProcessedColor.G, (byte)result.ColorDetectionOutput.ProcessedColor.B); - }); - //calculate delta E. - Lab measureLab = new Lab(MeasureL, MeasureA, MeasureB); - deltaE = measureLab.Compare(new Rgb(ProcessedColor.R, ProcessedColor.G, ProcessedColor.B), new CieDe2000Comparison()); + //calculate delta E. + Lab measureLab = new Lab(MeasureL, MeasureA, MeasureB); + deltaE = measureLab.Compare(new Rgb(ProcessedColor.R, ProcessedColor.G, ProcessedColor.B), new CieDe2000Comparison()); + + CaptureItems.Insert(0, new CaptureItem() + { + CapturedColor = CapturedColor, + ProcessedColor = ProcessedColor, + DeltaE = deltaE, + Time = DateTime.Now, + }); + }); } } diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Views/MainView.xaml index 259e3160e..54231dfde 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Views/MainView.xaml @@ -14,186 +14,351 @@ xmlns:global="clr-namespace:Tango.MachineStudio.ColorCapture" xmlns:local="clr-namespace:Tango.MachineStudio.ColorCapture.Views" mc:Ignorable="d" - d:DesignHeight="1080" d:DesignWidth="1920" Background="Transparent" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}"> + d:DesignHeight="1080" d:DesignWidth="1920" Background="#202020" Foreground="#BBBBBB" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}"> + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + - - - Capture Device - - - - - - - - - - + + + + + + + + + + + + + + + Capture Device + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - Captured Color - - - - - - - - - - + Rectified Image + + - - - - - - Processed Color - - - - - - - - - - + Calculated Averages + + - - - - - - - - - - - - - - - HISTORY - - - - - - - - - - - - - Delta E Reference Point - - L: - - - A: - - - B: - - - - - - - + + + - - + + - - - - - + + + Captured Color + + + + + + + + + + + + + + + + - + + + Processed Color + + + + + + + + + + + + + + + + - - - + + Delta E Reference Point + + + L: + + + + + A: + + + + + B: + + + + - + + + + + + + + + + + Measures + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Delta E Distance + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.3.1