Browse Source

it's called Manhattan distance! stupid me :P

af/merge-core
Anton Firszov 9 years ago
parent
commit
4822a04c8b
  1. 2
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  2. 4
      tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs
  3. 22
      tests/ImageSharp.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs
  4. 2
      tests/ImageSharp.Tests/TestUtilities/Tests/ImageComparerTests.cs

2
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs

@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Tests
// TODO: We should make this comparer less tolerant ... // TODO: We should make this comparer less tolerant ...
private static readonly ImageComparer VeryTolerantJpegComparer = private static readonly ImageComparer VeryTolerantJpegComparer =
ImageComparer.Tolerant(0.005f, pixelThresholdHammingDistance: 4); ImageComparer.Tolerant(0.005f, perPixelManhattanThreshold: 4);
public JpegDecoderTests(ITestOutputHelper output) public JpegDecoderTests(ITestOutputHelper output)
{ {

4
tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs

@ -17,9 +17,9 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
public static ImageComparer Tolerant( public static ImageComparer Tolerant(
float imageThreshold = TolerantImageComparer.DefaultImageThreshold, float imageThreshold = TolerantImageComparer.DefaultImageThreshold,
int pixelThresholdHammingDistance = 0) int perPixelManhattanThreshold = 0)
{ {
return new TolerantImageComparer(imageThreshold, pixelThresholdHammingDistance); return new TolerantImageComparer(imageThreshold, perPixelManhattanThreshold);
} }
public abstract ImageSimilarityReport CompareImagesOrFrames<TPixelA, TPixelB>( public abstract ImageSimilarityReport CompareImagesOrFrames<TPixelA, TPixelB>(

22
tests/ImageSharp.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs

@ -12,10 +12,10 @@
{ {
public const float DefaultImageThreshold = 1.0f / (100 * 100 * 255); public const float DefaultImageThreshold = 1.0f / (100 * 100 * 255);
public TolerantImageComparer(float imageThreshold, int pixelThresholdHammingDistance = 0) public TolerantImageComparer(float imageThreshold, int perPixelManhattanThreshold = 0)
{ {
this.ImageThreshold = imageThreshold; this.ImageThreshold = imageThreshold;
this.PixelThresholdHammingDistance = pixelThresholdHammingDistance; this.PerPixelManhattanThreshold = perPixelManhattanThreshold;
} }
/// <summary> /// <summary>
@ -26,7 +26,10 @@
/// 3. PixelA = (255,255,255,0) PixelB =(128,128,128,128) leads to 50% difference on a single pixel /// 3. PixelA = (255,255,255,0) PixelB =(128,128,128,128) leads to 50% difference on a single pixel
/// ///
/// The total differences is the sum of all pixel differences normalized by image dimensions! /// The total differences is the sum of all pixel differences normalized by image dimensions!
/// /// The individual distances are calculated using the Manhattan function:
/// <see>
/// <cref>https://en.wikipedia.org/wiki/Taxicab_geometry</cref>
/// </see>
/// ImageThresholdInPercents = 1.0/255 means that we allow one byte difference per channel on a 1x1 image /// ImageThresholdInPercents = 1.0/255 means that we allow one byte difference per channel on a 1x1 image
/// ImageThresholdInPercents = 1.0/(100*100*255) means that we allow only one byte difference per channel on a 100x100 image /// ImageThresholdInPercents = 1.0/(100*100*255) means that we allow only one byte difference per channel on a 100x100 image
/// </summary> /// </summary>
@ -34,9 +37,12 @@
/// <summary> /// <summary>
/// The threshold of the individual pixels before they acumulate towards the overall difference. /// The threshold of the individual pixels before they acumulate towards the overall difference.
/// For an individual <see cref="Rgba32"/> pixel the value it's calculated as: pixel.R + pixel.G + pixel.B + pixel.A /// For an individual <see cref="Rgba32"/> pixel pair the value is the Manhattan distance of pixels:
/// <see>
/// <cref>https://en.wikipedia.org/wiki/Taxicab_geometry</cref>
/// </see>
/// </summary> /// </summary>
public int PixelThresholdHammingDistance { get; } public int PerPixelManhattanThreshold { get; }
public override ImageSimilarityReport CompareImagesOrFrames<TPixelA, TPixelB>(ImageBase<TPixelA> expected, ImageBase<TPixelB> actual) public override ImageSimilarityReport CompareImagesOrFrames<TPixelA, TPixelB>(ImageBase<TPixelA> expected, ImageBase<TPixelB> actual)
{ {
@ -66,9 +72,9 @@
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
{ {
int d = GetHammingDistanceInRgbaSpace(ref aBuffer[x], ref bBuffer[x]); int d = GetManhattanDistanceInRgbaSpace(ref aBuffer[x], ref bBuffer[x]);
if (d > this.PixelThresholdHammingDistance) if (d > this.PerPixelManhattanThreshold)
{ {
var diff = new PixelDifference(new Point(x, y), aBuffer[x], bBuffer[x]); var diff = new PixelDifference(new Point(x, y), aBuffer[x], bBuffer[x]);
differences.Add(diff); differences.Add(diff);
@ -92,7 +98,7 @@
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int GetHammingDistanceInRgbaSpace(ref Rgba32 a, ref Rgba32 b) private static int GetManhattanDistanceInRgbaSpace(ref Rgba32 a, ref Rgba32 b)
{ {
return Diff(a.R, b.R) + Diff(a.G, b.G) + Diff(a.B, b.B) + Diff(a.A, b.A); return Diff(a.R, b.R) + Diff(a.G, b.G) + Diff(a.B, b.B) + Diff(a.A, b.A);
} }

2
tests/ImageSharp.Tests/TestUtilities/Tests/ImageComparerTests.cs

@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Tests
ImagingTestCaseUtility.ModifyPixel(clone, 1, 0, 10); ImagingTestCaseUtility.ModifyPixel(clone, 1, 0, 10);
ImagingTestCaseUtility.ModifyPixel(clone, 2, 0, 10); ImagingTestCaseUtility.ModifyPixel(clone, 2, 0, 10);
var comparer = ImageComparer.Tolerant(pixelThresholdHammingDistance: 42); var comparer = ImageComparer.Tolerant(perPixelManhattanThreshold: 42);
comparer.VerifySimilarity(image, clone); comparer.VerifySimilarity(image, clone);
} }
} }

Loading…
Cancel
Save