/* 第一步 縮小圖片尺寸 將圖片縮小到8x8的尺寸, 總共64個像素. 這一步的作用是去除各種圖片尺寸和圖片比例的差異, 只保留結構、明暗等基本資料. * * 第二步 轉為灰階圖片 將縮小後的圖片, 轉為64級灰階圖片 * * 第三步 計算灰階平均值 計算圖片中所有像素的灰階平均值 * * 第四步 比較像素的灰階 將每個像素的灰階與平均值進行比較, 如果大於或等於平均值記為1, 小於平均值記為0. * * 第五步 計算雜湊值 將上一步的比較結果, 組合在一起, 就構成了一個64位的二進位整數, 這就是這張圖片的指紋. * * 第六步 對比圖片指紋 得到圖片的指紋後, 就可以對比不同的圖片的指紋, 計算出64位中有多少位是不一樣的. 如果不相同的資料位元數不超過5, 就說明兩張圖片很相似, 如果大於10, 說明它們是兩張不同的圖片. */
using System;using System.Drawing;using System.IO;namespace SimilarPhoto{ class imghash { Image SourceImg; public imghash(string filePath) { SourceImg = Image.FromFile(filePath); } public imghash(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; } }}