Browse Source

number of tiles is now fixed and depended on the width and height of the image

pull/673/head
popow 8 years ago
parent
commit
516d96f157
  1. 89
      src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs

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

@ -46,12 +46,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
int numberOfPixels = source.Width * source.Height;
Span<TPixel> pixels = source.GetPixelSpan();
int pixelsInGrid = this.GridSize * this.GridSize;
int halfGridSize = this.GridSize / 2;
int xtiles = Convert.ToInt32(Math.Ceiling(source.Width / (double)this.GridSize));
int ytiles = Convert.ToInt32(Math.Ceiling(source.Height / (double)this.GridSize));
int numTilesX = 20;
int numTilesY = 20;
var cdfData = new CdfData[xtiles, ytiles];
int tileWidth = Convert.ToInt32(Math.Ceiling(source.Width / (double)numTilesX));
int tileHeight = Convert.ToInt32(Math.Ceiling(source.Height / (double)numTilesY));
int pixelsInTile = tileWidth * tileHeight;
int halfTileWidth = tileWidth / 2;
int halfTileHeight = tileHeight / 2;
var cdfData = new CdfData[numTilesX, numTilesY];
using (System.Buffers.IMemoryOwner<int> histogramBuffer = memoryAllocator.Allocate<int>(this.LuminanceLevels, AllocationOptions.Clean))
using (System.Buffers.IMemoryOwner<int> cdfBuffer = memoryAllocator.Allocate<int>(this.LuminanceLevels, AllocationOptions.Clean))
{
@ -60,17 +64,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
// The image is split up into square tiles of the size of the parameter GridSize.
// For each tile the cumulative distribution function will be calculated.
int cdfPosX = 0;
int cdfPosY = 0;
for (int y = 0; y < source.Height; y += this.GridSize)
int tileX = 0;
int tileY = 0;
for (int y = 0; y < source.Height; y += tileHeight)
{
cdfPosX = 0;
for (int x = 0; x < source.Width; x += this.GridSize)
tileX = 0;
for (int x = 0; x < source.Width; x += tileWidth)
{
histogram.Clear();
cdf.Clear();
int ylimit = Math.Min(y + this.GridSize, source.Height);
int xlimit = Math.Min(x + this.GridSize, source.Width);
int ylimit = Math.Min(y + tileHeight, source.Height);
int xlimit = Math.Min(x + tileWidth, source.Width);
for (int dy = y; dy < ylimit; dy++)
{
for (int dx = x; dx < xlimit; dx++)
@ -82,62 +86,61 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
if (this.ClipHistogramEnabled)
{
this.ClipHistogram(histogram, this.ClipLimitPercentage, pixelsInGrid);
this.ClipHistogram(histogram, this.ClipLimitPercentage, pixelsInTile);
}
int cdfMin = this.CalculateCdf(cdf, histogram, histogram.Length - 1);
var currentCdf = new CdfData(cdf.ToArray(), cdfMin);
cdfData[cdfPosX, cdfPosY] = currentCdf;
cdfData[tileX, tileY] = currentCdf;
cdfPosX++;
tileX++;
}
cdfPosY++;
tileY++;
}
int tilePosX = 0;
int tilePosY = 0;
for (int y = halfGridSize; y < source.Height - this.GridSize; y += this.GridSize)
tileX = 0;
tileY = 0;
for (int y = halfTileHeight; y < source.Height - tileHeight; y += tileHeight)
{
tilePosX = 0;
for (int x = halfGridSize; x < source.Width - this.GridSize; x += this.GridSize)
tileX = 0;
for (int x = halfTileWidth; x < source.Width - tileWidth; x += tileWidth)
{
int gridPosX = 0;
int gridPosY = 0;
int ylimit = Math.Min(y + this.GridSize, source.Height);
int xlimit = Math.Min(x + this.GridSize, source.Width);
int tilePosX = 0;
int tilePosY = 0;
int ylimit = Math.Min(y + tileHeight, source.Height);
int xlimit = Math.Min(x + tileWidth, source.Width);
for (int dy = y; dy < ylimit; dy++)
{
gridPosX = 0;
float ty = gridPosY / (float)(this.GridSize - 1);
int yTop = tilePosY;
tilePosX = 0;
float ty = tilePosY / (float)(tileHeight - 1);
int yTop = tileY;
int yBottom = yTop + 1;
for (int dx = x; dx < xlimit; dx++)
{
TPixel sourcePixel = source[dx, dy];
int luminace = this.GetLuminance(sourcePixel, this.LuminanceLevels);
int xLeft = tilePosX;
int xRight = tilePosX + 1;
float cdfLeftTopLuminance = cdfData[xLeft, yTop].RemapGreyValue(luminace, pixelsInGrid);
float cdfRightTopLuminance = cdfData[xRight, yTop].RemapGreyValue(luminace, pixelsInGrid);
float cdfLeftBottomLuminance = cdfData[xLeft, yBottom].RemapGreyValue(luminace, pixelsInGrid);
float cdfRightBottomLuminance = cdfData[xRight, yBottom].RemapGreyValue(luminace, pixelsInGrid);
int xLeft = tileX;
int xRight = tileX + 1;
float luminanceEqualized = this.BilinearInterpolation(gridPosX, gridPosY, gridPosX / (float)(this.GridSize - 1), ty, cdfLeftTopLuminance, cdfRightTopLuminance, cdfLeftBottomLuminance, cdfRightBottomLuminance);
float cdfLeftTopLuminance = cdfData[xLeft, yTop].RemapGreyValue(luminace, pixelsInTile);
float cdfRightTopLuminance = cdfData[xRight, yTop].RemapGreyValue(luminace, pixelsInTile);
float cdfLeftBottomLuminance = cdfData[xLeft, yBottom].RemapGreyValue(luminace, pixelsInTile);
float cdfRightBottomLuminance = cdfData[xRight, yBottom].RemapGreyValue(luminace, pixelsInTile);
float luminanceEqualized = this.BilinearInterpolation(tilePosX, tilePosY, tilePosX / (float)(tileWidth - 1), ty, cdfLeftTopLuminance, cdfRightTopLuminance, cdfLeftBottomLuminance, cdfRightBottomLuminance);
pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized));
gridPosX++;
tilePosX++;
}
gridPosY++;
tilePosY++;
}
tilePosX++;
tileX++;
}
tilePosY++;
tileY++;
}
}
}
@ -198,11 +201,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
/// Remaps the grey value with the cdf.
/// </summary>
/// <param name="luminance">The original luminance.</param>
/// <param name="pixelsInGrid">The pixels in grid.</param>
/// <param name="pixelsInTile">The number of pixels in the tile.</param>
/// <returns>The remapped luminance.</returns>
public float RemapGreyValue(int luminance, int pixelsInGrid)
public float RemapGreyValue(int luminance, int pixelsInTile)
{
return (pixelsInGrid - this.CdfMin) == 0 ? this.Cdf[luminance] / (float)pixelsInGrid : this.Cdf[luminance] / (float)(pixelsInGrid - this.CdfMin);
return (pixelsInTile - this.CdfMin) == 0 ? this.Cdf[luminance] / (float)pixelsInTile : this.Cdf[luminance] / (float)(pixelsInTile - this.CdfMin);
}
}
}

Loading…
Cancel
Save