如何将此方法转换为使用LockBits更快,并且它将比较3个或更多图像?

时间:2014-10-03 16:01:30

标签: c# .net winforms

该方法获得两张图片。一个是来自资源的同一个图像。 第二个是下载的图像,可能与资源中的图像相同或不同。 然后该方法返回tre或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;

        }

问题在于我使用的是GetPixel和SetPixel,在某些下载的图片上可能会太慢。所以我想把它改成LockBits。 第二件事是我想改变方法,所以它现在将获得3个图像不仅2个,第三个图像也将来自资源。

这就是我在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;
                        }

file2是来自资源的图片:

file2 = Properties.Resources.RadarImageClose;

File1是下载的图片:

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

现在我想改变方法来做这件事:

  1. 使用LockBits代替GetPixel和SetPixel。

  2. 获取3张图片并进行两个比较过程:

    首先在第一个资源图像文件2和File1之间进行比较,然后在方法中进行另一个比较过程,将文件3(也是资源图像)与File1进行比较。

  3. 我将方法顶部更改为:

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

    Image1 Image 3和Image4都来自资源获取资源图片。 Image2是下载的图像。

    我需要使用LockBits并首先将Image1与Image2进行比较,然后将Image3与Image2进行比较,然后将Image4与Image2进行比较。

    如果其中一个比较结果为真,那么如果所有比较都返回结果为false,则该方法返回true而不进行其余的比较。该方法返回false。

    这是一个测试我确实拿了3个pictureBoxes并放在左边和中间的图像里面的文字都有不同的文字,但两者都意味着雷达很接近。在右边,我有雷达打开的图像。我在同一区域的所有区域上绘制一个红色矩形,它们都在同一区域。

    images

1 个答案:

答案 0 :(得分:1)

使用此功能比较两个图像:

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;
    }

如果要比较多个,请将它们插入列表

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

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

然后:

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;
    }
}