• 此资源收集自网络。 算法采用比较两幅图片的byte流是否相同来判断图片是否相同比较速度较慢,由于没有找到类似的资源,也就将就用了。
  • MSDN的一位技术人员告诉大家一个在C#中进行图像一致性比较的简易算法。一般的情况下,人们习惯的轮询图像中的每一个像素进行比对,如果出现一个像素点的不同则判断两张照片不一致。但这样做的缺点是显而易见的...

    MSDN的一位技术人员告诉大家一个在C#中进行图像一致性比较的简易算法。一般的情况下,人们习惯的轮询图像中的每一个像素进行比对,如果出现一个像素点的不同则判断两张照片不一致。但这样做的缺点是显而易见的:大量的查询会显著拖慢系统速度,如果要比较的图像很多则可能导致系统挂掉。新的思路是把图像文件的数据流转化成一串Base64字串,然后只要比较这些字串就可以了。作者测试了256*256以下大小的一些图片,结果完全正确而且速度明显加快。来看他是如何实现的吧。

            /// <summary>
            /// 比较两张图片是否完全一样
            /// 
            /// 速度慢,但匹配精确
            /// 
            /// (方法:匹配两张图片的每一个像素)
            /// </summary>        
            private bool ImageCompareArray(Bitmap firstImage, Bitmap secondImage)
            {
                bool flag = true;
                string firstPixel;
                string secondPixel;
                if (firstImage.Width == secondImage.Width && firstImage.Height == secondImage.Height)
                {
                    for (int i = 0; i < firstImage.Width; i++)
                    {
                        for (int j = 0; j < firstImage.Height; j++)
                        {
                            firstPixel = firstImage.GetPixel(i, j).ToString();
                            secondPixel = secondImage.GetPixel(i, j).ToString();
                            if (firstPixel != secondPixel)
                            {
                                flag = false; break;
                            }
                        }
                    }
                    if (flag == false)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    return false;
                }
            }
    
    
            /// <summary>
            /// 比较两张图片是否完全一样
            /// 
            /// 速度快,但对大图片可能有些误差
            /// 
            /// (方法:将图片转换为Base64后,匹配Base64)
            /// </summary>
            public static bool ImageCompareString(Bitmap firstImage, Bitmap secondImage)
            {
                MemoryStream ms = new MemoryStream();
                firstImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                String firstBitmap = Convert.ToBase64String(ms.ToArray());
                ms.Position = 0;
                secondImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                String secondBitmap = Convert.ToBase64String(ms.ToArray());
                if (firstBitmap.Equals(secondBitmap))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }


    测试了大量图片,只要改动一个像素点,新方法都可以检测出不同。不过目前为止还没有对500*600分辨率以上的图像进行测试。

    运行大量测试以后,Base64方法的平均测试速度为每对照片0.1s。但是,使用传统的数组方法快慢则随图片而有明显差别。如果是完全一致的图片需要平均每对1.8s,检测出不同则只需要平均每对0.05s。综合看来匹配图片流的Base64编码在速度上具有优势。

    展开全文
  • c#查找图片中相似图片代码,已测试通过,为完整的C#工程
  • C#对比图片相似度

    2014-04-26 10:59:54
    Krawetz博士的这篇文章, 实现这种功能的关键技术叫做"感知哈希算法"(Perceptual Hash Algorithm), 意思是为图片生成一个指纹(字符串格式), 两张图片的指纹越相似, 说明两张图片就越相似. 但关键是如何根据图片计算...

        参考Neal Krawetz博士的这篇文章, 实现这种功能的关键技术叫做"感知哈希算法"(Perceptual Hash Algorithm), 意思是为图片生成一个指纹(字符串格式), 两张图片的指纹越相似, 说明两张图片就越相似. 但关键是如何根据图片计算出"指纹"呢? 下面用最简单的步骤来说明一下原理:

    第一步 缩小图片尺寸

            将图片缩小到8x8的尺寸, 总共64个像素. 这一步的作用是去除各种图片尺寸和图片比例的差异, 只保留结构、明暗等基本信息.

            

    第二步 转为灰度图片

             将缩小后的图片, 转为64级灰度图片.

            

    第三步 计算灰度平均值

             计算图片中所有像素的灰度平均值

    第四步 比较像素的灰度

            将每个像素的灰度与平均值进行比较, 如果大于或等于平均值记为1, 小于平均值记为0.

    第五步 计算哈希值

             将上一步的比较结果, 组合在一起, 就构成了一个64位的二进制整数, 这就是这张图片的指纹.

    第六步 对比图片指纹

            得到图片的指纹后, 就可以对比不同的图片的指纹, 计算出64位中有多少位是不一样的. 如果不相同的数据位数不超过5, 就说明两张图片很相似, 如果大于10, 说明它们是两张不同的图片.

    代码实现 (C#版本)

            下面我用C#代码根据上一节所阐述的步骤实现一下.

     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    using System;
    using System.IO;
    using System.Drawing;
     
    namespace SimilarPhoto
    {
        class SimilarPhoto
        {
            Image SourceImg;
     
            public SimilarPhoto(string filePath)
            {
                SourceImg = Image.FromFile(filePath);
            }
     
            public SimilarPhoto(Stream stream)
            {
                SourceImg = Image.FromStream(stream);
            }
     
            public String GetHash()
            {
                Image image = ReduceSize();
                Byte[] grayValues = ReduceColor(image);
                Byte average = CalcAverage(grayValues);
                String reslut = ComputeBits(grayValues, average);
                return reslut;
            }
     
            // Step 1 : Reduce size to 8*8
            private Image ReduceSize(int width = 8, int height = 8)
            {
                Image image = SourceImg.GetThumbnailImage(width, height, () => { return false; }, IntPtr.Zero);
                return image;
            }
     
            // Step 2 : Reduce Color
            private Byte[] ReduceColor(Image image)
            {
                Bitmap bitMap = new Bitmap(image);
                Byte[] grayValues = new Byte[image.Width * image.Height];
     
                for(int x = 0; x<image.Width; x++)
                    for (int y = 0; y < image.Height; y++)
                    {
                        Color color = bitMap.GetPixel(x, y);
                        byte grayValue = (byte)((color.R * 30 + color.G * 59 + color.B * 11) / 100);
                        grayValues[x * image.Width + y] = grayValue;
                    }
                return grayValues;
            }
     
            // Step 3 : Average the colors
            private Byte CalcAverage(byte[] values)
            {
                int sum = 0;
                for (int i = 0; i < values.Length; i++)
                    sum += (int)values[i];
                return Convert.ToByte(sum / values.Length);
            }
     
            // Step 4 : Compute the bits
            private String ComputeBits(byte[] values, byte averageValue)
            {
                char[] result = new char[values.Length];
                for (int i = 0; i < values.Length; i++)
                {
                    if (values[i] < averageValue)
                        result[i] = '0';
                    else
                        result[i] = '1';
                }
                return new String(result);
            }
     
            // Compare hash
            public static Int32 CalcSimilarDegree(string a, string b)
            {
                if (a.Length != b.Length)
                    throw new ArgumentException();
                int count = 0;
                for (int i = 0; i < a.Length; i++)
                {
                    if (a[i] != b[i])
                        count++;
                }
                return count;
            }
        }
    }

            谷歌服务器里的图片数量是百亿级别的, 我电脑里的图片数量当然没法比, 但以前做过爬虫程序, 电脑里有40,000多人的头像照片, 就拿它们作为对比结果吧! 我计算出这些图片的"指纹", 放在一个txt文本中, 格式如下.

            用ASP.NET写一个简单的页面, 允许用户上传一张图片, 后台计算出该图片的指纹, 并与txt文本中各图片的指纹对比, 整理出结果显示在页面中, 效果如下:

    本文地址: http://www.cnblogs.com/technology/archive/2012/07/12/Perceptual-Hash-Algorithm.html

    展开全文
  • #region 判断图片是否一致 /// /// 判断图片是否一致 /// /// 图片一 /// 图片二 /// 是否一致 public bool IsSameImg(Bitmap img, Bitmap bmp) { //大小不一致
    #region 判断图片是否一致
            /// <summary>
            /// 判断图片是否一致
            /// </summary>
            /// <param name="img">图片一</param>
            /// <param name="bmp">图片二</param>
            /// <returns>是否一致</returns>
            public bool IsSameImg(Bitmap img, Bitmap bmp)
            {
                //大小不一致
                if (img != null && bmp != null && img.Width == bmp.Width && img.Height == bmp.Height)
                {
                    //将图片一锁定到内存
                    BitmapData imgData_i = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
                    IntPtr ipr_i = imgData_i.Scan0;
                    int length_i = imgData_i.Width * imgData_i.Height * 3;
                    byte[] imgValue_i = new byte[length_i];
                    Marshal.Copy(ipr_i, imgValue_i, 0, length_i);
                    img.UnlockBits(imgData_i);
                    //将图片二锁定到内存
                    BitmapData imgData_b = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
                    IntPtr ipr_b = imgData_b.Scan0;
                    int length_b = imgData_b.Width * imgData_b.Height * 3;
                    byte[] imgValue_b = new byte[length_b];
                    Marshal.Copy(ipr_b, imgValue_b, 0, length_b);
                    bmp.UnlockBits(imgData_b);
                    //长度不相同
                    if (length_i != length_b)
                    {
                        return false;
                    }
                    else
                    {
                        //循环判断值
                        for (int i = 0; i < length_i; i++)
                        {
                            //不一致
                            if (imgValue_i[i] != imgValue_b[i])
                            {
                                return false;
                            }
                        }
                        return true;
                    }
                }
                else
                {
                    return false;
                }
            }
            #endregion


    展开全文
  • 一般的情况下,人们习惯的轮询图像中的每一个...但这样做的缺点是显而易见的:大量的查询会显著拖慢系统速度,如果要比较的图像很多则可能导致系统挂掉。新的思路是把图像文件的数据流转化成一串Base64字串,然后...

    原文 http://blog.csdn.net/summer_dream_journey/article/details/8980312

    一般的情况下,人们习惯的轮询图像中的每一个像素进行比对,如果出现一个像素点的不同则判断两张照片不一致。但这样做的缺点是显而易见的:大量的查询会显著拖慢系统速度,如果要比较的图像很多则可能导致系统挂掉。新的思路是把图像文件的数据流转化成一串Base64字串,然后只要比较这些字串就可以了。作者测试了256*256以下大小的一些图片,结果完全正确而且速度明显加快。来看他是如何实现的吧。

    传统的像素比对方法:

    1. private bool ImageCompareArray(Bitmap firstImage, Bitmap secondImage)  
    2.  {  
    3.      bool flag = true;  
    4.      string firstPixel;  
    5.      string secondPixel;  
    6.    
    7.      if (firstImage.Width == secondImage.Width  
    8.          && firstImage.Height == secondImage.Height)  
    9.      {  
    10.           for (int i = 0; i < firstImage.Width; i++)  
    11.           {  
    12.               for (int j = 0; j < firstImage.Height; j++)  
    13.               {  
    14.                   firstPixel = firstImage.GetPixel(i, j).ToString();  
    15.                   secondPixel = secondImage.GetPixel(i, j).ToString();  
    16.                   if (firstPixel != secondPixel)  
    17.                   {  
    18.                       flag = false;  
    19.                       break;  
    20.                   }  
    21.               }  
    22.           }  
    23.     
    24.           if (flag == false)  
    25.           {  
    26.               return false;  
    27.           }  
    28.           else  
    29.           {  
    30.               return true;  
    31.           }  
    32.       }  
    33.       else  
    34.       {  
    35.           return false;  
    36.       }  
    37.   }  

     

    改良后的代码:

    1. public static bool ImageCompareString(Bitmap firstImage, Bitmap secondImage)  
    2.   {  
    3.       MemoryStream ms = new MemoryStream();  
    4.       firstImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);  
    5.       String firstBitmap = Convert.ToBase64String(ms.ToArray());  
    6.       ms.Position = 0;  
    7.     
    8.       secondImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);  
    9.       String secondBitmap = Convert.ToBase64String(ms.ToArray());  
    10.     
    11.       if (firstBitmap.Equals(secondBitmap))  
    12.       {  
    13.           return true;  
    14.       }  
    15.       else  
    16.       {  
    17.           return false;  
    18.       }  
    19.   }  


    作者测试了大量图片,只要改动一个像素点,新方法都可以检测出不同。不过目前为止还没有对500*600分辨率以上的图像进行测试。
    运行大量测试以后,Base64方法的平均测试速度为每对照片0.1s。但是,使用传统的数组方法快慢则随图片而有明显差别。如果是完全一致的图片需要平均每对1.8s,检测出不同则只需要平均每对0.05s。综合看来新方法在速度上具有优势。

    展开全文
  • c#高效比对大量图片

    2019-07-17 16:19:51
    比较图片的方法  以前传统的比较方式是遍历图片中... 所以微软给我们提供了另外一种比对的方法,能够正确,高效的比对出两张图片是否相同。这种方法的原理是:将图片保存到数据流中然后使用Convert.ToBase64Str...

     

    比较图片的方法

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

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

    按 Ctrl+C 复制代码

     

    按 Ctrl+C 复制代码

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

     

    大量图片的比较

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

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

       

    复制代码

     1   public static List<Dictionary<string, string>> chekImgss(string filePath)
     2         {
     3             
     4             List<Dictionary<string, string>> liststr = new List<Dictionary<string, string>>();
     5             DirectoryInfo dir = new DirectoryInfo(filePath);
     6             FileInfo[] files = dir.GetFiles();
     7             foreach (FileInfo fileInfo in files)
     8             {
     9                 Dictionary<string, string> dic = new Dictionary<string, string>();
    10                 string ex = fileInfo.Extension;
    11                 if (ex == ".jpg" || ex == ".png")
    12                 {
    13                     MemoryStream ms1 = new MemoryStream();
    14                     Image image2 = Image.FromFile(filePath + fileInfo.Name);
    15                     image2.Save(ms1, System.Drawing.Imaging.ImageFormat.Jpeg);
    16                    
    17                     string imgBase64 = Convert.ToBase64String(ms1.ToArray());
    18 
    19                     dic["base64"] = imgBase64;
    20                     dic["imgName"] = fileInfo.Name;
    21                     liststr.Add(dic);
    22                 }
    23             }
    24 
    25             return liststr;
    26         }

    复制代码

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

       

    复制代码

     1         /// <summary>
     2         /// 对数组进行深拷贝
     3         /// </summary>
     4         /// <param name="files"></param>
     5         /// <returns></returns>
     6         public static List<Dictionary<string, string>> CopyList(List<Dictionary<string, string>> files)
     7         {
     8             MemoryStream ms = new MemoryStream();//序列化
     9             BinaryFormatter bf = new BinaryFormatter();
    10             bf.Serialize(ms, files);
    11             ms.Position = 0;
    12 
    13             List<Dictionary<string, string>> array3 = (List<Dictionary<string, string>>)bf.Deserialize(ms);  //反序列化
    14             return array3;
    15         }
    16 
    17         /// <summary>
    18         /// 比较图片
    19         /// </summary>
    20         /// <param name="listDic"></param>
    21         /// <param name="filePath"></param>
    22         /// <returns></returns>
    23         public static List<Dictionary<object, string>> chekImg2(List<Dictionary<string, string>> listDic,string filePath)
    24         {
    25             List<Dictionary<object, string>> list = new List<Dictionary<object, string>>();
    26 
    27             DirectoryInfo dir = new DirectoryInfo(filePath);
    28             var files = dir.GetFiles().ToList();
    29 
    30             for (int j = 0; j < listDic.Count; j++)
    31             {
    32                 var file = listDic[j];
    33 
    34                 
    35                 var fileList = CopyList(listDic);
    36                 var index = 0;
    37                 var isFirst = false;
    38                 Dictionary<object, string> dic = new Dictionary<object, string>();
    39                 for (int i = 0; i < fileList.Count; i++)
    40                 {
    41                     var fileInfo = fileList[i];
    42 
    43                     if (file["imgName"] == fileInfo["imgName"])
    44                     {
    45                         fileList.Remove(fileInfo);
    46                         i -= 1;
    47                         continue;
    48                     }
    49                     //使用equals比普通的,string==string 高效很多倍
    50                     if (file["base64"].Equals(fileInfo["base64"]))
    51                     {
    52                         if (!isFirst)
    53                         {
    54                             dic[++index] = file["imgName"];
    55                             isFirst = true;
    56                         }
    57                         dic[++index] = fileInfo["imgName"];
    58 
    59                         fileList.Remove(fileInfo);
    60 
    61                         listDic.Remove(listDic.Where(c => c.Values.Contains(fileInfo["imgName"])).FirstOrDefault());
    62                         i -= 1;
    63                     }
    64                     else
    65                     {
    66                         fileList.Remove(fileInfo);
    67                         i -= 1;
    68                     }
    69 
    70                 }
    71 
    72                 if (dic.Keys.Count > 0)
    73                 {
    74                     list.Add(dic);
    75                     listDic.Remove(file);
    76                     j -= 1;
    77                 }
    78                 else
    79                 {
    80                     listDic.Remove(file);
    81                     j -= 1;
    82                 }
    83             }
    84             return list;
    85         }

    复制代码

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

     

    总结

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

    展开全文
  • C#图片比较

    2020-07-12 23:31:10
    对两个图片比较,判断两个图片在允许有差距的范围内是否相等
  • C# 判断两张图片是否一致的快速方法。 代码: [code="java"]#region 判断图片是否一致 /// /// 判断图片是否一致 /// /// 图片一 /// 图片二 /// 是否一致 public bool IsSameImg(Bitmap ...
  • 需求就是对比服务器和本地2个图片一致性,如果超过90%一致 则用本地图片覆盖服务器图片. C++ 用 openCV组件库 C# 用 emgu CV 组件库 PHP 直接用内置标准函数 先将图片打称灰度 然后取得平均灰度值 ...
  • public int num = 0; /// <summary>... /// 判断服务器路径中的图片文件是否存在存在则累加统计 /// </summary> private int GetAcount(string name) { for (int i = 1; i < i +...
  • C#复制图片_并重命名

    2019-07-03 05:47:03
    首先是命名空间 using System.IO;using System.Data.OleDb;...//首先把图片的文件夹中的图片名用一个数组存放 string[] fileName = System.IO.Directory.GetFiles(@"C:\Documents and Settings...
  • 页面有大量图片,优化图片的加载方法 1. 图片懒加载,在页面上的未可视区域可以添加一个滚动条事件,判断图片位置与浏览器顶端的距离与页面的距离,如果前者小于后者,优先加载。  什么是图片懒加载问题:  ...
  • 参考Neal Krawetz博士的这篇文章, 实现这种功能的关键技术叫做"感知哈希算法"(Perceptual Hash Algorithm), 意思是为图片生成一个指纹(字符串格式), 两张图片的指纹越相似, 说明两张图片就越相似. 但关键是如何根据...
  • 早上看到stg609写的《Dot Net下实现屏幕图像差异获取v2.0》文章,想起自己以前写过的一个...当时用的简单实现方法就是:将两副图片同时按一定大小的小块“切分开”,再分别比较这些小块,如果某个块里出现有一个...
  • 在程序中会用到图片,有两种方法,一种是将图片放在运行文件夹中,直接调用,另一种是将图片放入资源文件中。方法一,一般在.exe文件同级创建文件夹,如“ico”,然后把图标放进去。在程序中代码采用相对路径调用。...
  • private void Form1_Load(object sender, EventArgs e) { string result = MatchHist(); MessageBox.Show(result); } //成对几何直方图匹配 private static strin
1 2 3 4 5 ... 20
收藏数 24,139
精华内容 9,655