in Sources/Imaging/Microsoft.Psi.Imaging/ImageExtensions.cs [371:488]
public static bool Compare(this ImageBase image1, ImageBase image2, double tolerance, double percentOutliersAllowed, ref ImageError errorMetrics)
{
if (image1.GetType() != image2.GetType() ||
image1.PixelFormat != image2.PixelFormat ||
image1.Width != image2.Width ||
image1.Height != image2.Height)
{
return false;
}
errorMetrics.MaxError = 0.0f;
errorMetrics.AvgError = 0.0f;
errorMetrics.NumberOutliers = 0;
double dist = 0.0f;
unsafe
{
int bytesPerPixel1 = image1.BitsPerPixel / 8;
int bytesPerPixel2 = image2.BitsPerPixel / 8;
byte* row1 = (byte*)image1.ImageData.ToPointer();
byte* row2 = (byte*)image2.ImageData.ToPointer();
for (int y = 0; y < image1.Height; y++)
{
byte* col1 = row1;
byte* col2 = row2;
for (int x = 0; x < image1.Width; x++)
{
switch (image1.PixelFormat)
{
case PixelFormat.BGRA_32bpp:
{
int db = col1[0] - col2[0];
int dg = col1[1] - col2[1];
int dr = col1[2] - col2[2];
int da = col1[3] - col2[3];
dist = (double)(db * db + dg * dg + dr * dr + da * da);
}
break;
case PixelFormat.BGRX_32bpp:
case PixelFormat.BGR_24bpp:
{
int db = col1[0] - col2[0];
int dg = col1[1] - col2[1];
int dr = col1[2] - col2[2];
dist = (double)(db * db + dg * dg + dr * dr);
}
break;
case PixelFormat.Gray_16bpp:
{
int d = ((ushort*)col1)[0] - ((ushort*)col2)[0];
dist = (double)(d * d);
}
break;
case PixelFormat.Gray_8bpp:
{
int d = col1[0] - col2[0];
dist = (double)(d * d);
}
break;
case PixelFormat.RGB_24bpp:
{
int dr = col1[0] - col2[0];
int dg = col1[1] - col2[1];
int db = col1[2] - col2[2];
dist = (double)(dr * dr + dg * dg + db * db);
}
break;
case PixelFormat.RGBA_64bpp:
{
int dr = ((ushort*)col1)[0] - ((ushort*)col2)[0];
int dg = ((ushort*)col1)[1] - ((ushort*)col2)[1];
int db = ((ushort*)col1)[2] - ((ushort*)col2)[2];
int da = ((ushort*)col1)[3] - ((ushort*)col2)[3];
dist = (double)(dr * dr + dg * dg + db * db + da * da);
}
break;
case PixelFormat.Undefined:
default:
throw new ArgumentException("Unsupported image format");
}
if (dist > errorMetrics.MaxError)
{
errorMetrics.MaxError = dist;
}
errorMetrics.AvgError += dist;
if (dist > tolerance * tolerance)
{
errorMetrics.NumberOutliers++;
}
col1 += bytesPerPixel1;
col2 += bytesPerPixel2;
}
row1 += image1.Stride;
row2 += image2.Stride;
}
}
errorMetrics.AvgError /= (double)(image1.Width * image1.Height);
errorMetrics.MaxError = Math.Sqrt(errorMetrics.MaxError);
return errorMetrics.NumberOutliers <= percentOutliersAllowed * image1.Width * image1.Height;
}