Browse Source

linear interpolation in the border tiles

pull/673/head
popow 8 years ago
parent
commit
3dfe5a5c1d
  1. 53
      src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs

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

@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
tileX = 0; tileX = 0;
for (int dx = x; dx < xEnd; dx++) for (int dx = x; dx < xEnd; dx++)
{ {
float luminanceEqualized = this.InterpolateBetweenTiles(source[dx, dy], cdfData, dx, dy, tileX, tileY, cdfX, cdfY, tileWidth, tileHeight, pixelsInTile); float luminanceEqualized = this.InterpolateBetweenFourTiles(source[dx, dy], cdfData, 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));
tileX++; tileX++;
} }
@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
// fix left column // fix left column
cdfX = 0; cdfX = 0;
cdfY = 0; cdfY = 0;
for (int y = 0; y < source.Height; y += tileHeight) for (int y = halfTileWidth; y < source.Height - halfTileWidth; y += tileHeight)
{ {
int yLimit = Math.Min(y + tileHeight, source.Height - 1); int yLimit = Math.Min(y + tileHeight, source.Height - 1);
tileY = 0; tileY = 0;
@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
tileX = 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, tileX, tileY, cdfX, cdfY, tileWidth, tileHeight, pixelsInTile); float luminanceEqualized = this.InterpolateBetweenTwoTiles(source[dx, dy], cdfData[cdfX, cdfY], cdfData[cdfX, cdfY + 1], tileY, tileHeight, pixelsInTile);
pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized)); pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized));
tileX++; tileX++;
} }
@ -117,9 +117,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
} }
// fix right column // fix right column
cdfX = this.Tiles - 2; cdfX = this.Tiles - 1;
cdfY = 0; cdfY = 0;
for (int y = 0; y < source.Height; y += tileHeight) for (int y = halfTileWidth; y < source.Height - halfTileWidth; y += tileHeight)
{ {
int yLimit = Math.Min(y + tileHeight, source.Height - 1); int yLimit = Math.Min(y + tileHeight, source.Height - 1);
tileY = 0; tileY = 0;
@ -128,7 +128,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
tileX = 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, tileX, tileY, cdfX, cdfY, tileWidth, tileHeight, pixelsInTile); float luminanceEqualized = this.InterpolateBetweenTwoTiles(source[dx, dy], cdfData[cdfX, cdfY], cdfData[cdfX, cdfY + 1], tileY, tileHeight, pixelsInTile);
pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized)); pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized));
tileX++; tileX++;
} }
@ -142,7 +142,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
// fix top row // fix top row
cdfX = 0; cdfX = 0;
cdfY = 0; cdfY = 0;
for (int x = 0; x < source.Width; x += tileWidth) for (int x = halfTileWidth; x < source.Width - halfTileWidth; x += tileWidth)
{ {
tileY = 0; tileY = 0;
for (int dy = 0; dy < halfTileHeight; dy++) for (int dy = 0; dy < halfTileHeight; dy++)
@ -151,7 +151,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
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, tileX, tileY, cdfX, cdfY, tileWidth, tileHeight, pixelsInTile); float luminanceEqualized = this.InterpolateBetweenTwoTiles(source[dx, dy], cdfData[cdfX, cdfY], cdfData[cdfX + 1, cdfY], tileX, tileWidth, pixelsInTile);
pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized)); pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized));
tileX++; tileX++;
} }
@ -164,8 +164,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
// fix bottom row // fix bottom row
cdfX = 0; cdfX = 0;
cdfY = 0; cdfY = this.Tiles - 1;
for (int x = 0; x < source.Width; x += tileWidth) for (int x = halfTileWidth; x < source.Width - halfTileWidth; x += tileWidth)
{ {
tileY = 0; tileY = 0;
for (int dy = source.Height - halfTileHeight; dy < source.Height; dy++) for (int dy = source.Height - halfTileHeight; dy < source.Height; dy++)
@ -174,7 +174,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
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, tileX, tileY, cdfX, cdfY, tileWidth, tileHeight, pixelsInTile); float luminanceEqualized = this.InterpolateBetweenTwoTiles(source[dx, dy], cdfData[cdfX, cdfY], cdfData[cdfX + 1, cdfY], tileX, tileWidth, pixelsInTile);
pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized)); pixels[(dy * source.Width) + dx].PackFromVector4(new Vector4(luminanceEqualized));
tileX++; tileX++;
} }
@ -188,12 +188,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
} }
/// <summary> /// <summary>
/// Interpolates between four adjacent tiles. /// Bilinear interpolation between four adjacent tiles.
/// </summary> /// </summary>
/// <param name="sourcePixel">The pixel to remap the grey value from.</param> /// <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="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="tileX">X position inside the tile.</param>
/// <param name="tileY">Y 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="cdfX">X index of the top left lookup table to use.</param>
@ -202,7 +200,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
/// <param name="tileHeight">Height 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> /// <param name="pixelsInTile">Amount of pixels in one tile.</param>
/// <returns>A re-mapped grey value.</returns> /// <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) private float InterpolateBetweenFourTiles(TPixel sourcePixel, CdfData[,] cdfData, 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 = tileX / (float)(tileWidth - 1); float tx = tileX / (float)(tileWidth - 1);
@ -222,6 +220,28 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
return luminanceEqualized; return luminanceEqualized;
} }
/// <summary>
/// Linear interpolation between two tiles.
/// </summary>
/// <param name="sourcePixel">The pixel to remap the grey value from.</param>
/// <param name="cdfData1">First lookup table.</param>
/// <param name="cdfData2">Second lookup table.</param>
/// <param name="tilePos">Position inside the tile.</param>
/// <param name="tileWidth">Width of the tile.</param>
/// <param name="pixelsInTile">Pixels in one tile.</param>
/// <returns>A re-mapped grey value.</returns>
private float InterpolateBetweenTwoTiles(TPixel sourcePixel, CdfData cdfData1, CdfData cdfData2, int tilePos, int tileWidth, int pixelsInTile)
{
int luminace = this.GetLuminance(sourcePixel, this.LuminanceLevels);
float tx = tilePos / (float)(tileWidth - 1);
float cdfLuminance1 = cdfData1.RemapGreyValue(luminace, pixelsInTile);
float cdfLuminance2 = cdfData2.RemapGreyValue(luminace, pixelsInTile);
float luminanceEqualized = this.LinearInterpolation(cdfLuminance1, cdfLuminance2, tx);
return luminanceEqualized;
}
/// <summary> /// <summary>
/// Calculates the lookup tables for each tile of the image. /// Calculates the lookup tables for each tile of the image.
/// </summary> /// </summary>
@ -302,6 +322,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
return left + ((right - left) * t); return left + ((right - left) * t);
} }
/// <summary>
/// Lookup table for remapping the grey values of one tile.
/// </summary>
private class CdfData private class CdfData
{ {
/// <summary> /// <summary>

Loading…
Cancel
Save