簡體   English   中英

比較位圖列表中圖像的最佳方法是什么

[英]What is the best way to compare images in a bitmap list

我正在開發一個應用程序,可以在列表中加載多張圖片,並將列表中的每張圖片相互比較,以便找到重復的圖片。

所以首先我成功獲取圖片並將它們加載到IList<Bitmap>

 public IList<Bitmap> getPictures()
        {
            IList<Bitmap> pictures = new List<Bitmap>();

            string filepath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            DirectoryInfo d = new DirectoryInfo(filepath+ "\\Phone Pictures\\");
            foreach (var picture in d.GetFiles("*.png"))
            {
                pictures.Add(ConvertToBitmap(picture.FullName));
            }
                return pictures;
        }

比我使用的預制圖像比較算法:

public static CompareResult Compare(Bitmap bmp1, Bitmap bmp2)
        {
            CompareResult cr = CompareResult.ciCompareOk;

            //Test to see if we have the same size of image
            if (bmp1.Size != bmp2.Size)
            {
                cr = CompareResult.ciSizeMismatch;
            }
            else
            {
                //Convert each image to a byte array
                System.Drawing.ImageConverter ic =
                       new System.Drawing.ImageConverter();
                byte[] btImage1 = new byte[1];
                btImage1 = (byte[])ic.ConvertTo(bmp1, btImage1.GetType());
                byte[] btImage2 = new byte[1];
                btImage2 = (byte[])ic.ConvertTo(bmp2, btImage2.GetType());

                //Compute a hash for each image
                SHA256Managed shaM = new SHA256Managed();
                byte[] hash1 = shaM.ComputeHash(btImage1);
                byte[] hash2 = shaM.ComputeHash(btImage2);

                //Compare the hash values
                for (int i = 0; i < hash1.Length && i < hash2.Length
                                  && cr == CompareResult.ciCompareOk; i++)
                {
                    if (hash1[i] != hash2[i])
                        cr = CompareResult.ciPixelMismatch;
                }
            }
            return cr;
        } 

現在,這就是我嘗試調用算法並將其應用於我的已加載列表的方式:

public void ComparePictureList()
        {

            IList<Bitmap> picturesList = getPictures();

            foreach (var picture1 in picturesList)
            {
                foreach( var picture2 in picturesList)
                {
                    Compare(picture1, picture2);
                }
            }

        }

但是,是否有更好的方法將算法應用到列表中,我的意思是不是聲明2個循環picture1picture2而是.NET框架中有任何功能可以更好?

PS:對於任何想知道ConvertToBitmap是什么的人來說,就是這樣:

   public Bitmap ConvertToBitmap(string fileName)
        {
            Bitmap bitmap;
            using (Stream bmpStream = System.IO.File.Open(fileName, System.IO.FileMode.Open))
            {
                Image image = Image.FromStream(bmpStream);

                bitmap = new Bitmap(image);

            }
            return bitmap;
        }

我將避免為同一張圖片多次計算散列,並且只在這些圖片之間循環一次:

public static void Main(string[] args)
{
    var files = new Dictionary<string, string>();
    foreach (var file in Directory.GetFiles("c:\\", "*.png"))
    {
        files.Add(file, CalculateHash(file));
    }

    var duplicates = files.GroupBy(item => item.Value).Where(group => group.Count() > 1);
}

private static string CalculateHash(string file)
{
    using (var stream = File.OpenRead(file))
    {
        var sha = new SHA256Managed();
        var checksum = sha.ComputeHash(stream);
        return BitConverter.ToString(checksum).Replace("-", String.Empty);
    }
}
  1. 您無法確定具有相同哈希值的兩個圖像是否相等。

  2. 如果您的哈希函數使用圖像的所有字節,則可以更快地比較圖像的字節,而不是計算哈希並進行比較。

  3. 您需要多次計算每個圖像的哈希值。 您不需要這樣做。

我建議執行以下操作:

  1. 計算每個圖像的哈希值並將其存儲。

  2. 使用地圖或兩個循環來查找哈希沖突。

  3. 具有相同哈希值的圖像需要逐字節比較,以確保它們相等。

您已經在計算每個圖像的哈希,因此可以將其轉換為例如String ,然后僅使用Dictionary<String, Bitmap> ,其中Key將為哈希。 您可以使用ContainsKey快速確定列表中是否已ContainsKey圖像哈希。

由於您是通過流打開圖像文件的,因此有一種更簡單的方法可以從Stream計算哈希,如此處所述在C#中計算文件內容的哈希? 您可能必須倒帶流以讀取圖像。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM