AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

zwei Bitmaps vergleichen

Offene Frage von "KahPee"
Ein Thema von KahPee · begonnen am 1. Feb 2010 · letzter Beitrag vom 2. Feb 2010
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von Aphton
Aphton

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

Re: zwei Bitmaps vergleichen

  Alt 1. Feb 2010, 15:49
Zitat von KahPee:
Der Code macht seine Sache gut . Vielen Dank habs grad ausprobiert und der erste Test verlief erfolgreich

mfg KahPee
Ich möchte dich hiermit herzlichst darauf hinweisen - das wird es nicht lange... Siehe dazu Bild im Anhang.
Die Bilder in der Mitte und Rechts wurden durch die beiden Routinen (Algorithmen) gejagt.
Bei der Linken (Mittleren) sieht man schön dass nicht alle Pixel "angetastet" (schwarz gesetzt) werden, wohingegen die korrigierte Routine auch wirklich alle Pixel abtastet.

Edit:
Ich habe eine kleine ScanlineBitmap Unit angehangen. Mit TScanlineBitmap.Pixel[] bist du schneller dran, da es per Scanline arbeitet.

MfG
Miniaturansicht angehängter Grafiken
fehler_174.png  
Angehängte Dateien
Dateityp: pas uscanlinebitmap_533.pas (1,7 KB, 10x aufgerufen)
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Benutzerbild von KahPee
KahPee

Registriert seit: 12. Mai 2009
214 Beiträge
 
Turbo Delphi für Win32
 
#12

Re: zwei Bitmaps vergleichen

  Alt 1. Feb 2010, 17:02
Mh jetzt versteh ich schon wieder nur Bahnhof . Hatte mich gerade gefreut, dass das ganze so einfach lief

Also gut. Man vergleiche deinen und meinen Teil, da fällt auf, dass

Delphi-Quellcode:
//eine Abfrage dazukommt
bytes := PixelFormatBytes[bmp.PixelFormat];
  if bytes = 0 then
    Exit;

//das hier anstelle des meines Vergleiches steht
for k := 0 to bytes - 1 do
      begin
        Pixel^ := 0; //Zeiger??
        inc( Pixel ); //inc??
 //hier müsste der Vergleich der Pixel hin?!
       end;
Leider hab ich keine Ahnung von Zeigern und dem "inc()" kram. Wie sähe denn unter Berücksichtigung des Pixelformates meine angepasste Prozedur aus?

mfg KahPee

Edit:
Zitat von Aphton:
Edit:
Ich habe eine kleine ScanlineBitmap Unit angehangen. Mit TScanlineBitmap.Pixel[] bist du schneller dran, da es per Scanline arbeitet.
Arbeitet der obige Quellcode nicht auch per "Scanline"?
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

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

Re: zwei Bitmaps vergleichen

  Alt 1. Feb 2010, 17:56
Ja das tut es, aber mit der Unit bist du besser unterwegs, da du nur noch mehr Folgendes (bsp) machen musst:

Delphi-Quellcode:
var
  myBmp : TScanlineBitmap;
  x, y : Integer;
begin
  myBmp := TScanlineBitmap.Create;
  myBmp.LoadFromFile( '<Filename goes here>' );
  myBmp.UpdateScanlineBase();
  for y := 0 to myBmp.Height - 1 do
    for x := 0 to myBmp.Width - 1 do
    begin
      myBmp.Pixel[x,y] := $FF0000; // r = 0xFF, g = 0x00, b = 0x00
    end;
end;
Zu dem Problem mit den Zeigern:
1. Pixel zeigt auf den Start der RowLine (Scanline) -> Pixel := ...Scanline[y];
2. per Dereferenzierung (pointervariable + "^") greife ich nun direkt auf den Wert, auf den "gezeigt" wird zu und ändere sie:
Pixel^ := 0;
3. Inc( Variable ) = Increment = Erhöhe - entspricht --> Variable := Variable + 1;
Dh. der Zeiger Pixel zeigt nun auf die Addresse + 1

So wird solange verfahren, bis man am Ende der Zeile (scanLINE) angelangt ist.
Und wie schon beschrieben, besteht eine Zeile aus Width*Bytes Pixel, wobei Bytes PixelFormat entspricht -> 8, 16, 24 oder 32 Bit (es sind auch nur diese, die in der Unit uScanlineBitmap unterstützt werden)

Hoffe, ich konnte Licht ins Dunkel bringen...

Edit:
Zur Abfrage -> Falls Bytes = 0 -> dh <> 8, 16, 24 oder 32 Bit, dann brich ab, da wir nicht mit Bits rümkämpfen wollen.
Zur Schleife mit Schleifenvariable k -> der Pointer muss (Width * Bytss) mal inkrementiert werden, damit man an das Ende gelangt.
die kleine Schleife erhöht die Variable "Bytes" mal UND die Schleife wird Width mal aufgerufen.

Komisch zum Erklären, aber es sollte verständlich sein.

MfG
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Benutzerbild von KahPee
KahPee

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

Re: zwei Bitmaps vergleichen

  Alt 1. Feb 2010, 18:23
Ich habe das Bild im Moment als Tbitmap vorliegen.
myBmp.LoadFromFile( '<Filename goes here>' ); Das lädt ein Bitmap aus einer Datei, allerdings ist dieser vorgang schon längst passiert.. Kann ich an der Stelle irgendwie aus einer bestehenden Variable auslesen (Assign??) ?
Da das ganze nur ein kleiner Teil eines Programms ist und gerade diese Prozedur oft aufgerufen wird. Wäre interessant ob das wirklich eine schnelle variante ist, wenn das Bitmap jeweils einmal kopiert werden muss in eine weitere Variable. Deshalb hatte ich ja auch vor das ganze mit einem TBitmap zu machen.
Bleibt also letztendlich die Frage welche Variante schneller ist (die mit einmal kopieren (+ deine Unit einbinden) oder das ganze ohne deine Unit).

mfg Kahpee
  Mit Zitat antworten Zitat
Teekeks

Registriert seit: 19. Okt 2008
Ort: Dresden
765 Beiträge
 
FreePascal / Lazarus
 
#15

Re: zwei Bitmaps vergleichen

  Alt 1. Feb 2010, 19:02
Ich würde das so machen:
Dein Momentanes Bild in einen Stream (TStream) schieben und dann myBmp.LoadFromStream(stream) aufrufen.
Peter
"Div by zero Error" oder auch: "Es geht auch ohne Signatur!".
  Mit Zitat antworten Zitat
Benutzerbild von KahPee
KahPee

Registriert seit: 12. Mai 2009
214 Beiträge
 
Turbo Delphi für Win32
 
#16

Re: zwei Bitmaps vergleichen

  Alt 1. Feb 2010, 19:30
das ist dann doch noch langsamer, da es dann gleich zweimal kopiert wird...
  Mit Zitat antworten Zitat
Benutzerbild von KahPee
KahPee

Registriert seit: 12. Mai 2009
214 Beiträge
 
Turbo Delphi für Win32
 
#17

Re: zwei Bitmaps vergleichen

  Alt 1. Feb 2010, 23:28
So ich habe das ganze nochmal eingehender studiert. Unten habe ich meine ursprüngliche Funktion noch mal aufgegriffen und versucht anzupassen. Allerdings will das nocht nicht so wie ich will . Wie gebe ich die x-koordinate für den Pixel an? Mein Gefühl sagt, mir das ich nur 2-3 Zeilen von der Lösung weg bin. Aber ich hoffe ich täusche micht nicht . Es wäre nett wenn mir da nochmal auf die Sprünge geholfen werden könnte.

Delphi-Quellcode:
function Bitmapcompare(pic1, pic2: Tbitmap; Posx,posy: Integer): Boolean;
var
  Pix1, Pix2 : PByte;
  y, k, x : Integer;
  bytes : Byte;
  compix, matchpix: integer;
const
  PixelFormatBytes: Array[TPixelFormat] of Byte = ( 0, 0, 0, 1, 0, 2, 3, 4, 0 );
begin
  result:=false;
  bytes1 := PixelFormatBytes[pic1.PixelFormat];
  bytes2 := PixelFormatBytes[pic2.PixelFormat];
  
  if (bytes1 = 0) or (bytes2=0) then
    Exit; // PixelFormat wird nicht unterstützt ... kannst du dann gerne von mir aus umändern ...
  for y := 0 to pic2.Height - 1 do
  begin
    Pix1 := pic1.Scanline[posy+y];
    Pix2 := pic2.Scanline[y];
    for x := 0 to pic2.Width - 1 do
      for k := 0 to bytes2 - 1 do
      begin
    //VERGLEICH
        if pix1=pix2 then inc(matchpix); //x-Koordinate nicht berücksichtigt
    
        Pix1^ := 0;
        inc(Pix1);
        Pix2^ :=0;
        inc(pix2);
      
        inc(compix);
      end;
  end;

   if compix=matchpix then Result:=true;
end;
Übrigens vielen Dank für den Hinweis mit "Inc()", das dürfte mir in Zukunft ein wenig Tipparbeit ersparen

schon mal Vielen Dank

KahPee
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

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

Re: zwei Bitmaps vergleichen

  Alt 2. Feb 2010, 08:21
So dürfte das funzen:

Delphi-Quellcode:
function Bitmapcompare(pic1, pic2: Tbitmap; Posx,posy: Integer): Boolean;
var
  Pix1, Pix2 : PByte;
  y, k, x : Integer;
  bytes: Byte;
  compix, matchpix: integer;
const
  PixelFormatBytes: Array[TPixelFormat] of Byte = ( 0, 0, 0, 1, 0, 2, 3, 4, 0 );
begin
  result:=false;
  bytes := PixelFormatBytes[pic1.PixelFormat];
  if bytes <> PixelFormatBytes[pic2.PixelFormat] then
    Exit;
  if (bytes = 0) then
    Exit; // PixelFormat wird nicht unterstützt ... kannst du dann gerne von mir aus umändern ...
  if (pic1.Width <> pic2.Width) or (pic1.Height <> pic2.Height) then
    Exit;
  matchpix := 0;
  compix := 0;
  for y := 0 to pic2.Height - 1 do
  begin
    Pix1 := pic1.Scanline[posy+y];
    Pix2 := pic2.Scanline[y];
    inc( Pix2, Posx*bytes );
    for x := 0 to pic2.Width - 1 do
      for k := 0 to bytes - 1 do
      begin
    //VERGLEICH
        if pix1^= pix2^ then
          inc(matchpix); //x-Koordinate nicht berücksichtigt
        inc(Pix1);
        inc(pix2);
        inc(compix);
      end;
  end;
  if compix = matchpix then
    Result := true;
end;
Du hast eine Untergrenze (posx,posy) aber warum keine Obergrenze?

Ein Optimierungsvorschlag für die vorige Routine wäre das hier:

Delphi-Quellcode:
function Bitmapcompare(pic1, pic2: Tbitmap; Posx,posy: Integer): Boolean;
var
  Pix1, Pix2 : PByte;
  y, k, x : Integer;
  bytes: Byte;
const
  PixelFormatBytes: Array[TPixelFormat] of Byte = ( 0, 0, 0, 1, 0, 2, 3, 4, 0 );
begin
  result:=false;
  bytes := PixelFormatBytes[pic1.PixelFormat];
  if bytes <> PixelFormatBytes[pic2.PixelFormat] then
    Exit;
  if (bytes = 0) then
    Exit; // PixelFormat wird nicht unterstützt ... kannst du dann gerne von mir aus umändern ...
  if (pic1.Width <> pic2.Width) or (pic1.Height <> pic2.Height) then
    Exit;
  for y := 0 to pic2.Height - 1 do
  begin
    Pix1 := pic1.Scanline[posy+y];
    Pix2 := pic2.Scanline[y];
    inc( Pix2, Posx*bytes );
    for x := 0 to pic2.Width - 1 do
      for k := 0 to bytes - 1 do
      begin
    //VERGLEICH
        if pix1^ <> pix2^ then
          Exit; // ungleich, verlasse deshalb routine. Result ist in diesem Falle = False ...
        inc(Pix1);
        inc(pix2);
      end;
  end;
  // wenn wir es bis hierher geschafft haben, dann sind die bilder von (posx, posy) aufwärts gleich
  Result := true;
end;
Wie wärs denn mit soetwas?
Delphi-Quellcode:
{ Rückgabe = Gleichheit in % }
function CompareBitmap( bmp1, bmp2: TScanlineBitmap; const posX, posY, Width, Height: Integer ): Byte;
var
  x, y,
  TotalPixels,
  MatchingPixels : Integer;
  Bytes : Byte;
const
  PixelFormatBytes: Array[TPixelFormat] of Byte = ( 0, 0, 0, 1, 0, 2, 3, 4, 0 );
begin
  Result := 0;
  if (bmp1.Width <> bmp2.Width) or (bmp1.Height <> bmp2.Height) then
    Exit;
  if (bmp1.PixelFormat <> bmp2.PixelFormat) then
    Exit;
  Bytes := PixelFormatBytes[bmp1.PixelFormat];
  TotalPixels := (Height-posY) * (Width-posX);
  MatchingPixels := 0;
  for y := posY to Height - 1 do
    for x := posX to Width - 1 do
      if bmp1.Pixel[x,y] = bmp2.Pixel[x,y] then
        inc( MatchingPixels );
  Result := Round(MatchingPixels * 100 / TotalPixels);
end;
MfG
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Benutzerbild von KahPee
KahPee

Registriert seit: 12. Mai 2009
214 Beiträge
 
Turbo Delphi für Win32
 
#19

Re: zwei Bitmaps vergleichen

  Alt 2. Feb 2010, 09:08
if (pic1.Width <> pic2.Width) or (pic1.Height <> pic2.Height) then Das macht genau das was ich NICHT möchte. pic1 ist ja hat in den meisten Fällen (99% oder sogar mehr) eine größere Größe als pic1 sowohl in x als auch in y Richtung.
müsste es deshabl nicht so heißen?:
if (pic1.Width < pic2.Width) or (pic1.Height < pic2.Height) then //für den Fall, dass Bild1 in einer Richtung kleiner ist Außerdem hab ich hier was gefunden.. Müsste das an markierter Stelle nicht Pix1 statt Pix2 heißen?
Delphi-Quellcode:
for y := 0 to pic2.Height - 1 do
  begin
    Pix1 := pic1.Scanline[posy+y];
    Pix2 := pic2.Scanline[y];
    inc( Pix1, Posx*bytes ); //Position wird bei dem größeren! Bild verschoben
    for x := 0 to pic2.Width - 1 do
      for k := 0 to bytes - 1 do
      begin
    //VERGLEICH
        if pix1^= pix2^ then
          inc(matchpix);
Ansonsten sieht der 2. Vorschlag schon besser aus, der bricht direkt ab, wenn es keine Übereinstimmung gibt. Das spart Rechenzeit .
Die Prozentangabe find ich nett, verfehlt aber in meinem speziellen Fall den Zweck, bei geht es ja nur um 100% Übereinstimmung ja oder nein. von der 3. Prozedur möchte ich wie schon oben bemerkt Abstand nehmen (TscanlineBitmap<>Bitmap {zu viele Konvertierungen wären nötig -> kostet Zeit}; außerdem verstehe ich das andere noch halbwegs )

Es gibt keine Obergrenze weil das 2. Bild als das kleinere (in x und y Richtung) komplett in dem ersten drin sein soll (an einer bestimmten Stelle). D.h. das zweite Bild besteht nur aus dem Ausschnitt den ich haben will. Obergrenze ist also (pic2.height-1 bzw. pic2.width-1)


mfg KahPee
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

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

Re: zwei Bitmaps vergleichen

  Alt 2. Feb 2010, 12:16
Ja sorry, da fehlt noch ein
inc() bei Pix1

MfG
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:29 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz