Thema: FreePascal Grafiken erkennen. Library ?

Einzelnen Beitrag anzeigen

Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#14

AW: Grafiken erkennen. Library ?

  Alt 5. Mai 2012, 13:13
Hier, die einfache Variante mit SAD (Sum of Absolute Differences (siehe Wikipedia))

Delphi-Quellcode:
function findPicture(const Source, Picture: TBitmap): TPoint;
type
  TPRGBTripleRow = Array of PRGBTriple;
var
  SourceScanlineRow : TPRGBTripleRow;
  PictureScanlineRow : TPRGBTripleRow;
  function getRGBDifference(const ColorA, ColorB: PRGBTriple): Integer;
  begin
    Result := abs(ColorA.rgbtBlue - ColorB.rgbtBlue) +
              abs(ColorA.rgbtGreen - ColorB.rgbtGreen) +
              abs(ColorA.rgbtRed - ColorB.rgbtRed);
  end;
  function getPColor(const ScanlineRow: TPRGBTripleRow; const X, Y: Integer): PRGBTriple;
  begin
    Result := PRGBTriple(Integer(ScanlineRow[y]) + x * 3);
  end;
  procedure buildScanlineRows;
  var
    y: Integer;
  begin
    SetLength(SourceScanlineRow, Source.Height);
    for y := 0 to Source.Height - 1 do SourceScanlineRow[y] := Source.ScanLine[y];
    SetLength(PictureScanlineRow, Picture.Height);
    for y := 0 to Picture.Height - 1 do PictureScanlineRow[y] := Picture.ScanLine[y];
  end;
  function _findPicture: TPoint;
  var
    x, y, i, j : Integer;
    SAD : Integer;
    curSAD : Integer;
  begin
    SAD := -1; // not assigned
    for y := 0 to Source.Height - Picture.Height do
      for x := 0 to Source.Width - Picture.Width do
      begin
        curSAD := 0;
        for j := 0 to Picture.Height - 1 do
          for i := 0 to Picture.Width - 1 do
            inc(curSAD, getRGBDifference(getPColor(SourceScanlineRow, x + i, y + j), getPColor(PictureScanlineRow, i, j)));
        if (SAD = -1) or (curSAD < SAD) then
        begin
          SAD := curSAD;
          Result := Point(x, y);
          if SAD = 0 then Exit;
        end;
      end;
  end;
begin
  if (Picture.Width > Source.Width) or (Picture.Height > Source.Height) or
     (Picture.PixelFormat <> pf24bit) or (Source.PixelFormat <> pf24bit) then
    Result := Point(-1, -1)
  else
  begin
    buildScanlineRows;
    Result := _findPicture;
  end;
end;
Edit: Das liefert die linke obere Ecke des Bereiches. Der Bereich hat klarerweise dieselbe Dimension wie "Picture"
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG

Geändert von Aphton ( 5. Mai 2012 um 14:18 Uhr)
  Mit Zitat antworten Zitat