Improvements on contours classes and add a contour cache to layer

This commit is contained in:
Tiago Conceição
2023-01-06 23:46:18 +00:00
parent 8a0ba6719e
commit 516b87d209
5 changed files with 162 additions and 9 deletions
+12 -6
View File
@@ -35,7 +35,7 @@ public class EmguContour : IReadOnlyCollection<Point>, IDisposable, IComparable<
#region Members
private VectorOfPoint _points = null!;
private VectorOfPoint _points;
private Rectangle? _bounds;
private RotatedRect? _boundsBestFit;
private CircleF? _minEnclosingCircle;
@@ -106,7 +106,7 @@ public class EmguContour : IReadOnlyCollection<Point>, IDisposable, IComparable<
(int)Math.Round(Moments.M01 / Moments.M00));
/// <summary>
/// Gets or sets the contour <see cref="Point"/>
/// Gets or sets the contour points
/// </summary>
public VectorOfPoint Points
{
@@ -224,7 +224,7 @@ public class EmguContour : IReadOnlyCollection<Point>, IDisposable, IComparable<
#region Static methods
public static Point GetCentroid(VectorOfPoint points)
{
if (points is null || points.Length == 0) return EmguExtensions.AnchorCenter;
if (points.Length == 0) return EmguExtensions.AnchorCenter;
using var moments = CvInvoke.Moments(points);
return moments.M00 == 0 ? EmguExtensions.AnchorCenter :
new Point(
@@ -235,6 +235,13 @@ public class EmguContour : IReadOnlyCollection<Point>, IDisposable, IComparable<
#region Implementations
public EmguContour Clone()
{
var clone = (EmguContour)MemberwiseClone();
clone._points = new VectorOfPoint(_points.ToArray());
return clone;
}
public IEnumerator<Point> GetEnumerator()
{
return (IEnumerator<Point>) _points.ToArray().GetEnumerator();
@@ -254,8 +261,9 @@ public class EmguContour : IReadOnlyCollection<Point>, IDisposable, IComparable<
public void Dispose()
{
_points?.Dispose();
_points.Dispose();
_moments?.Dispose();
_moments = null;
}
#endregion
@@ -295,6 +303,4 @@ public class EmguContour : IReadOnlyCollection<Point>, IDisposable, IComparable<
return x._area.CompareTo(y._area);
}
#endregion
}
+46 -2
View File
@@ -44,6 +44,21 @@ public class EmguContours : IReadOnlyList<EmguContour>, IDisposable
public EmguContour this[int index] => _contours[index];
private EmguContours(int count, int[,] hierarchy)
{
_contours = new EmguContour[count];
Hierarchy = hierarchy;
}
public EmguContours(Point[][] points)
{
_contours = new EmguContour[points.Length];
for (int i = 0; i < points.Length; i++)
{
_contours[i] = new EmguContour(points[i]);
}
}
public EmguContours(VectorOfVectorOfPoint vectorOfPointsOfPoints)
{
_contours = new EmguContour[vectorOfPointsOfPoints.Size];
@@ -53,6 +68,11 @@ public class EmguContours : IReadOnlyList<EmguContour>, IDisposable
}
}
public EmguContours(Point[][] points, int[,] hierarchy) : this(points)
{
Hierarchy = hierarchy;
}
public EmguContours(VectorOfVectorOfPoint vectorOfPointsOfPoints, int[,] hierarchy) : this(vectorOfPointsOfPoints)
{
Hierarchy = hierarchy;
@@ -96,6 +116,18 @@ public class EmguContours : IReadOnlyList<EmguContour>, IDisposable
return items;
}
public EmguContours Clone()
{
var clone = new EmguContours(_contours.Length, Hierarchy);
for (int i = 0; i < _contours.Length; i++)
{
clone._contours[i] = this[i].Clone();
}
return clone;
}
public void Dispose()
{
foreach (var contour in _contours)
@@ -104,6 +136,17 @@ public class EmguContours : IReadOnlyList<EmguContour>, IDisposable
}
}
/// <summary>
/// Gets contours inside a point
/// </summary>
@@ -331,10 +374,11 @@ public class EmguContours : IReadOnlyList<EmguContour>, IDisposable
{
var contour1Rect = CvInvoke.BoundingRectangle(contour1[0]);
var contour2Rect = CvInvoke.BoundingRectangle(contour2[0]);
/* early exit if the bounding rectangles don't intersect */
if (!contour1Rect.IntersectsWith(contour2Rect)) return 0;
var totalRect = Rectangle.Union(contour1Rect, contour2Rect);
//var totalRect = Rectangle.Union(contour1Rect, contour2Rect);
var totalRect = RectangleExtensions.SmallestRectangle(contour1Rect, contour2Rect);
using var contour1Mat = EmguExtensions.InitMat(totalRect.Size);
using var contour2Mat = EmguExtensions.InitMat(totalRect.Size);
@@ -6,6 +6,7 @@
* of this license document, but changing it is not allowed.
*/
using System.Drawing;
using System.Linq;
namespace UVtools.Core.Extensions;
@@ -25,4 +26,32 @@ public static class RectangleExtensions
public static Rectangle OffsetBy(this Rectangle src, Point position) => src.OffsetBy(position.X, position.Y);
/// <summary>
/// Gets the smallest rectangle among all rectangles
/// </summary>
/// <param name="rectangles"></param>
/// <returns>The smallest rectangle</returns>
public static Rectangle SmallestRectangle(params Rectangle[] rectangles) => rectangles.MinBy(rectangle => rectangle.Area());
/// <summary>
/// Gets the smallest rectangle among all rectangles
/// </summary>
/// <param name="rectangles"></param>
/// <returns>The smallest rectangle</returns>
public static RectangleF SmallestRectangle(params RectangleF[] rectangles) => rectangles.MinBy(rectangle => rectangle.Area());
/// <summary>
/// Gets the largest rectangle among all rectangles
/// </summary>
/// <param name="rectangles"></param>
/// <returns>The largest rectangle</returns>
public static Rectangle LargestRectangle(params Rectangle[] rectangles) => rectangles.MaxBy(rectangle => rectangle.Area());
/// <summary>
/// Gets the largest rectangle among all rectangles
/// </summary>
/// <param name="rectangles"></param>
/// <returns>The largest rectangle</returns>
public static RectangleF LargestRectangle(params RectangleF[] rectangles) => rectangles.MaxBy(rectangle => rectangle.Area());
}
+31
View File
@@ -83,6 +83,8 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
private byte _lightPWM = FileFormat.DefaultLightPWM;
private float _materialMilliliters;
private EmguContours? _contours;
#endregion
#region Properties
@@ -794,6 +796,8 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
_compressedBytes = value;
IsModified = true;
SlicerFile.BoundingRectangle = Rectangle.Empty;
_contours?.Dispose();
_contours = null;
RaisePropertyChanged();
RaisePropertyChanged(nameof(HaveImage));
}
@@ -1027,6 +1031,31 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
/// </summary>
public bool IsUsingTSMC => LiftHeight2 > 0 || RetractHeight2 > 0;
/// <summary>
/// Gets tree contours cache for this layer, however should call <see cref="GetContours"/> instead with <see cref="LayerMat"/> instance
/// </summary>
public EmguContours Contours
{
get
{
if (_contours is null)
{
using var mat = LayerMat;
_contours = new EmguContours(mat);
}
return _contours;
}
}
/// <summary>
/// Gets tree contours cache for this layer
/// </summary>
public EmguContours GetContours(IInputOutputArray mat)
{
return _contours ??= new EmguContours(mat);
}
#endregion
#region Constructor
@@ -1694,6 +1723,7 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
layer.ResolutionX = _resolutionX;
layer.ResolutionY = _resolutionY;
layer.CompressedBytes = _compressedBytes?.ToArray();
layer._contours = _contours?.Clone();
layer.BoundingRectangle = _boundingRectangle;
layer.NonZeroPixelCount = _nonZeroPixelCount;
}
@@ -1702,6 +1732,7 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
{
var layer = (Layer)MemberwiseClone();
layer._compressedBytes = _compressedBytes?.ToArray();
layer._contours = _contours?.Clone();
//Debug.WriteLine(ReferenceEquals(_compressedBytes, layer.CompressedBytes));
return layer;
/*return new (_index, CompressedBytes?.ToArray()!, SlicerFile)