From 176e7e9f83cc2a3dea0eac5fbcd61498f7c32dcf Mon Sep 17 00:00:00 2001 From: popow Date: Mon, 27 Aug 2018 19:38:14 +0200 Subject: [PATCH] simplified interpolation between the tiles --- .../AdaptiveHistEqualizationProcessor.cs | 53 ++++++++++++------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs index 94000bd8da..87fb63502d 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs @@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization Span histogram = histogramBuffer.GetSpan(); Span cdf = cdfBuffer.GetSpan(); - // The image is split up in square tiles of the size of the parameter GridSize. + // 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; @@ -97,10 +97,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization int tilePosX = 0; int tilePosY = 0; - for (int y = halfGridSize; y < source.Height - halfGridSize; y += this.GridSize) + for (int y = halfGridSize; y < source.Height - this.GridSize; y += this.GridSize) { tilePosX = 0; - for (int x = halfGridSize; x < source.Width - halfGridSize; x += this.GridSize) + for (int x = halfGridSize; x < source.Width - this.GridSize; x += this.GridSize) { int gridPosX = 0; int gridPosY = 0; @@ -109,17 +109,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization for (int dy = y; dy < ylimit; dy++) { gridPosX = 0; + float ty = gridPosY / (float)(this.GridSize - 1); + int yTop = tilePosY; + int yBottom = yTop + 1; for (int dx = x; dx < xlimit; dx++) { TPixel sourcePixel = source[dx, dy]; int luminace = this.GetLuminance(sourcePixel, this.LuminanceLevels); - float cdfLeftTopLuminance = cdfData[tilePosX, tilePosY].RemapGreyValue(luminace, pixelsInGrid); - float cdfRightTopLuminance = cdfData[tilePosX + 1, tilePosY].RemapGreyValue(luminace, pixelsInGrid); - float cdfLeftBottomLuminance = cdfData[tilePosX, tilePosY + 1].RemapGreyValue(luminace, pixelsInGrid); - float cdfRightBottomLuminance = cdfData[tilePosX + 1, tilePosY + 1].RemapGreyValue(luminace, pixelsInGrid); + 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); + + float luminanceEqualized = this.BilinearInterpolation(gridPosX, gridPosY, gridPosX / (float)(this.GridSize - 1), ty, cdfLeftTopLuminance, cdfRightTopLuminance, cdfLeftBottomLuminance, cdfRightBottomLuminance); - float luminanceEqualized = this.BilinearInterpolation(gridPosX, gridPosY, this.GridSize, cdfLeftTopLuminance, cdfRightTopLuminance, cdfLeftBottomLuminance, cdfRightBottomLuminance); pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized)); gridPosX++; } @@ -140,20 +147,28 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// /// X position. /// Y position. - /// The size of the grid. - /// Luminance from tile top left. - /// Luminance from tile right top. - /// Luminance from tile left bottom. - /// Luminance from tile right bottom. + /// The interpolation value in x direction in the range of [0, 1]. + /// The interpolation value in y direction in the range of [0, 1]. + /// Luminance from top left tile. + /// Luminance from right top tile. + /// Luminance from left bottom tile. + /// Luminance from right bottom tile. /// Interpolated Luminance. - private float BilinearInterpolation(int x, int y, int gridSize, float lt, float rt, float lb, float rb) + private float BilinearInterpolation(int x, int y, float tx, float ty, float lt, float rt, float lb, float rb) { - float r1 = ((gridSize - x) / (float)gridSize * lb) + ((x / (float)gridSize) * rb); - float r2 = ((gridSize - x) / (float)gridSize * lt) + ((x / (float)gridSize) * rt); - - float res = ((y / ((float)gridSize)) * r1) + (((y - gridSize) / (float)(-gridSize)) * r2); + return this.LinearInterpolation(this.LinearInterpolation(lt, rt, tx), this.LinearInterpolation(lb, rb, tx), ty); + } - return res; + /// + /// Linear interpolation between two grey values. + /// + /// The left value. + /// The right value. + /// The interpolation value between the two values in the range of [0, 1]. + /// The interpolated value. + private float LinearInterpolation(float left, float right, float t) + { + return left + ((right - left) * t); } private class CdfData