感知哈希算法——找出相似的图片
第一步 缩小图片尺寸
将图片缩小到16x16的尺寸, 总共256个像素. 这一步的作用是去除各种图片尺寸和图片比例的差异, 只保留结构、明暗等基本信息.
第二步 转为灰度图片
将缩小后的图片, 转为256级灰度图片.
第三步 计算灰度平均值
计算图片中所有像素的灰度平均值
第四步 比较像素的灰度
将每个像素的灰度与平均值进行比较, 如果大于或等于平均值记为1, 小于平均值记为0.
第五步 计算哈希值
将上一步的比较结果, 组合在一起, 就构成了一个64位的二进制整数, 这就是这张图片的指纹.
第六步 对比图片指纹
得到图片的指纹后, 就可以对比不同的图片的指纹, 计算出64位中有多少位是不一样的. 如果不相同的数据位数不超过5, 就说明两张图片很相似, 如果大于10, 说明它们是两张不同的图片.
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 90 91 92 93 94 95 | using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace B2BPicture { public class pictureCompare { Image SourceImg; public pictureCompare( string filePath) { SourceImg = Image.FromFile(filePath); } public pictureCompare(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 = 16, int height = 16) { 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; } } } |
调用生成hash码值
pictureCompare picture = new pictureCompare(@"C:\Users\yc\Desktop\图片\" + i+".png");
string hashvalue = picture.GetHash();
pictureCompare picture2 = new pictureCompare(@"C:\Users\yc\Desktop\图片\" + i+".png");
string hashvalue2 = picture2.GetHash();
hash码值对比
int count= pictureCompare.CalcSimilarDegree(hashvalue2 , hashvalue);
count小于10 基本就非常相似了,这样子就可以从图库找到相似图了
参考来源:https://www.cnblogs.com/technology/archive/2012/07/12/2588022.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异