Browse Source

refactoring to improve readability

pull/673/head
popow 8 years ago
parent
commit
895cecfe0d
  1. 2
      src/ImageSharp/Processing/HistogramEqualizationExtension.cs
  2. 122
      src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs
  3. 4
      src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationMethod.cs

2
src/ImageSharp/Processing/HistogramEqualizationExtension.cs

@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Processing
processor = new GlobalHistogramEqualizationProcessor<TPixel>(options.LuminanceLevels, options.ClipHistogram, options.ClipLimitPercentage); processor = new GlobalHistogramEqualizationProcessor<TPixel>(options.LuminanceLevels, options.ClipHistogram, options.ClipLimitPercentage);
break; break;
case HistogramEqualizationMethod.Adaptive: case HistogramEqualizationMethod.AdaptiveTileInterpolation:
processor = new AdaptiveHistEqualizationProcessor<TPixel>(options.LuminanceLevels, options.ClipHistogram, options.ClipLimitPercentage, options.Tiles); processor = new AdaptiveHistEqualizationProcessor<TPixel>(options.LuminanceLevels, options.ClipHistogram, options.ClipLimitPercentage, options.Tiles);
break; break;

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

@ -62,153 +62,155 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
// The image is split up into tiles. For each tile the cumulative distribution function will be calculated. // The image is split up into tiles. For each tile the cumulative distribution function will be calculated.
CdfData[,] cdfData = this.CalculateLookupTables(source, histogram, cdf, this.Tiles, this.Tiles, tileWidth, tileHeight); CdfData[,] cdfData = this.CalculateLookupTables(source, histogram, cdf, this.Tiles, this.Tiles, tileWidth, tileHeight);
int cdfX = 0;
int cdfY = 0;
int tileX = 0; int tileX = 0;
int tileY = 0; int tileY = 0;
for (int y = halfTileHeight; y < source.Height - halfTileHeight; y += tileHeight) for (int y = halfTileHeight; y < source.Height - halfTileHeight; y += tileHeight)
{ {
tileX = 0; cdfX = 0;
for (int x = halfTileWidth; x < source.Width - halfTileWidth; x += tileWidth) for (int x = halfTileWidth; x < source.Width - halfTileWidth; x += tileWidth)
{ {
int tilePosX = 0; tileY = 0;
int tilePosY = 0;
int yEnd = Math.Min(y + tileHeight, source.Height); int yEnd = Math.Min(y + tileHeight, source.Height);
int xEnd = Math.Min(x + tileWidth, source.Width); int xEnd = Math.Min(x + tileWidth, source.Width);
for (int dy = y; dy < yEnd; dy++) for (int dy = y; dy < yEnd; dy++)
{ {
tilePosX = 0; tileX = 0;
float ty = tilePosY / (float)(tileHeight - 1);
int yTop = tileY;
int yBottom = yTop + 1;
for (int dx = x; dx < xEnd; dx++) for (int dx = x; dx < xEnd; dx++)
{ {
TPixel sourcePixel = source[dx, dy]; float luminanceEqualized = this.InterpolateBetweenTiles(source[dx, dy], cdfData, dx, dy, tileX, tileY, cdfX, cdfY, tileWidth, tileHeight, pixelsInTile);
int luminace = this.GetLuminance(sourcePixel, this.LuminanceLevels);
int xLeft = tileX;
int xRight = tileX + 1;
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 / (float)(tileWidth - 1), ty, cdfLeftTopLuminance, cdfRightTopLuminance, cdfLeftBottomLuminance, cdfRightBottomLuminance);
pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized)); pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized));
tilePosX++; tileX++;
} }
tilePosY++; tileY++;
} }
tileX++; cdfX++;
} }
tileY++; cdfY++;
} }
// fix left column // fix left column
tileX = 0; cdfX = 0;
tileY = 0; cdfY = 0;
for (int y = 0; y < source.Height; y += tileHeight) for (int y = 0; y < source.Height; y += tileHeight)
{ {
int yLimit = Math.Min(y + tileHeight, source.Height - 1); int yLimit = Math.Min(y + tileHeight, source.Height - 1);
int tilePosY = 0; tileY = 0;
for (int dy = y; dy < yLimit; dy++) for (int dy = y; dy < yLimit; dy++)
{ {
int tilePosX = 0; tileX = 0;
for (int dx = 0; dx < halfTileWidth; dx++) for (int dx = 0; dx < halfTileWidth; dx++)
{ {
float luminanceEqualized = this.InterpolateBetweenTiles(source[dx, dy], cdfData, dx, dy, tilePosX, tilePosY, tileX, tileY, tileWidth, tileHeight, pixelsInTile); float luminanceEqualized = this.InterpolateBetweenTiles(source[dx, dy], cdfData, dx, dy, tileX, tileY, cdfX, cdfY, tileWidth, tileHeight, pixelsInTile);
pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized)); pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized));
tilePosX++; tileX++;
} }
tilePosY++; tileY++;
} }
tileY++; cdfY++;
} }
// fix right column // fix right column
tileX = this.Tiles - 2; cdfX = this.Tiles - 2;
tileY = 0; cdfY = 0;
for (int y = 0; y < source.Height; y += tileHeight) for (int y = 0; y < source.Height; y += tileHeight)
{ {
int yLimit = Math.Min(y + tileHeight, source.Height - 1); int yLimit = Math.Min(y + tileHeight, source.Height - 1);
int tilePosY = 0; tileY = 0;
for (int dy = y; dy < yLimit; dy++) for (int dy = y; dy < yLimit; dy++)
{ {
int tilePosX = halfTileWidth; tileX = halfTileWidth;
for (int dx = source.Width - halfTileWidth; dx < source.Width; dx++) for (int dx = source.Width - halfTileWidth; dx < source.Width; dx++)
{ {
float luminanceEqualized = this.InterpolateBetweenTiles(source[dx, dy], cdfData, dx, dy, tilePosX, tilePosY, tileX, tileY, tileWidth, tileHeight, pixelsInTile); float luminanceEqualized = this.InterpolateBetweenTiles(source[dx, dy], cdfData, dx, dy, tileX, tileY, cdfX, cdfY, tileWidth, tileHeight, pixelsInTile);
pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized)); pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized));
tilePosX++; tileX++;
} }
tilePosY++; tileY++;
} }
tileY++; cdfY++;
} }
// fix top row // fix top row
tileX = 0; cdfX = 0;
tileY = 0; cdfY = 0;
for (int x = 0; x < source.Width; x += tileWidth) for (int x = 0; x < source.Width; x += tileWidth)
{ {
int tilePosY = 0; tileY = 0;
for (int dy = 0; dy < halfTileHeight; dy++) for (int dy = 0; dy < halfTileHeight; dy++)
{ {
int tilePosX = 0; tileX = 0;
int xLimit = Math.Min(x + tileWidth, source.Width - 1); int xLimit = Math.Min(x + tileWidth, source.Width - 1);
for (int dx = x; dx < xLimit; dx++) for (int dx = x; dx < xLimit; dx++)
{ {
float luminanceEqualized = this.InterpolateBetweenTiles(source[dx, dy], cdfData, dx, dy, tilePosX, tilePosY, tileX, tileY, tileWidth, tileHeight, pixelsInTile); float luminanceEqualized = this.InterpolateBetweenTiles(source[dx, dy], cdfData, dx, dy, tileX, tileY, cdfX, cdfY, tileWidth, tileHeight, pixelsInTile);
pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized)); pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized));
tilePosX++; tileX++;
} }
tilePosY++; tileY++;
} }
tileX++; cdfX++;
} }
// fix bottom row // fix bottom row
tileX = 0; cdfX = 0;
tileY = 0; cdfY = 0;
for (int x = 0; x < source.Width; x += tileWidth) for (int x = 0; x < source.Width; x += tileWidth)
{ {
int tilePosY = 0; tileY = 0;
for (int dy = source.Height - halfTileHeight; dy < source.Height; dy++) for (int dy = source.Height - halfTileHeight; dy < source.Height; dy++)
{ {
int tilePosX = 0; tileX = 0;
int xLimit = Math.Min(x + tileWidth, source.Width - 1); int xLimit = Math.Min(x + tileWidth, source.Width - 1);
for (int dx = x; dx < xLimit; dx++) for (int dx = x; dx < xLimit; dx++)
{ {
float luminanceEqualized = this.InterpolateBetweenTiles(source[dx, dy], cdfData, dx, dy, tilePosX, tilePosY, tileX, tileY, tileWidth, tileHeight, pixelsInTile); float luminanceEqualized = this.InterpolateBetweenTiles(source[dx, dy], cdfData, dx, dy, tileX, tileY, cdfX, cdfY, tileWidth, tileHeight, pixelsInTile);
pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized)); pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized));
tilePosX++; tileX++;
} }
tilePosY++; tileY++;
} }
tileX++; cdfX++;
} }
} }
} }
private float InterpolateBetweenTiles(TPixel sourcePixel, CdfData[,] cdfData, int dx, int dy, int tilePosX, int tilePosY, int tileX, int tileY, int tileWidth, int tileHeight, int pixelsInTile) /// <summary>
/// Interpolates between four adjacent tiles.
/// </summary>
/// <param name="sourcePixel">The pixel to remap the grey value from.</param>
/// <param name="cdfData">The pre-computed lookup tables to remap the grey values for each tiles.</param>
/// <param name="dx">X index in the image.</param>
/// <param name="dy">Y index in the image.</param>
/// <param name="tileX">X position inside the tile.</param>
/// <param name="tileY">Y position inside the tile.</param>
/// <param name="cdfX">X index of the top left lookup table to use.</param>
/// <param name="cdfY">Y index of the top left lookup table to use.</param>
/// <param name="tileWidth">Width of one tile in pixels.</param>
/// <param name="tileHeight">Height of one tile in pixels.</param>
/// <param name="pixelsInTile">Amount of pixels in one tile.</param>
/// <returns>A re-mapped grey value.</returns>
private float InterpolateBetweenTiles(TPixel sourcePixel, CdfData[,] cdfData, int dx, int dy, int tileX, int tileY, int cdfX, int cdfY, int tileWidth, int tileHeight, int pixelsInTile)
{ {
int luminace = this.GetLuminance(sourcePixel, this.LuminanceLevels); int luminace = this.GetLuminance(sourcePixel, this.LuminanceLevels);
float tx = tilePosX / (float)(tileWidth - 1); float tx = tileX / (float)(tileWidth - 1);
float ty = tilePosY / (float)(tileHeight - 1); float ty = tileY / (float)(tileHeight - 1);
int yTop = tileY; int yTop = cdfY;
int yBottom = Math.Min(this.Tiles - 1, yTop + 1); int yBottom = Math.Min(this.Tiles - 1, yTop + 1);
int xLeft = tileX; int xLeft = cdfX;
int xRight = Math.Min(this.Tiles - 1, xLeft + 1); int xRight = Math.Min(this.Tiles - 1, xLeft + 1);
float cdfLeftTopLuminance = cdfData[xLeft, yTop].RemapGreyValue(luminace, pixelsInTile); float cdfLeftTopLuminance = cdfData[xLeft, yTop].RemapGreyValue(luminace, pixelsInTile);

4
src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationMethod.cs

@ -14,9 +14,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
Global, Global,
/// <summary> /// <summary>
/// Adaptive histogram equalization. /// Adaptive histogram equalization using a tile interpolation approach.
/// </summary> /// </summary>
Adaptive, AdaptiveTileInterpolation,
/// <summary> /// <summary>
/// Adaptive sliding window histogram equalization. /// Adaptive sliding window histogram equalization.

Loading…
Cancel
Save