Reputation:
I'm trying to compare 2 images with a comparison function called SAD (sum of square differences), I take a block from each image, and I convert the pixels to grayscale and I do the comparison. but the problem is that if I compare two identical blocks, the result of sad isn't 0 (so there is a difference). I checked with multiple messageboxes and then I saw that the program returns incorrect colors for pixels: for example, black pixel=255 instead of 0.
here the code of my comparison function:
public double SAD(bloc Bc, bloc Br)
{
double sad = 0;
{
BitmapData bmp = image1.LockBits(new Rectangle(Bc.x, Bc.y, taille_bloc, taille_bloc), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
BitmapData bmp2 = image2.LockBits(new Rectangle(Br.x, Br.y, taille_bloc, taille_bloc), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
IntPtr ptr2 = bmp2.Scan0;
IntPtr ptr = bmp.Scan0;
int bytes = bmp.Width * bmp.Height * 3;
double gris1, gris2;
byte[] rgb = new byte[bytes];
byte[] rgb2 = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgb, 0, bytes);
System.Runtime.InteropServices.Marshal.Copy(ptr2, rgb2, 0, bytes);
for (int i = 0; i < rgb.Length; i += 3)
{
gris1 = rgb[i] * 0.2989 + rgb[i+1] * 0.5870 + rgb[i+2] * 0.1140;
gris2 = rgb2[i] * 0.2989 + rgb2[i + 1] * 0.5870 + rgb2[i + 2] * 0.1140;
sad = sad + Math.Abs(gris2 - gris1);
}
image2.UnlockBits(bmp2);
image1.UnlockBits(bmp);
}
return sad;
}
If I didn't be clear in my explanation please tell me so I will reformulate
thank you very much in advance for your help :)
Upvotes: 0
Views: 447
Reputation: 133995
One possible problem is that your number of bytes calculation is wrong. You have:
int bytes = bmp.Width * bmp.Height * 3;
But bitmaps are padded, typically to a 4-byte boundary. You need to use
int bytes = bmp.Stride * bmp.Height;
Stride
is the number of bytes it takes to represent a scan line. For a 24-bit image, that will be equal to 3 * bmp.Width
PLUS the number of bytes required for padding (which might be zero).
To index the array, then, you go line by line, and ignore the padding bytes. You have to initialize your index at the beginning of each row.
for (int row = 0; row < bmp.Height; ++row)
{
int i = row * bmp.Stride;
for (int p = 0; p < bmp.Width; ++p)
{
// do comparisons with rgb[i], rgb[i+1], rgb[i+2]
i += 3;
}
}
Upvotes: 1