From c1c58fa336b1cc68e19276398239f5873b96681d Mon Sep 17 00:00:00 2001 From: popow Date: Tue, 24 Jul 2018 19:51:01 +0200 Subject: [PATCH] using memory allocator to create the histogram and the cdf --- .../AdaptiveHistEqualizationProcessor.cs | 59 +++++++++---------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs index 3df1877339..61ee6aea45 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Collections.Generic; using System.Numerics; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; @@ -36,27 +35,29 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization Span pixels = source.GetPixelSpan(); int gridSize = 64; + int pixelsInGrid = gridSize * gridSize; int contrastLimit = 5; int halfGridSize = gridSize / 2; - int[] histogram = new int[this.LuminanceLevels]; - int[] histogramCopy = new int[this.LuminanceLevels]; - int[] cdf = new int[this.LuminanceLevels]; + using (IBuffer histogramBuffer = memoryAllocator.AllocateClean(this.LuminanceLevels)) + using (IBuffer histogramBufferCopy = memoryAllocator.AllocateClean(this.LuminanceLevels)) + using (IBuffer cdfBuffer = memoryAllocator.AllocateClean(this.LuminanceLevels)) using (Buffer2D targetPixels = configuration.MemoryAllocator.Allocate2D(source.Width, source.Height)) { + Span histogram = histogramBuffer.GetSpan(); + Span histogramCopy = histogramBufferCopy.GetSpan(); + Span cdf = cdfBuffer.GetSpan(); + for (int x = halfGridSize; x < source.Width - halfGridSize; x++) { - this.CleanArray(histogram); - this.CleanArray(cdf); + histogram.Clear(); - var pixelsGrid = new List(); + // Build the histogram of grayscale values for the current grid. for (int dy = 0; dy < gridSize; dy++) { Span rowSpan = source.GetPixelRowSpan(dy).Slice(start: x - halfGridSize, length: gridSize); - pixelsGrid.AddRange(rowSpan.ToArray()); + this.AddPixelsTooHistogram(rowSpan, histogram, this.LuminanceLevels); } - this.CalcHistogram(pixelsGrid, histogram, this.LuminanceLevels); - for (int y = halfGridSize + 1; y < source.Height - halfGridSize; y++) { // Remove top most row from the histogram @@ -68,17 +69,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization this.AddPixelsTooHistogram(rowSpan, histogram, this.LuminanceLevels); // Clipping the histogram, but doing it on a copy to keep the original un-clipped values - histogram.AsSpan().CopyTo(histogramCopy); + histogram.CopyTo(histogramCopy); this.ClipHistogram(histogramCopy, gridSize, contrastLimit); + cdf.Clear(); int cdfMin = this.CalculateCdf(cdf, histogramCopy); - double numberOfPixelsMinusCdfMin = (double)(pixelsGrid.Count - cdfMin); + double numberOfPixelsMinusCdfMin = (double)(pixelsInGrid - cdfMin); // Map the current pixel to the new equalized value int luminance = this.GetLuminance(pixels[(y * source.Width) + x], this.LuminanceLevels); double luminanceEqualized = cdf[luminance] / numberOfPixelsMinusCdfMin; targetPixels[x, y].PackFromVector4(new Vector4((float)luminanceEqualized)); - - this.CleanArray(cdf); } } @@ -88,7 +88,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// /// AHE tends to over amplify the contrast in near-constant regions of the image, since the histogram in such regions is highly concentrated. - /// Clipping the histogram is meant to reduce this effect, by cutting of histogram bin's which exceed a certain amount and redistribute + /// Clipping the histogram is meant to reduce this effect, by cutting of histogram bin's which exceed a certain amount and redistribute /// the values over the clip limit to all other bins equally. /// /// The histogram to apply the clipping @@ -125,6 +125,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization return addToEachBin; } + /// + /// Adds a row of grey values to the histogram. + /// + /// The grey values to add + /// The histogram + /// The number of different luminance levels. private void AddPixelsTooHistogram(Span greyValues, Span histogram, int luminanceLevels) { for (int i = 0; i < greyValues.Length; i++) @@ -134,6 +140,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization } } + /// + /// Removes a row of grey values from the histogram. + /// + /// The grey values to remove + /// The histogram + /// The number of different luminance levels. private void RemovePixelsFromHistogram(Span greyValues, Span histogram, int luminanceLevels) { for (int i = 0; i < greyValues.Length; i++) @@ -142,22 +154,5 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization histogram[luminance]--; } } - - private void CalcHistogram(List greyValues, Span histogram, int luminanceLevels) - { - for (int i = 0; i < greyValues.Count; i++) - { - int luminance = this.GetLuminance(greyValues[i], luminanceLevels); - histogram[luminance]++; - } - } - - private void CleanArray(Span array) - { - for (int i = 0; i < array.Length; i++) - { - array[i] = 0; - } - } } }