Browse Source

using Parallel.For

pull/673/head
popow 8 years ago
parent
commit
f04ac406e3
  1. 90
      src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs

90
src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
@ -28,6 +29,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
public AdaptiveHistEqualizationProcessor(int gridSize, int clipLimit, int luminanceLevels)
: base(luminanceLevels)
{
Guard.MustBeGreaterThan(gridSize, 8, nameof(gridSize));
Guard.MustBeGreaterThan(clipLimit, 1, nameof(clipLimit));
this.GridSize = gridSize;
this.ClipLimit = clipLimit;
}
@ -51,49 +55,55 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
int pixelsInGrid = this.GridSize * this.GridSize;
int halfGridSize = this.GridSize / 2;
using (IBuffer<int> histogramBuffer = memoryAllocator.AllocateClean<int>(this.LuminanceLevels))
using (IBuffer<int> histogramBufferCopy = memoryAllocator.AllocateClean<int>(this.LuminanceLevels))
using (IBuffer<int> cdfBuffer = memoryAllocator.AllocateClean<int>(this.LuminanceLevels))
using (Buffer2D<TPixel> targetPixels = configuration.MemoryAllocator.Allocate2D<TPixel>(source.Width, source.Height))
{
Span<int> histogram = histogramBuffer.GetSpan();
Span<int> histogramCopy = histogramBufferCopy.GetSpan();
Span<int> cdf = cdfBuffer.GetSpan();
for (int x = 0; x < source.Width; x++)
{
histogram.Clear();
// Build the histogram of grayscale values for the current grid.
for (int dy = -halfGridSize; dy < halfGridSize; dy++)
Parallel.For(
0,
source.Width,
configuration.ParallelOptions,
x =>
{
Span<TPixel> rowSpan = this.GetPixelRow(source, x - halfGridSize, dy, this.GridSize);
this.AddPixelsTooHistogram(rowSpan, histogram, this.LuminanceLevels);
}
for (int y = 0; y < source.Height; y++)
{
// Clipping the histogram, but doing it on a copy to keep the original un-clipped values for the next iteration
histogram.CopyTo(histogramCopy);
this.ClipHistogram(histogramCopy, this.ClipLimit);
cdf.Clear();
int cdfMin = this.CalculateCdf(cdf, histogramCopy);
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));
// Remove top most row from the histogram, mirroring rows which exceeds the borders
Span<TPixel> rowSpan = this.GetPixelRow(source, x - halfGridSize, y - halfGridSize, this.GridSize);
this.RemovePixelsFromHistogram(rowSpan, histogram, this.LuminanceLevels);
// Add new bottom row to the histogram, mirroring rows which exceeds the borders
rowSpan = this.GetPixelRow(source, x - halfGridSize, y + halfGridSize, this.GridSize);
this.AddPixelsTooHistogram(rowSpan, histogram, this.LuminanceLevels);
}
}
using (IBuffer<int> histogramBuffer = memoryAllocator.AllocateClean<int>(this.LuminanceLevels))
using (IBuffer<int> histogramBufferCopy = memoryAllocator.AllocateClean<int>(this.LuminanceLevels))
using (IBuffer<int> cdfBuffer = memoryAllocator.AllocateClean<int>(this.LuminanceLevels))
{
Span<int> histogram = histogramBuffer.GetSpan();
Span<int> histogramCopy = histogramBufferCopy.GetSpan();
Span<int> cdf = cdfBuffer.GetSpan();
histogram.Clear();
// Build the histogram of grayscale values for the current grid.
for (int dy = -halfGridSize; dy < halfGridSize; dy++)
{
Span<TPixel> rowSpan = this.GetPixelRow(source, x - halfGridSize, dy, this.GridSize);
this.AddPixelsTooHistogram(rowSpan, histogram, this.LuminanceLevels);
}
for (int y = 0; y < source.Height; y++)
{
// Clipping the histogram, but doing it on a copy to keep the original un-clipped values for the next iteration
histogram.CopyTo(histogramCopy);
this.ClipHistogram(histogramCopy, this.ClipLimit);
cdf.Clear();
int cdfMin = this.CalculateCdf(cdf, histogramCopy);
double numberOfPixelsMinusCdfMin = (double)(pixelsInGrid - cdfMin);
// Map the current pixel to the new equalized value
int luminance = this.GetLuminance(source[x, y], this.LuminanceLevels);
double luminanceEqualized = cdf[luminance] / numberOfPixelsMinusCdfMin;
targetPixels[x, y].PackFromVector4(new Vector4((float)luminanceEqualized));
// Remove top most row from the histogram, mirroring rows which exceeds the borders
Span<TPixel> rowSpan = this.GetPixelRow(source, x - halfGridSize, y - halfGridSize, this.GridSize);
this.RemovePixelsFromHistogram(rowSpan, histogram, this.LuminanceLevels);
// Add new bottom row to the histogram, mirroring rows which exceeds the borders
rowSpan = this.GetPixelRow(source, x - halfGridSize, y + halfGridSize, this.GridSize);
this.AddPixelsTooHistogram(rowSpan, histogram, this.LuminanceLevels);
}
}
});
Buffer2D<TPixel>.SwapOrCopyContent(source.PixelBuffer, targetPixels);
}

Loading…
Cancel
Save