大学IT网 - 最懂大学生的IT学习网站! QQ资料交流群:367606806
当前位置:大学IT网 > C#技巧 > c#高效比对图片是否相同

c#高效比对图片是否相同

关键词:高效比对图片  阅读(598) 赞(11)

[摘要]微软给我们提供了另外一种比对的方法,能够正确,高效的比对出两张图片的是否相同。这种方法的原理是:将图片保存到数据流中然后使用Convert.ToBase64String将数据流转换为字符串,那么我们只需要比对两张图片的字符串就ok了。

比较图片的方法

  以前传统的比较方式是遍历图片中的每一个像素,然后进行比对。这样的比对在少量图片的比对上虽然效率低一点,但是也没有什么不好。但是在大量图片比对的时候,过长的反应时间和对服务器比较高的消耗肯定是不行的。

  所以微软给我们提供了另外一种比对的方法,能够正确,高效的比对出两张图片的是否相同。这种方法的原理是:将图片保存到数据流中然后使用Convert.ToBase64String将数据流转换为字符串,那么我们只需要比对两张图片的字符串就ok了。代码如下:

   public bool CheckImg(string filePath1, string filePath2)
         {
         
            
             MemoryStream ms1 = new MemoryStream();
             Image image1 = Image.FromFile(filePath1);
             image1.Save(ms1, System.Drawing.Imaging.ImageFormat.Jpeg);
 
             string img1 = Convert.ToBase64String(ms1.ToArray());
 
             Image image2 = Image.FromFile(filePath2);
             image2.Save(ms1, System.Drawing.Imaging.ImageFormat.Jpeg);
             string img2 = Convert.ToBase64String(ms1.ToArray());
 
             if (img1.Equals(img2))
             {
                return true;
             }
             else
             {
                 return false;
             }
         }
比较图片

这种方法我使用控制台测试了下时间,时间大概为0.015s左右比较一张图片的时间。还是比较高效的。

大量图片的比较

比较两张图片能够满足需求,那么大量呢? 我这边也做了这种测试的。在450张图片中,选择出其中重复的图片,并展示出来。大概时间是16s左右,基本能够满足大部分的需求了。

  比较方法是,先讲450张图片,全部一次性转换为string类型,存放到一个数组里面,这样就避免了每次循环都要额外的去转换,使程序的效率降低很多。

   public static List<Dictionary<string, string>> chekImgss(string filePath)
         {
             
             List<Dictionary<string, string>> liststr = new List<Dictionary<string, string>>();
             DirectoryInfo dir = new DirectoryInfo(filePath);
             FileInfo[] files = dir.GetFiles();
             foreach (FileInfo fileInfo in files)
             {
                 Dictionary<string, string> dic = new Dictionary<string, string>();
                 string ex = fileInfo.Extension;
                 if (ex == ".jpg" || ex == ".png")
                 {
                     MemoryStream ms1 = new MemoryStream();
                     Image image2 = Image.FromFile(filePath + fileInfo.Name);
                     image2.Save(ms1, System.Drawing.Imaging.ImageFormat.Jpeg);
                    
                     string imgBase64 = Convert.ToBase64String(ms1.ToArray());
 
                     dic["base64"] = imgBase64;
                     dic["imgName"] = fileInfo.Name;
                     liststr.Add(dic);
                 }
             }
 
             return liststr;
         }

将图片的base64string和图片的名称存储在一个dictionary中,然后存储到list数组中。这样我们在比较的时候,只需要判断两个字符串是否相等就可以了。

   

         /// <summary>
         /// 对数组进行深拷贝
         /// </summary>
         /// <param name="files"></param>
         /// <returns></returns>
         public static List<Dictionary<string, string>> CopyList(List<Dictionary<string, string>> files)
         {
             MemoryStream ms = new MemoryStream();//序列化
             BinaryFormatter bf = new BinaryFormatter();
             bf.Serialize(ms, files);
             ms.Position = 0;
 
             List<Dictionary<string, string>> array3 = (List<Dictionary<string, string>>)bf.Deserialize(ms);  //反序列化
             return array3;
         }
 
         /// <summary>
         /// 比较图片
         /// </summary>
         /// <param name="listDic"></param>
         /// <param name="filePath"></param>
         /// <returns></returns>
         public static List<Dictionary<object, string>> chekImg2(List<Dictionary<string, string>> listDic,string filePath)
         {
             List<Dictionary<object, string>> list = new List<Dictionary<object, string>>();
 
             DirectoryInfo dir = new DirectoryInfo(filePath);
             var files = dir.GetFiles().ToList();
 
             for (int j = 0; j < listDic.Count; j++)
             {
                 var file = listDic[j];
 
                 
                 var fileList = CopyList(listDic);
                 var index = 0;
                 var isFirst = false;
                 Dictionary<object, string> dic = new Dictionary<object, string>();
                 for (int i = 0; i < fileList.Count; i++)
                 {
                     var fileInfo = fileList[i];
 
                     if (file["imgName"] == fileInfo["imgName"])
                     {
                         fileList.Remove(fileInfo);
                         i -= 1;
                         continue;
                     }
                     //使用equals比普通的,string==string 高效很多倍
                     if (file["base64"].Equals(fileInfo["base64"]))
                     {
                         if (!isFirst)
                         {
                             dic[++index] = file["imgName"];
                             isFirst = true;
                         }
                         dic[++index] = fileInfo["imgName"];
 
                         fileList.Remove(fileInfo);
 
                         listDic.Remove(listDic.Where(c => c.Values.Contains(fileInfo["imgName"])).FirstOrDefault());
                         i -= 1;
                     }
                     else
                     {
                         fileList.Remove(fileInfo);
                         i -= 1;
                     }
 
                 }
 
                 if (dic.Keys.Count > 0)
                 {
                     list.Add(dic);
                     listDic.Remove(file);
                     j -= 1;
                 }
                 else
                 {
                     listDic.Remove(file);
                     j -= 1;
                 }
             }
             return list;
         }

这样,我们就可以将完全相同的图片都取出来存放在一个dictionary中,每一组相同的都是一个dictionary,然后存放到list数组中。需要的时候遍历出来就可以了。

总结

大量比对的时候,最好先将图片转换为string吧。如果在两个for里面实现这个转换,时间会是现在的很多倍,因为造成了许多重复的转换。然后在比对的过程中,尽量将已经比对过的图片从数组中剔除,这样比对,你会发现越来越快。



相关评论