James Aharon
James Aharon

Reputation: 223

How can convert this method ot use LockBits to be faster and that it will compare 3 images or more?

The method get two images. One is from the resources the same image all the time. The second is downloaded image that might be the same as the one in the resources or a different one. Then the method return tre or false.

//*** This function compare images region specific area ( in this case the "radar close" text area ) ***\\
        public bool ImageComparison(Bitmap Image1, Bitmap Image2, Rectangle Rect, double tol)
        {
            //Logger.Write("Rect >>>> " + Rect.ToString());
            double color_distance;
            int x;
            int y;
            bool different = false;
            textbox3 = Rect.ToString();
            //if pictures are not of same size, return that they are different
            if (Image1.Width != Image2.Width || Image1.Height != Image2.Height)
            {
                Logger.Write("Image1 Width >>>> " + Image1.Width.ToString());
                Logger.Write("Image2 Width >>>> " + Image2.Width.ToString());
                Logger.Write("Image1 Height >>>> " + Image1.Height.ToString());
                Logger.Write("Image2 Height >>>> " + Image2.Height.ToString());
                Logger.Write("Returned False images were different size");
                MessageBox.Show("Images are different Size");
                textbox1 = "";
                textbox2 = "";
                textbox3 = "";
                return false;
            }
            //Iterate over the Rect
            for (x = Rect.X; x < Rect.X + Rect.Width; ++x)
            {
                for (y = Rect.Y; y < Rect.Y + Rect.Height; ++y)
                {
                    //check, if x and y are inside the picture
                    if (x >= 0 && x < Image1.Width && y >= 0 && y < Image1.Height &&
                     x < Image2.Width && y < Image2.Height)
                    {
                        Color c = Image1.GetPixel(x, y);
                        textbox1 = c.ToString();
                        Color c2 = Image2.GetPixel(x, y);
                        textbox2 = c2.ToString();


                            double Dr = c.R - c2.R;
                            double Dg = c.G - c2.G;
                            double Db = c.B - c2.B;

                            color_distance = Math.Sqrt(Dr * Dr + Dg * Dg + Db * Db);

                            if (color_distance > tol)
                            {
                                different = true;
                                break;
                            }
                    }
                    else
                    {
                        throw new Exception(" Hello!! your region is way off!!!.. major bug!");

                    }
                }

                if (different)
                    break;
            }
            //Logger.Write("differenet bool is now >>>> " + different.ToString());
            return !different;

        }

The problem is that i'm using GetPixel and SetPixel and it might be too slow on some downloaded images. So i want to change it to LockBits. And the second thing is i want to change the method so it will get now 3 images not only 2 and the third image also will be from the resources.

This is how i'm using the method in form1:

if (ImagesComparion1.ImageComparison(File1, file2, image_scan_text_rect, 50) == true)
                        {
                            File1.Dispose();
                            Properties.Resources.RadarImageClose.Dispose();
                            label18.Text = "The Radar Is Not Active Now";
                            label18.Visible = true;
                        }
                        else
                        {
                            File1.Dispose();
                            Properties.Resources.RadarImageClose.Dispose();
                            label18.Text = "The Radar Is Active Now";
                            label18.Visible = true;
                        }

And file2 is the image from the resources:

file2 = Properties.Resources.RadarImageClose;

And File1 is the downloaded image:

File1 = new Bitmap(Properties.Resources.RadarImageClose);

Now i want to change the method to make this things:

  1. Use LockBits instead GetPixel and SetPixel.

  2. Get 3 images and make two comparison processes:

    First comparison between the first resources image file2 and File1 and then to make another process of comparsion in the method that will compare the file3 which is also resources image with File1.

I changed the method top to:

public bool ImageComparison(Bitmap Image1, Bitmap Image2, Bitmap Image3, Bitmap Image4, Rectangle Rect, double tol)

Image1 Image 3 and Image4 are all from resources get resources images. And Image2 is the downloaded image.

And i need to use the LockBits and compare first Image1 with Image2 then Image3 with Image2 then Image4 with Image2.

And if one of the comparisons it's result is true then the method return true without doing the rest of the comparisons if all comparisons are return result false the method return false.

This is a test i did took 3 pictureBoxes and put in the left and in the middle images with text inside both have different text but both meaning the radar is close. and on the right i have an image of the radar open. and i paint on all of them at the same area a red rectangle and they are all at the same area.

images

Upvotes: 1

Views: 147

Answers (1)

Use this function to compare two images:

private bool ImageComparison(Bitmap Image1, Bitmap Image2, Rectangle Rect, double tol)
    {
        int x, y, p, stride1, stride2;
        int bytes, bytesPerPixel;
        byte[] rgbValues1;
        byte[] rgbValues2;
        double Dr, Dg, Db, color_distance;
        IntPtr ptr;
        Rectangle rect;
        BitmapData bitmap_Data;

        if ( (Image1.Width != Image2.Width) || (Image1.Height != Image2.Height) )
        {
            MessageBox.Show("Images are different Size");

            return false;
        }

        if (Rect.X < 0 || Rect.Y < 0 || ((Rect.X + Rect.Width) > Image1.Width) || ((Rect.Y + Rect.Height) > Image1.Height))
        {
            MessageBox.Show("Hello!! your region is way off!!!.. major bug!");

            return false;
        }



        rect = new Rectangle(0, 0, Image1.Width, Image1.Height);

        //Lock bitmap to copy its color information fast
        bitmap_Data = Image1.LockBits(rect, ImageLockMode.ReadWrite, Image1.PixelFormat);
        ptr = bitmap_Data.Scan0;
        stride1 = bitmap_Data.Stride;
        bytes = bitmap_Data.Stride * Image1.Height;

        rgbValues1 = new byte[bytes];

        //copy color information to rgbValues array
        System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues1, 0, bytes);

        //we are done copying so unlock bitmap. We dont need it anymore
        Image1.UnlockBits(bitmap_Data);



        rect = new Rectangle(0, 0, Image2.Width, Image2.Height);

        //Lock bitmap to copy its color information fast
        bitmap_Data = Image2.LockBits(rect, ImageLockMode.ReadWrite, Image2.PixelFormat);
        ptr = bitmap_Data.Scan0;
        stride2 = bitmap_Data.Stride;
        bytes = bitmap_Data.Stride * Image2.Height;

        rgbValues2 = new byte[bytes];

        //copy color information to rgbValues array
        System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues2, 0, bytes);

        //we are done copying so unlock bitmap. We dont need it anymore
        Image2.UnlockBits(bitmap_Data);


        if (stride1 != stride2) //different pixel format
        {
            MessageBox.Show("Different pixel format");
            return false;
        }


        bytesPerPixel = Image.GetPixelFormatSize(Image1.PixelFormat) / 8;

        //scan images pixel per pixel
        for (y = 0; y < Image1.Height; y++)
        {
            for (x = 0; x < Image1.Width; x++)
            {
                p = y * stride1 + x * bytesPerPixel;

                Dr = (double)(rgbValues1[p + 2] - rgbValues2[p + 2]);
                Dg = (double)(rgbValues1[p + 1] - rgbValues2[p + 1]);
                Db = (double)(rgbValues1[p] - rgbValues2[p]);

                color_distance = Math.Sqrt(Dr * Dr + Dg * Dg + Db * Db);

                if (color_distance > tol)
                {
                    return false;
                }
            }
        }


        return true;
    }

If you want to compare multiple ones then insert them int a list:

List<Bitmap> bitmapListToCompare = new List<Bitmap>();

bitmapListToCompare.Add(....);
bitmapListToCompare.Add(....);
....

and then:

int i;
bool bl;
Bitmap bitmapToCompareWith = new Bitmap(...); //your bitmap to use as reference 
                                              //for your comparisons
for (i = 0; i < bitmapListToCompare.Count; i++)
{
    bl = ImageComparison(bitmapToCompareWith, bitmapListToCompare[i], ...., ....);
    if (bl == false)
    {
        MessageBox.Show("Image " + i.ToString() + " was different!");
        break;
    }
}

Upvotes: 1

Related Questions