Hash算法有三種,分別為平均哈希算法(aHash)、感知哈希算法你(pHash)和差異哈哈希算法(dHash)。
針對以上三種的Hash算法詳解見博客園文章
https://www.cnblogs.com/Kalafinaian/p/11260808.html
本文實現針對平均哈希算法;
1 平均哈希算法(aHash)
1.1 算法步驟
平均哈希算法是三種Hash算法中最簡單的一種,它通過下面幾個步驟來獲得圖片的Hash值,這幾個步驟分別是(1) 縮放圖片;(2)轉灰度圖; (3) 算像素均值;(4)根據相似均值計算指紋。具體算法如下所示:
表1 aHash得到圖片Hash值地算法
| 縮放圖片 |
輸入圖片大小尺寸各異,為了統一圖片的輸入,統一將圖片尺寸縮放為8*8,一共得到了64個像素點。 |
| 轉灰度圖 |
輸入圖片有些為單通道灰度圖,有些RGB三通道彩色圖,有些為RGBA四通道彩色圖。也為了統一下一步輸入標准,將非單通道圖片都轉為單通道灰度圖。 其中RGB三通道轉單通道算法有下面幾種: 1.浮點算法:Gray=R0.3+G0.59+B0.11 2.整數方法:Gray=(R30+G59+B11)/100 3.移位方法:Gray =(R76+G151+B*28)>>8; 4.平均值法:Gray=(R+G+B)/3; 本Demo采用的該方法 5.僅取綠色:Gray=G; |
| 算像素均值 | 通過上一步可得一個8x8的整數矩陣G,計算這個矩陣中所有元素的平均值,假設其值為a |
| 據像素均值計算指紋 |
初始化輸入圖片的ahash = "" 從左到右一行一行地遍歷矩陣G每一個像素如果第i行j列元素G(i,j) >= a,則ahash += "1"如果第i行j列元素G(i,j) <a, 則ahash += "0" |
得到圖片的ahash值后,比較兩張圖片ahash值的漢明距離,通常認為漢明距離小於10的一組圖片為相似圖片。
Demo 界面/



獲取aHash函數如下:
function TForm1.GetHash(src: TBitmap; iType: Integer): Int64;
var
p: PByteArray;
bmp: TBitmap;
x, y: Integer;
gray, sum: Integer;
ct: array[0..7, 0..7] of Byte;
avg: Single;
ret: Int64;
begin
ret := 0;
case iType of
0: // aHash 平均哈希算法
begin
bmp := TBitmap.Create;
try
bmp.Assign(src);
bmp.Width := 8;
bmp.Height := 8;
bmp.PixelFormat := pf24bit;
sum := 0;
for y := 0 to 7 do
begin
p := bmp.ScanLine[y];
for x := 0 to 7 do
begin
//轉灰度圖 平均值法
gray := (p[3 * x + 2] + p[3 * x + 1] + p[3 * x]) div 3;
ct[y, x] := gray;
sum := sum + gray;
end;
end;
avg := sum/64;
for y := 0 to 7 do
for x := 0 to 7 do
ret := ret shl 1 or Ord(ct[y, x] > avg);
finally
bmp.Free;
end;
end;
1: // pHash 感知哈希算法
begin
end;
2: // dHash 差異哈希算法
begin
end;
end;
Result := ret;
end;
計算漢明距離函數:原理參考:https://blog.csdn.net/u013243347/article/details/52220551
function TForm1.Hamming(Hash1, Hash2: Int64): Integer;
var
A: Int64;
begin
Result := 0;
A := Hash1 xor Hash2;
while A<>0 do
begin
A := A and (A-1);
Inc(Result);
end;
end;
Demo 下載地址:https://download.csdn.net/download/huffmanlepand/11833317
