如何更改比较两个图像的方法更快?

时间:2013-12-19 04:30:56

标签: c# winforms

这是我今天使用的方法:

public static Bitmap CloudsOnly(Bitmap bitmapwithclouds, Bitmap bitmapwithoutclouds)
        {
            Color color;
            Color backgroundColor = Color.Black;

            CreateErrorsArray(bitmapwithclouds, bitmapwithoutclouds);

            int tolerance = tolerancenum * tolerancenumeric + tolerancenumeric * tolerancenumeric + tolerancenumeric * tolerancenumeric;
            Bitmap newbitmap = new Bitmap(512, 512);
            for (int x = 0; x < bitmapwithclouds.Width; x++)
            {
                for (int y = 0; y < bitmapwithclouds.Height; y++)
                {
                    int error = errorsArray[x, y];

                    if (error < tolerance)
                    {
                        color = backgroundColor;
                    }
                    else
                    {
                        color = bitmapwithclouds.GetPixel(x, y);
                    }
                    newbitmap.SetPixel(x, y, color);
                }
            }
            newbitmap.Save(@"d:\test\newbitmap.jpg");
            return newbitmap;
        }

但GetPixel很慢我搜索谷歌并发现一些使用LockBits的方法,例如这种方法:

private bool CompareBitmaps(Image left, Image right)
        {
            if (object.Equals(left, right))
                return true;
            if (left == null || right == null)
                return false;
            if (!left.Size.Equals(right.Size) || !left.PixelFormat.Equals(right.PixelFormat))
                return false;

            Bitmap leftBitmap = left as Bitmap;
            Bitmap rightBitmap = right as Bitmap;
            if (leftBitmap == null || rightBitmap == null)
                return true;

            #region Optimized code for performance

            int bytes = left.Width * left.Height * (Image.GetPixelFormatSize(left.PixelFormat) / 8);

            bool result = true;
            byte[] b1bytes = new byte[bytes];
            byte[] b2bytes = new byte[bytes];

            BitmapData bmd1 = leftBitmap.LockBits(new Rectangle(0, 0, leftBitmap.Width - 1, leftBitmap.Height - 1), ImageLockMode.ReadOnly, leftBitmap.PixelFormat);
            BitmapData bmd2 = rightBitmap.LockBits(new Rectangle(0, 0, rightBitmap.Width - 1, rightBitmap.Height - 1), ImageLockMode.ReadOnly, rightBitmap.PixelFormat);

            Marshal.Copy(bmd1.Scan0, b1bytes, 0, bytes);
            Marshal.Copy(bmd2.Scan0, b2bytes, 0, bytes);

            for (int n = 0; n <= bytes - 1; n++)
            {
                if (b1bytes[n] != b2bytes[n])
                {
                    result = false;
                    break;
                }
            }

            leftBitmap.UnlockBits(bmd1);
            rightBitmap.UnlockBits(bmd2);

            #endregion

            return result;
        }

但是这个只是告诉我一个图像是否与第二个图像相同。 我想使用上面的方法,但使用LockBits或更快一些。

如何更改上述第一个方法以更快?

2 个答案:

答案 0 :(得分:2)

GetPixel速度非常慢,如果您有多个像素并且不希望通过观看代码爬过图片来度过童年时间,请不要使用它。

您必须使用不安全的代码(非托管)来快速访问图片。请参阅此帖子以获取帮助: C# Bitmap using unsafe code

效果比较:C# Image Processing Performance - Unsafe vs. Safe code, Part II

答案 1 :(得分:-2)

我可以推荐一个天真的优化。 而不是手动比较结果数组中的每个字节,您可以使用哈希函数。这意味着下一个代码:

 for (int n = 0; n <= bytes - 1; n++)
            {
                if (b1bytes[n] != b2bytes[n])
                {
                    result = false;
                    break;
                }
            }

可以替换为

var sha1 = new SHA1CryptoServiceProvider();
return sha1.ComputeHash(b1bytes) == sha1.ComputeHash(b2bytes);

内置散列函数已得到很好的优化。