图片相似度算法

来源:互联网 发布:在线字数统计软件 编辑:程序博客网 时间:2024/05/01 16:15

图片相似度算法,写了两次,但是都丢了,奇怪ing

最近在做一个连连看的小程序,帮助发现两个一样的图片。在网上找了一圈,终于了解了大致步骤。

1、图片大小规格化

    为了比较两个图像,应该使其大小完全一致,这里可以设置为两个图片中较大的那个大小,长宽。
   
function Resize(const Source: TBitmap; var Dest: TBitmap): Boolean;
begin
  if not Assigned(Dest) then
    Dest := TBitmap.Create;
  Dest.pixelformat := pf24bit;
  Dest.Width := BMPWIDTH;
  Dest.Height := BMPHEIGHT;
  Dest.Canvas.CopyRect(Rect(0, 0, Dest.Width - 1, Dest.Height - 1), Source.Canvas, Rect(0, 0, Source.Width - 1, Source.Height - 1));
end;

2、图像灰度化
    图像灰度化的方法有多种,这里介绍两种。一种是绝对平均值,一种是加权平均值。其实质就是将RGB三原色的色值相加,平均后赋予新值。不同的只是RGB三原色的权重不同。

绝对平均值   
function Gray1(const Source: TBitmap): Boolean;
var
  p                 : PByteArray;
  w                 : Integer;
  i, j              : Integer;
begin
  for i := 0 to Source.Height - 1 do
  begin
    p := Source.ScanLine[i];
    for j := 0 to (Source.Width - 1) do
    begin
      w := p[3 * j] + p[3 * j + 1] + p[3 * j + 2];
      w := w div 3;
      w := byte(w);
      p[3 * j] := w;
      p[3 * j + 1] := w;
      p[3 * j + 2] := w;
    end;
  end;
end;
   
加权平均值
function TForm1.Gray2(const Source: TBitmap): Boolean;
var
  p                 : PByteArray;
  w                 : Integer;
  i, j              : Integer;
begin
  for i := 0 to Source.Height - 1 do
  begin
    p := Source.ScanLine[i];
    for j := 0 to (Source.Width - 1) do
    begin
      w := (p[3 * j] * 28 + p[3 * j + 1] * 151 + p[3 * j + 2] * 77);
      w := w div 3;
      w := byte(w);
      p[3 * j] := w;
      p[3 * j + 1] := w;
      p[3 * j + 2] := w;
    end;
  end;
end;

3、抽取直方图
由于是灰度图,所以只会有256种灰度值,计算直方图

function GetHisogram(const Source: TBitmap; var His: TSamp): Boolean;
var
  i, j, c           : Integer;
  p                 : PByteArray;
begin
  try
    //取样
    for i := 0 to 255 do
      His[i] := 0;

    for i := 0 to Source.Height - 1 do
    begin
      p := Source.ScanLine[i];
      for j := 0 to Source.Width - 1 do
      begin
        c := p^[j * 3];
        Inc(His[c]);
      end;
    end;
  finally
    tb.Free;
  end;
end;

4、判断相似度

 

这里采用的是一个公式,,g,s分别为两附图片的直方图,N为直方图抽样个数。

 

function GetSimilar(const HisA, HisB: TSamp): Double;
var
  i, j              : Integer;

  function DivideAbs(const NumA, NumB: Integer): Double;
  var
    Tabs            : Integer;
  begin
    Tabs := Abs(NumA - NumB);
    if NumA >= NumB then
      Result := NumA
    else
      Result := NumB;

    if Result <> 0 then
      Result := Tabs / Result;
  end;
begin
  Result := 0.0;
  if Length(HisA) <> Length(HisB) then
    Exit;

  for i := 0 to Length(HisA) do
  begin
    Result := Result + 1 - DivideAbs(HisA[i], HisB[i]);
  end;

  Result := Result / Length(HisA);
end;

原创粉丝点击