Delphi图像Hash算法,关于图像相似度问题

图像Hash算法,有PHash,DHash,AHash,以下记录平均值哈希AHash的Delphi算法代码

var
  bmp: TBitmap = nil;
  //gb: TBitmap;
//算法原理:将图像缩放成8x8的灰度图,统计出像素平均值
//再遍历每个像素,值大于平均值记为二进制的1,否则记为0,最终得到一个64位的整数
function GetAHash(SrcBmp: TBitmap): Int64;
var
  I, J: Integer;
  P24, P8: PByte;
  AG, SG: Integer;
  AVG: Single;
  CT: array[0..7, 0..7] of Byte;
begin
  Result := 0;
  if bmp = nil then
  begin
    bmp := TBitmap.Create;
    bmp.Width := 8;
    bmp.Height := 8;
    bmp.PixelFormat := TPixelFormat.pf24bit;
  end;
//  if gb = nil then
//  begin
//    gb := TBitmap.Create;
//    gb.Width := 8;
//    gb.Height := 8;
//    gb.PixelFormat := TPixelFormat.pf24bit;
//  end;
  //TODO 可以高斯模糊一下,能去除杂点的影响
  SetStretchBltMode(bmp.Canvas.Handle, COLORONCOLOR); //设置指位图拉伸模式
  StretchBlt(bmp.Canvas.Handle, 0, 0, bmp.Width, bmp.Height, SrcBmp.Canvas.Handle, 0, 0, SrcBmp.Width, SrcBmp.Height, SRCCOPY); //从源矩形中复制一个位图到目标

  AG := 0;
  for I := 0 to 7 do
  begin
    P24 := bmp.ScanLine[I];
//    P8 := gb.ScanLine[I];
    for J := 0 to 7 do
    begin
      SG := Round(P24[0] * 0.11 + P24[1] * 0.59 + P24[2] * 0.3);
      CT[I, J] := SG;
//      P8[0] := CT[I, J];
//      P8[1] := CT[I, J];
//      P8[2] := CT[I, J];
      Inc(P8, 3);
      AG := AG + SG;
      Inc(P24, 3);
    end;
  end;

//  bmp.SaveToFile('D:\_rgb.bmp');
//  gb.SaveToFile('D:\_gray.bmp');

  AVG := AG / 64;
  Result := 0;
  for I := 0 to 7 do
    for J := 0 to 7 do
      Result := Result shl 1 or Ord(CT[I, J] > AVG);
end;

两个Hash值比较相似度,比较两个数有多少个不同的二进制位,即:海明距离

function Hamming(Hash1, Hash2: Int64): Integer;
var
  I: Integer;
  A: Int64;
begin
  Result := 0;
  //使用一个神奇的表达式 n&=(n-1)
  //参考:https://blog.csdn.net/u013243347/article/details/52220551
  A := Hash1 xor Hash2;
  while A <> 0 do
  begin
    A := A and (A -1);
    Inc(Result);
  end;
end;

最后,平均Hash仅适用于背景不变,前景部分变化的场景比较。

你可能感兴趣的:(Delphi,算法,图像处理)