user1113809
user1113809

Reputation:

The colour of pixels of the image are incorrect

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

Answers (1)

Jim Mischel
Jim Mischel

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

Related Questions