From b7d5eda17ed12032e07fa9cd18b30a516bbd8506 Mon Sep 17 00:00:00 2001 From: LarsBrubaker Date: Mon, 18 Jun 2018 09:07:48 -0700 Subject: [PATCH] Working on putting a histogram into ImageToPath --- .../Image/AlphaThresholdFunction.cs | 7 ++- .../Operations/Image/IThresholdFunction.cs | 7 +++ DesignTools/Operations/Image/ImageToPath.cs | 56 +++++++++++++++++-- .../Operations/Image/MapOnMaxIntensity.cs | 15 +++-- DesignTools/PublicPropertyEditor.cs | 13 ++++- Submodules/agg-sharp | 2 +- 6 files changed, 87 insertions(+), 13 deletions(-) diff --git a/DesignTools/Operations/Image/AlphaThresholdFunction.cs b/DesignTools/Operations/Image/AlphaThresholdFunction.cs index 24ffca984..381c2b561 100644 --- a/DesignTools/Operations/Image/AlphaThresholdFunction.cs +++ b/DesignTools/Operations/Image/AlphaThresholdFunction.cs @@ -47,9 +47,14 @@ namespace MatterHackers.MatterControl.DesignTools this.end0To255 = end; } + public int ThresholdSpace0to255(Color color) + { + return color.Alpha0To255; + } + public double Threshold0To1(Color color) { - return GetThresholded0To1(color.Alpha0To255); + return GetThresholded0To1(ThresholdSpace0to255(color)); } protected double GetThresholded0To1(int inValue0To255) diff --git a/DesignTools/Operations/Image/IThresholdFunction.cs b/DesignTools/Operations/Image/IThresholdFunction.cs index c465aaec8..4e93c9126 100644 --- a/DesignTools/Operations/Image/IThresholdFunction.cs +++ b/DesignTools/Operations/Image/IThresholdFunction.cs @@ -33,6 +33,13 @@ namespace MatterHackers.MatterControl.DesignTools { public interface IThresholdFunction { + /// + /// Convert the color into the intensity space used by the threshold function + /// + /// + /// + int ThresholdSpace0to255(Color color); + double Threshold0To1(Color color); } } \ No newline at end of file diff --git a/DesignTools/Operations/Image/ImageToPath.cs b/DesignTools/Operations/Image/ImageToPath.cs index 81c7eb419..990ab265e 100644 --- a/DesignTools/Operations/Image/ImageToPath.cs +++ b/DesignTools/Operations/Image/ImageToPath.cs @@ -63,8 +63,52 @@ namespace MatterHackers.MatterControl.DesignTools public override bool CanRemove => true; public ThresholdFunctions FeatureDetector { get; set; } = ThresholdFunctions.Intensity; - public int EndThreshold { get; internal set; } = 255; - public int StartThreshold { get; internal set; } = 120; + + ImageBuffer _histogramCache = null; + [JsonIgnore] + public ImageBuffer Histogram + { + get + { + _histogramCache = null; + if (_histogramCache == null) + { + _histogramCache = new ImageBuffer(256, 100); + var image = Image; + var counts = new int[256]; + var function = ThresholdFunction; + for (int y=0; y< image.Height; y++) + { + for(int x=0; x< image.Width; x++) + { + var color = image.GetPixel(x, y); + counts[(int)(function.ThresholdSpace0to255(color))]++; + } + } + double max = counts.Select((value, index) => new { value, index }) + .OrderByDescending(vi => vi.value) + .First().value; + var graphics2D = _histogramCache.NewGraphics2D(); + graphics2D.Clear(Color.White); + for(int i=0; i<256; i++) + { + graphics2D.Line(i, 0, i, Easing.Exponential.Out(counts[i] / max) * _histogramCache.Height, Color.Black); + } + graphics2D.FillRectangle(0, 0, ClampLessTo0, _histogramCache.Height, new Color(Color.LightGray, 100)); + graphics2D.FillRectangle(ClampMoreTo255, 0, 255, _histogramCache.Height, new Color(Color.LightGray, 100)); + graphics2D.Line(ClampLessTo0, 0, ClampLessTo0, _histogramCache.Height, new Color(Color.LightGray, 200)); + graphics2D.Line(ClampMoreTo255, 0, ClampMoreTo255, _histogramCache.Height, new Color(Color.LightGray, 200)); + } + return _histogramCache; + } + + set + { + } + } + + public int ClampLessTo0 { get; set; } = 120; + public int ClampMoreTo255 { get; set; } = 255; public IVertexSource VertexSource { get; set; } = new VertexStorage(); @@ -78,16 +122,16 @@ namespace MatterHackers.MatterControl.DesignTools switch (FeatureDetector) { case ThresholdFunctions.Intensity: - return new MapOnMaxIntensity(StartThreshold, EndThreshold); + return new MapOnMaxIntensity(ClampLessTo0, ClampMoreTo255); case ThresholdFunctions.Alpha: - return new AlphaThresholdFunction(StartThreshold, EndThreshold); + return new AlphaThresholdFunction(ClampLessTo0, ClampMoreTo255); case ThresholdFunctions.Hue: break; } - return new MapOnMaxIntensity(StartThreshold, EndThreshold); + return new MapOnMaxIntensity(ClampLessTo0, ClampMoreTo255); } } @@ -224,7 +268,7 @@ namespace MatterHackers.MatterControl.DesignTools // now create a long running task to process the image ApplicationController.Instance.Tasks.Execute( - "Extrude Image".Localize(), + "Calculate Path".Localize(), (reporter, cancellationToken) => { var progressStatus = new ProgressStatus(); diff --git a/DesignTools/Operations/Image/MapOnMaxIntensity.cs b/DesignTools/Operations/Image/MapOnMaxIntensity.cs index 1b6cc28a2..b31337196 100644 --- a/DesignTools/Operations/Image/MapOnMaxIntensity.cs +++ b/DesignTools/Operations/Image/MapOnMaxIntensity.cs @@ -47,13 +47,20 @@ namespace MatterHackers.MatterControl.DesignTools this.end0To255 = end; } + public int ThresholdSpace0to255(Color color) + { + var simpleIntensity = (color.red + color.blue + color.green) / 3; + if(simpleIntensity > 0) + { + int a = 0; + } + return simpleIntensity; + } + public double Threshold0To1(Color color) { // this is on I from HSI - return GetThresholded0To1((color.red + color.blue + color.green) / 3); - - // this is on L from HSL - //return GetThresholded0To1(Math.Max(color.red, Math.Max(color.blue, color.green))); + return GetThresholded0To1(ThresholdSpace0to255(color)); } protected double GetThresholded0To1(int inValue0To255) diff --git a/DesignTools/PublicPropertyEditor.cs b/DesignTools/PublicPropertyEditor.cs index d6997237c..4c46687d0 100644 --- a/DesignTools/PublicPropertyEditor.cs +++ b/DesignTools/PublicPropertyEditor.cs @@ -103,7 +103,8 @@ namespace MatterHackers.MatterControl.DesignTools typeof(double), typeof(int), typeof(char), typeof(string), typeof(bool), typeof(Vector2), typeof(Vector3), typeof(DirectionVector), typeof(DirectionAxis), - typeof(ChildrenSelector) + typeof(ChildrenSelector), + typeof(ImageBuffer), }; public const BindingFlags OwnedPropertiesOnly = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly; @@ -335,6 +336,11 @@ namespace MatterHackers.MatterControl.DesignTools rowContainer = CreateSettingsColumn(property); rowContainer.AddChild(CreateSelector(childSelector, property.Item, theme)); } + else if (propertyValue is ImageBuffer imageBuffer) + { + rowContainer = CreateSettingsColumn(property); + rowContainer.AddChild(CreateImageDisplay(imageBuffer, property.Item, theme)); + } // create a int editor else if (propertyValue is int intValue) { @@ -435,6 +441,11 @@ namespace MatterHackers.MatterControl.DesignTools return rowContainer; } + private static GuiWidget CreateImageDisplay(ImageBuffer imageBuffer, IObject3D parent, ThemeConfig theme) + { + return new ImageWidget(imageBuffer); + } + private static GuiWidget CreateSelector(ChildrenSelector childSelector, IObject3D parent, ThemeConfig theme) { GuiWidget tabContainer = new FlowLayoutWidget(FlowDirection.TopToBottom); diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index 70cc8c1cb..faae4c67d 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit 70cc8c1cbcfd70a642299d409fc1433aa47dd8b8 +Subproject commit faae4c67d968ae8816a4035550092deaa3b53610