Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/sn4k3/UVtools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'UVtools.Core/Operations/OperationLayerExportHeatMap.cs')
-rw-r--r--UVtools.Core/Operations/OperationLayerExportHeatMap.cs159
1 files changed, 159 insertions, 0 deletions
diff --git a/UVtools.Core/Operations/OperationLayerExportHeatMap.cs b/UVtools.Core/Operations/OperationLayerExportHeatMap.cs
new file mode 100644
index 0000000..eb6482c
--- /dev/null
+++ b/UVtools.Core/Operations/OperationLayerExportHeatMap.cs
@@ -0,0 +1,159 @@
+/*
+ * GNU AFFERO GENERAL PUBLIC LICENSE
+ * Version 3, 19 November 2007
+ * Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ * Everyone is permitted to copy and distribute verbatim copies
+ * of this license document, but changing it is not allowed.
+ */
+
+using System;
+using System.Text;
+using System.Threading.Tasks;
+using Emgu.CV;
+using Emgu.CV.CvEnum;
+using UVtools.Core.Extensions;
+using UVtools.Core.FileFormats;
+
+namespace UVtools.Core.Operations
+{
+ [Serializable]
+ public sealed class OperationLayerExportHeatMap : Operation
+ {
+ #region Members
+ private string _filePath;
+ private bool _cropByRoi = true;
+
+ #endregion
+
+ #region Overrides
+
+ public override bool CanHaveProfiles => false;
+ public override string Title => "Export layers to heat map";
+
+ public override string Description =>
+ "Export a layer range to a grayscale heat map image that represents the median of the mass in the Z depth/perception\n" +
+ "The pixel brightness/intensity shows where the most mass are concentrated.";
+
+ public override string ConfirmationText =>
+ $"generate a heatmap from layers {LayerIndexStart} through {LayerIndexEnd}?";
+
+ public override string ProgressTitle =>
+ $"Generating a heatmap from layers {LayerIndexStart} through {LayerIndexEnd}";
+
+ public override string ProgressAction => "Packed layers";
+
+ public override string ValidateInternally()
+ {
+ var sb = new StringBuilder();
+
+ if (LayerRangeCount < 2)
+ {
+ sb.AppendLine("To generate a heat map at least two layers are required.");
+ }
+
+ return sb.ToString();
+ }
+
+ public override string ToString()
+ {
+ var result = $"[Crop by ROI: {_cropByRoi}]" +
+ LayerRangeString;
+ if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}";
+ return result;
+ }
+
+ #endregion
+
+ #region Properties
+
+ public string FilePath
+ {
+ get => _filePath;
+ set => RaiseAndSetIfChanged(ref _filePath, value);
+ }
+
+ public bool CropByROI
+ {
+ get => _cropByRoi;
+ set => RaiseAndSetIfChanged(ref _cropByRoi, value);
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public OperationLayerExportHeatMap()
+ { }
+
+ public OperationLayerExportHeatMap(FileFormat slicerFile) : base(slicerFile)
+ {
+ _filePath = SlicerFile.FileFullPath + ".heatmap.png";
+ }
+
+ #endregion
+
+ #region Methods
+
+ protected override bool ExecuteInternally(OperationProgress progress)
+ {
+ using var sumMat32 = EmguExtensions.InitMat(SlicerFile.Resolution, 1, DepthType.Cv32S);
+ var sumMat32Roi = GetRoiOrDefault(sumMat32);
+ using var mask = GetMask(sumMat32);
+
+
+ Parallel.For(LayerIndexStart, LayerIndexEnd+1, layerIndex =>
+ {
+ if (progress.Token.IsCancellationRequested) return;
+
+ using var mat = SlicerFile[layerIndex].LayerMat;
+ using var mat32 = new Mat();
+ mat.ConvertTo(mat32, DepthType.Cv32S);
+ var mat32Roi = GetRoiOrDefault(mat32);
+
+ lock (progress.Mutex)
+ {
+ CvInvoke.Add(sumMat32Roi, mat32Roi, sumMat32Roi, mask);
+ progress++;
+ }
+ });
+
+ if (!progress.Token.IsCancellationRequested)
+ {
+ using var sumMat = EmguExtensions.InitMat(sumMat32.Size);
+ sumMat32.ConvertTo(sumMat, DepthType.Cv8U, 1.0 / LayerRangeCount);
+ if (_cropByRoi && HaveROI)
+ {
+ var sumMatRoi = GetRoiOrDefault(sumMat);
+ sumMatRoi.Save(_filePath);
+ }
+ else
+ {
+ sumMat.Save(_filePath);
+ }
+ }
+
+ return !progress.Token.IsCancellationRequested;
+ }
+
+ #endregion
+
+ #region Equality
+
+ private bool Equals(OperationLayerExportHeatMap other)
+ {
+ return _filePath == other._filePath && _cropByRoi == other._cropByRoi;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return ReferenceEquals(this, obj) || obj is OperationLayerExportHeatMap other && Equals(other);
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(_filePath, _cropByRoi);
+ }
+
+ #endregion
+ }
+}