Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Bilder schnell miteinander vergleichen (https://www.delphipraxis.net/80639-bilder-schnell-miteinander-vergleichen.html)

Flips 12. Nov 2006 21:16


Bilder schnell miteinander vergleichen
 
Hi.

Folgender Code ermöglicht das schnelle Vergleichen zweier Bitmaps und gibt, falls sie nicht identisch sind, ihre Unterschiede in Pixel aus. Der Algorithmus war ein Teil eines Jugend forscht Projektes und hat sich als schnellster unter vielen erwiesen. Ein Bild von 1024*768 wird auf einem AMD Athlon XP 2600+ @ 1,9 GHz in 4,4ms verglichen.

Delphi-Quellcode:

type
  PRGBTripleArray = ^TRGBTripleArray;
  TRGBTripleArray = array [0..50000000] of TRGBTriple;

function CompareImages(Image1,Image2:TBitmap):Int64;
var x,y:integer;
    P1,P2:PRGBTripleArray;
    summe1,summe2:integer;
begin
result := 0;
summe1 := 0;
summe2 := 0;
for y := 0 to Image1.Height -1 do
  begin
    P1 := Image1.ScanLine[y];
    P2 := Image2.ScanLine[y];
      if not CompareMem(p1,p2,Image1.Width*SizeOf(TRGBTriple)) then
        begin
          for x := 0 to Image1.Width-1 do
            begin
              inc(summe1,RGB(P1[x].rgbtRed,P1[x].rgbtGreen,P1[x].rgbtBlue));
              inc(summe2,RGB(P2[x].rgbtRed,P2[x].rgbtGreen,P2[x].rgbtBlue));
              if summe1 <> summe2 then
                begin
                  summe1 := 0;
                  summe2 := 0;
                  inc(result);
                end;
            end;
        end;
  end;
Application.ProcessMessages;
end;
Ein Aufruf könnte so erfolgen:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(IntToStr(CompareImages(Image1.Picture.Bitmap,Image2.Picture.Bitmap)));
end;
Bei Rückfragen einfach melden.
Hf, Flips :coder:

EDatabaseError 12. Nov 2006 21:49

Re: Bilder schnell miteinander vergleichen
 
kann es sein das es bei zu großen bildern ne AV auslöst?

mfg
tobi

Phantom1 12. Nov 2006 22:18

Re: Bilder schnell miteinander vergleichen
 
Zitat:

Zitat von EDatabaseError
kann es sein das es bei zu großen bildern ne AV auslöst?

der code oben dürfte auch bei großen bildern ok sein, es könnte aber eine AV kommen wenn man vergisst das pixelformat auf pf24bit zu stellen :wink:

Hab den Code von Flips mal optimiert, ist jetzt ca 4 mal schneller:
Delphi-Quellcode:
function CompareImages(Bitmap1, Bitmap2: TBitmap): LongWord;
var
  xy: integer;
  P1, P2: PInteger;
begin
  Result:=0;
  Bitmap1.PixelFormat:=pf32bit;
  Bitmap2.PixelFormat:=pf32bit;
  P1:=Bitmap1.ScanLine[Bitmap1.Height-1];
  P2:=Bitmap2.ScanLine[Bitmap2.Height-1];
  for xy:=1 to Bitmap1.Height*Bitmap1.Width do begin
    Inc(Result, Byte(P1^<>P2^));
    Inc(P1);
    Inc(P2);
  end;
end;
mfg

Flips 13. Nov 2006 15:48

Re: Bilder schnell miteinander vergleichen
 
Thx für das ganze Feedback. Ich will jetzt ned böse sein, finds ja nett das du den Code optimiert hast, aber dein Code is 6* langsamer :X

Igotcha 13. Nov 2006 16:04

Re: Bilder schnell miteinander vergleichen
 
Was bringt mir der Code aus dem Ursprungspost? Ist nicht böse gemeint ;-)

Hintergrund: Ich suche und versuche mich schon seit längerem sporadisch an einem Code, der 2 Bilder auf "Gleichheit" analysiert, um Doubletten in der privaten Bilderflut Herr zu werden.

Um 2 Bilder zu vergleichen, ob sie "identisch" sind, reicht ein Hash. Gleicher Hash = gleiche Bilder. Da nehme ich eine x-beliebige Hashfunktion.

Was nützt mir o.g. Code, wenn ich als Ergebnis bekomme, dass x Pixel unterschiedlich sind? Ich weiss, dass sie dann offenbar nicht "identisch" sind - aber das bekomme ich auch anders heraus.

2 Bilder sind bei mir aber auch "gleich", wenn sie z.B. inhaltlich gleich, aber in einer anderen Auflösung vorliegen und da hilft mir der o.g. Code nicht.

Viele Grüße
Igotcha

Flips 13. Nov 2006 16:15

Re: Bilder schnell miteinander vergleichen
 
Mhh gute Argumente^^
Klar, wenn man wissen will ob sie identisch sind nimmt man den Hash.
Klar, es geht nur bei Bildern gleicher Auflösung.

Aber der Code ist so gemeint wie dieser hier. Ich hab mal einen gebraucht der mir aus 2 auflösungsgleichen Bildern die unterschiedlichen Pixel liefert und gemerkt, dass im Internet befindliche Algo's einfach viel zu langsam sind. Deshalb hab ich mir gedacht, probier ich die mal zu optimieren. Und da mir das gelungen ist (ob das andere jetzt auch so sehn sei dahingestellt), wieso auch nicht andere daran teilhaben lassen? ;-)
Ich meins doch nur gut :wink:

:pale: :duck:

Phantom1 13. Nov 2006 16:29

Re: Bilder schnell miteinander vergleichen
 
Zitat:

Zitat von Flips
Thx für das ganze Feedback. Ich will jetzt ned böse sein, finds ja nett das du den Code optimiert hast, aber dein Code is 6* langsamer :X

Das kann ich so aber nich stehen lassen :wink: wie hast du denn die zeit gemessen?

ich messe die Zeit so hier:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  start, stop: Int64;
  i: Integer;
begin
  start:=GetTickCount;

  for i:=1 to 500 do
    CompareImages(image1.Picture.Bitmap, Image2.Picture.Bitmap);

  stop:=GetTickCount;
  Caption:=floattostr(stop-start);
end;
Insgesamt 500 durchläufe um messungenauigkeiten zu verhindern, dein Code braucht da 5,2 sek und im vergleich dazu mein code nur 1,7 sek.

Getestet habe ich das mit 2 verschiedenen Bildern (1024x768) auf einem Athlon64 X2 4600+ und 2GB RAM.

mfg

Flips 13. Nov 2006 16:56

Re: Bilder schnell miteinander vergleichen
 
Liste der Anhänge anzeigen (Anzahl: 2)
ich hab sie mit dem QueryPerformanceCounter gemessen.
Delphi-Quellcode:
procedure CompareImagesWithTesting(Image1,Image2:TBitmap);
var x,y:integer;
    P1,P2:PRGBTripleArray;
    summe1,summe2:integer;
begin
differents := 0;
summe1 := 0;
summe2 := 0;
QueryPerformanceFrequency(freq);
QueryPerformanceCounter(zeit1);
for y := 0 to Image1.Height -1 do
  begin
    P1 := Image1.ScanLine[y];
    P2 := Image2.ScanLine[y];
      if not CompareMem(p1,p2,Image1.Width*SizeOf(TRGBTriple)) then
        begin
          for x := 0 to Image1.Width-1 do
            begin
              inc(summe1,RGB(P1[x].rgbtRed,P1[x].rgbtGreen,P1[x].rgbtBlue));
              inc(summe2,RGB(P2[x].rgbtRed,P2[x].rgbtGreen,P2[x].rgbtBlue));
              if summe1 <> summe2 then
                begin
                  summe1 := 0;
                  summe2 := 0;
                  inc(differents);
                end;
            end;
        end;
  end;


QueryPerformanceCounter(zeit2);
Application.ProcessMessages;
Form1.Memo1.Lines.Add(FormatFloat('0.0000', (zeit2 - zeit1) * 1000 / freq));
Form1.Memo2.Lines.Add(IntToStr(differents));
end;
Hab ja für Jufo noch en Programm geschrieben. 100 Durchläufe

alzaimar 13. Nov 2006 18:10

Re: Bilder schnell miteinander vergleichen
 
Die beiden Algorithmen sind so nicht vergleichbar, da Phantoms Algo zunächst auf 32 bit Farbtiefe umrechnet. Auch ohne diese Umrechnung kann man die Verfahren nicht vergleichen, da eben das zugrundeliegende Pixel unterschiedlich ist.

Flips' Verfahren ist aber wirklich ordendlich schnell. Sofern die Bilder identisch oder doch Zeilenweise hinreichend gleich sind, denn er prüft zunächst mit CompareMem, ob die beiden 'Scanlines' überhaupt Unterschiede aufzeigen.

Wenn schon, dann kann man ja gleich die gesamte Bitmap per CompareMem vergleichen (bringt nochmal 10%).

Wie schon erwähnt, ist der Algorithmus nett, aber nicht zu gebrauchen. Immerhin ist der ungewöhnliche Vergleich interessant.

Viel interessanter wäre es, einen Ähnlichkeitsindex von zwei beliebigen Bildern zu erstellen, die unterschiedlich kodiert (JPEG vs. BMP) und in unterschiedlichen Farbtiefen und Auflösungen vorliegen.

Flips 13. Nov 2006 18:19

Re: Bilder schnell miteinander vergleichen
 
Zitat:

Flips' Verfahren ist aber wirklich ordendlich schnell.
Endlich ma ne positive Meinung :stupid:

Zitat:

Wie schon erwähnt, ist der Algorithmus nett, aber nicht zu gebrauchen. Immerhin ist der ungewöhnliche Vergleich interessant.
Hachja wie aufbauend :-D :-D :-D
Nee jetzt ma im Ernst, klingt vll als wär ich schwer von Begriff aber warum ist der jetzt ned zu gebrauchen? Hab das ned so ganz verstanden? :wink: :stupid:

alzaimar 13. Nov 2006 18:32

Re: Bilder schnell miteinander vergleichen
 
Wenn Du wissen willst, ob zwei Bilder identisch sind, oder nicht, dann reicht dieser Code:
Delphi-Quellcode:
Function CompareBitmap (Bitmap1, Bitmap2 : TBitmap) : Integer;
  If CompareMem (Bitmap1.Scanline[Bitmap1.Height - 1], Bitmap2.ScanLine [Bitmap2.Height - 1], Bitmap1.Width*Bitmap1.Height*SizeOf(TRGBTriple)) Then
    Result := 0
  Else
    Result := 1
End;
Dieses Fragment liefert 1, wenn die Bitmaps ungleich sind und 0, wenn sie identisch sind. Das ist nochmal 10% schneller als Dein Code. Die Voraussetzungen sind die Gleichen: Gleiche Auflösung, gleiche Größe, gleiches Pixelformat.

Mit FastCode (siehe FastCode.Sourceforge.net) kannst Du dann nochmal 20% rausholen...

Phantom1 13. Nov 2006 18:36

Re: Bilder schnell miteinander vergleichen
 
Ich hab das jetzt nochmal nachgeprüft und muss alzaimar recht geben, dein Algo ist schneller wenn die Bilder nur wenige oder garkeine unterschiede haben, das ganze dreht sich aber um wenn es sehr viele unterschiede gibt oder wenn komplett verschiedene bilder miteinander verglichen werden.

Gleiche Bilder vergleichen (500 durchläufe):
dein Algo: 1 sek
mein Algo: 1,7 sek

zwei komplett unterschiedliche Bilder vergleichen (500 Durchläufe):
dein Algo: 3,7 sek
mein Algo: 1,7 sek

Damit sollte die sache geklärt sein :wink:

@Alzaimar: was ist wenn er wirklich wissen muss wieviele unterschiede in 2 Bildern vorhanden sind? Was er genau damit machen will wissen wir ja nicht genau.

mfg

shmia 13. Nov 2006 18:56

Re: Bilder schnell miteinander vergleichen
 
Hier ist mein (ungetesteter) Vorschlag.
Es hat folgende Vorteile:
* man kann eine Maske angeben, um Farbunterschiede unterhalb einer bestimmten Grenze auszublenden
* durch Verwendung von Zeigern wird der Vergleich schneller
* die innere Schleife ist schneller, da sie auf 0 runterzählt
* der Code ist "kurz & knackig"
Delphi-Quellcode:
function CompareImagesShmia(Image1,Image2:TBitmap; mask:Cardinal=$00FEFEFE):Int64;
var x,y:integer;
    P1,P2: PByte;
begin
result := 0;
for y := 0 to Image1.Height -1 do
  begin
    P1 := Image1.ScanLine[y];
    P2 := Image2.ScanLine[y];

    for x := Image1.Width-1 downto 0 do
    begin
      if (PInteger(P1)^ and mask) <> (PInteger(P2)^ and mask) then
        inc(result);
      Inc(P1, 3); Inc(P2, 3);
    end;
  end;
end;
Nachtrag:
die Variable mask muss evtl. mit $FEFEFE00 vorbelegt werden.
Für den Vergleich werden ja 4 Bytes=Integer gelesen; es kommt nun drauf an,
ob das überzählige Byte MSB oder LSB ist.

alzaimar 13. Nov 2006 19:03

Re: Bilder schnell miteinander vergleichen
 
Zitat:

Zitat von Phantom1
@Alzaimar: was ist wenn er wirklich wissen muss wieviele unterschiede in 2 Bildern vorhanden sind? Was er genau damit machen will wissen wir ja nicht genau.
mfg

Das der Algo die Anzahl der unterschiedlichen Pixel zurückliefert, ist irgendwie klar :zwinker: , aber der Sinn ist nicht ersichtlich. Wozu? Wann sind Bilder in Auflösung, Größe und Farbtiefe absolut vergleichbar? Na ja, Anwendungen gibts bestimmt, hast schon recht :roll:

Phantom1 13. Nov 2006 19:47

Re: Bilder schnell miteinander vergleichen
 
@shima: dein Code bringt eine AV, du hast die Pointer P1 und P2 als PByte und inkrementierst diese bei der x-schleife mit 3

mfg

Airblader 13. Nov 2006 23:12

Re: Bilder schnell miteinander vergleichen
 
Ich kenn mich zwar nicht allzugut darin aus, aber wandelt der Borlandcompiler Schleifen nicht immer in ein downto um? (Ergo ist es egal ob ich es als downto hinschreibe oder nicht).

air

mbamler 14. Nov 2006 06:58

Re: Bilder schnell miteinander vergleichen
 
Zitat:

Zitat von Airblader
Ich kenn mich zwar nicht allzugut darin aus, aber wandelt der Borlandcompiler Schleifen nicht immer in ein downto um? (Ergo ist es egal ob ich es als downto hinschreibe oder nicht).

air

Das tut er - zumindest, wenn die Compiler-Optimierungen eingeschaltet sind...

Gruß
Matthias

shmia 14. Nov 2006 09:55

Re: Bilder schnell miteinander vergleichen
 
Zitat:

Zitat von Phantom1
@shima: dein Code bringt eine AV, du hast die Pointer P1 und P2 als PByte und inkrementierst diese bei der x-schleife mit 3

Natürlich müssen die Bitmaps im 24Bit-Format vorliegen. (bitmap.PixelFormat := pf24bit)
Ein Pixel benötigt 24Bit = 3 Bytes; daher werden die Zeiger jeweils um 3 Bytes inkrementiert.

Phoenix 14. Nov 2006 10:08

Re: Bilder schnell miteinander vergleichen
 
Zitat:

Zitat von alzaimar
Viel interessanter wäre es, einen Ähnlichkeitsindex von zwei beliebigen Bildern zu erstellen, die unterschiedlich kodiert (JPEG vs. BMP) und in unterschiedlichen Farbtiefen und Auflösungen vorliegen.

Was auch nicht so hyperkompliziert ist. Das wichtigste ist erstmal eine mehr oder weniger saubere Kanten- und Flächenerkennung, die Umrechnung dieser erkannten Kanten in Vektoren und dann die Vergleiche der enstprechenden Vektoren zusammen mit einem Farbvergleich der umschlossenen Flächen.

Daraus kann man dann mit einer gewissen Genauigkeit darauf schliessen, ob verschiedene Bilder das gleiche Motiv zeigen oder nicht, oder ob sie das gleiche Motiv mit einer verschobenen Position zeigen.

Alternativ kann man auch einfach einen Bildausschnitt nehmen (z.B. ein kleines Quadrat) und das dann auf dem nächsten Bild solange herumschieben bis es wieder ein Treffer ist. Das setzt aber wieder gleiche Auflösung und Farbtiefe voraus. Mit diesem Verfahren wird übrigens in MPEG-Videocodes ermittelt welche Bereiche im folgenden Bild aus Teilen des Vorherigen bestehen und dann wird komprimiert in dem gesagt wird: Der Ausschnitt (x,y, breite,höhe) aus Bild X kommt an diese Position (x,y) in Bild Y. Spart massigst Daten :)

Phantom1 14. Nov 2006 10:10

Re: Bilder schnell miteinander vergleichen
 
Zitat:

Zitat von shmia
Natürlich müssen die Bitmaps im 24Bit-Format vorliegen. (bitmap.PixelFormat := pf24bit)
Ein Pixel benötigt 24Bit = 3 Bytes; daher werden die Zeiger jeweils um 3 Bytes inkrementiert.

Das ist mir schon klar, aber dein Code bringt eine AV.

so sieht deine x-schleife aus
Delphi-Quellcode:
for x := Image1.Width-1 downto 0 do
ich vermute mal du wolltest es so hier machen, dann müsste dein code glaub ich gehen:
Delphi-Quellcode:
for x := Image1.Width div 3-1 downto 0 do
mfg

Phantom1 14. Nov 2006 10:39

Re: Bilder schnell miteinander vergleichen
 
Ich hab meinen Code jetzt nochmal optimiert, dieser ist jetzt auch bei Bildern die keine oder nur wenige Unterschiede haben schneller:

Delphi-Quellcode:
function CompareImages(Bitmap1, Bitmap2: TBitmap): LongWord;
var
  xy: integer;
  P1, P2: PRGBTriple;
begin
  Result:=0;
  Bitmap1.PixelFormat:=pf24bit;
  Bitmap2.PixelFormat:=pf24bit;
  P1:=Bitmap1.ScanLine[Bitmap1.Height-1];
  P2:=Bitmap2.ScanLine[Bitmap2.Height-1];
  if not CompareMem(P1, P2, Bitmap1.Width*Bitmap1.Height*3) then
    for xy:=1 to Bitmap1.Height*Bitmap1.Width do begin
      if (P1^.rgbtRed<>P2^.rgbtRed) or (PWord(P1)^<>PWord(P2)^) then
        Inc(Result);
      Inc(P1);
      Inc(P2);
    end;
end;
Gleiche Bilder vergleichen (500 durchläufe):
Flips Algo: 1,0 sek
mein Algo: 0,8 sek

zwei komplett unterschiedliche Bilder vergleichen (500 Durchläufe):
Flips Algo: 3,7 sek
mein Algo: 1,0 sek

Noch schneller dürfte es warscheinlich nur mit Assembler gehen ^^

EDIT: kleine Änderung am Code

mfg

Vjay 14. Nov 2006 11:15

Re: Bilder schnell miteinander vergleichen
 
Zitat:

(P1^.rgbtRed<>P2^.rgbtRed) or
(P1^.rgbtGreen<>P2^.rgbtGreen) or
(P1^.rgbtBlue<>P2^.rgbtBlue)
Wäre es nicht besser die drei Bytes auf einmal zu prüfen?

Phantom1 14. Nov 2006 11:37

Re: Bilder schnell miteinander vergleichen
 
Zitat:

Zitat von Vjay
Zitat:

(P1^.rgbtRed<>P2^.rgbtRed) or
(P1^.rgbtGreen<>P2^.rgbtGreen) or
(P1^.rgbtBlue<>P2^.rgbtBlue)
Wäre es nicht besser die drei Bytes auf einmal zu prüfen?

Hast du eine bessere möglichkeit gefunden?

EDIT: hab eben doch noch eine bessere möglichkeit gefunden:
Delphi-Quellcode:
if (P1^.rgbtRed<>P2^.rgbtRed) or (PWord(P1)^<>PWord(P2)^) then
Dadurch wird der Vergleich nochmals um etwa 0,2 sek schneller. Hab den Code oben geändert.

mfg

EDatabaseError 14. Nov 2006 13:19

Re: Bilder schnell miteinander vergleichen
 
Liste der Anhänge anzeigen (Anzahl: 1)
So...
ich hab jetzt mal beide codes von oben getestet.

Resultat:

das Testbild ist im Anhang

beim 1:
AV auch wenn das Bild gleich ist

beim 2:
Bei gleichem Bild OK
Bei unterschiedlichen Bildern AV


:drunken:

Mfg
Tobi

Phantom1 14. Nov 2006 13:40

Re: Bilder schnell miteinander vergleichen
 
Zitat:

Zitat von EDatabaseError
So...
ich hab jetzt mal beide codes von oben getestet.

Hast du auch mein Code getestet? Bei mir gehts jedenfalls ohne Probleme mit dem pi.bmp (egal ob die unterschiedlich sind oder nich).

mfg

negaH 15. Nov 2006 13:28

Re: Bilder schnell miteinander vergleichen
 
Delphi-Quellcode:
(P1^.rgbtRed<>P2^.rgbtRed) or
(P1^.rgbtGreen<>P2^.rgbtGreen) or
(P1^.rgbtBlue<>P2^.rgbtBlue)
Delphi-Quellcode:
if (P1.R xor p2.R) or (P1.G xor P2.G) or (P1.B xor P2.B) <> 0 then
sollte schneller sein. Dein obiger Source wird durch den Compiler in 3 Compare (quasi Subtrationen) Operationen mit jeweils einem Branch/bedingten Sprung umgesetzt. Mein nachfolgender Code verknüpft alle Werte erstmal mit simplen boolschen Operationen und wenn das Gesamtresultat <> 0 ist wird mit einem begingten Sprung ausgewertet. Bedingte Spünge sind ein Graus für die Branchprediction Unit der CPU und führen meistens zum Invalidieren des Instructioncache. Zudem können die 3 XOR + 3 OR Operationen quasi in parallel durch den Instructiondecoder ausgewertet werden, in mehreren Pipes der CPU. Erst am Ende wird ein bedingter Sprung ausgeführt der in letzten Falle nur überprüft ob die vorhergehenden Operationen das Zero Flag Z gesetzt/gelöscht haben.

Noch schneller wenn man AND masked und nicht in 24Bit RGB sondern als 32Bit zugreift

Delphi-Quellcode:
if P1 xor P2 and $FFFFFF <> 0 then
Zur Behauptung "schnellster Code" kann ich nur sagen "alles relativ" und wenn man "misst dann misst man nur Mist".

Ich gebe dir 2 Bitmaps mit 16Bit Farbauflösung. Du vergleichst sie aber im 24Bit Modus was dazu führt das die Delphi Bitmap VCL diese 16Bit Aufkösung erstmal in 24Bit umrechnen muß. Das erfolgt übers Windows API. Diese Operation hast du in deiner Meßschleife überhaupt nicht berücksichtigt. Ergo: Wenn überhaupt ist dein Code relativ optimiert ausschließlich bezogen auf Windows Bitmaps in 24 Bit Farbtiefe. Problem? es gibt unzählige Formate für Bitmaps und noch viel mehr in anderen Formaten. Die Umwandlung in das benötigte 24Bit Bitmap Format ist aber gerade der Punkt der die meiste Zeit frisst.

Gruß Hagen

Phantom1 15. Nov 2006 14:10

Re: Bilder schnell miteinander vergleichen
 
Zitat:

Zitat von negaH
Delphi-Quellcode:
(P1^.rgbtRed<>P2^.rgbtRed) or
(P1^.rgbtGreen<>P2^.rgbtGreen) or
(P1^.rgbtBlue<>P2^.rgbtBlue)
Delphi-Quellcode:
if (P1.R xor p2.R) or (P1.G xor P2.G) or (P1.B xor P2.B) <> 0 then
sollte schneller sein.

Die xor variante ist bei mir deutlich langsamer (ca 50%), habs mit Delphi7 und Delphi2006 getestet.

Zitat:

Zitat von negaH
Noch schneller wenn man AND masked und nicht in 24Bit RGB sondern als 32Bit zugreift

Mein erst geposteter Code war ja für 32bit Bmps, in diesem Fall war aber 24bit schneller. Warum das so ist weiß ich allerdings nich.

zwischen
Delphi-Quellcode:
if P1^<>P2^ then
und
Delphi-Quellcode:
if P1^ xor P2^ and $FFFFFF <> 0 then
konnte ich bei 32bit auch kein unterschied feststellen, waren beide gleichschnell.

mfg

negaH 16. Nov 2006 20:51

Re: Bilder schnell miteinander vergleichen
 
1.) hast du dir den durch den Compiler erzeugten Code in Assembler angeschaut ?
2.) wie hast du was gemessen ?
3.) der von mir vorfeschlagene 32Bit Zugriff bezog sich auf 24Bit Bitmapdaten, deshalb auch die AND Maske mit $00FFFFFF.


Gruß Hagen

sorry
Zitat:

habs mit Delphi7 und Delphi2006
sehe ich erst jetzt. Vergiß Delphi6,7,D2006 wenn es um Optimierungen geht. In diesen Versionen basiert der Borland Compiler auf einem Intel Produkt. Im Vergleich zu Delphi5 ist der erzeugte Code bis zu 30% langsammer als der vom Original Borland Compiler der bis zum Delphi5 benutzt wurde. Frage dich mal warum ab D7 in deren Licence.txt oä. es strickt verboten wurde Performancevergleiche mit älteren Versionen zu veröffentlichen !!

Ich persönlich hatte schon Codestücken die mehr als 200% langsammer waren als mit D5 compiliert. Das ist auch ein Grund warum ich privat im Hobby immer noch am liebsten mit Delphi 5 arbeite. Die nachfolgenden Versionen bieten, mal abgesehen von Gimmeck-VCLs wie TXPManifest etc.pp. nichts wirklich neues im Vergleich zum Delphi5. Nebenbei bemerkt ist der erzeugte Code mit D5 zusätzlich noch kompakter !

Phantom1 17. Nov 2006 12:19

Re: Bilder schnell miteinander vergleichen
 
Zitat:

Zitat von negaH
1.) hast du dir den durch den Compiler erzeugten Code in Assembler angeschaut ?

habe ich nicht

Zitat:

Zitat von negaH
2.) wie hast du was gemessen ?

so hier:
Delphi-Quellcode:
procedure TForm2.Button1Click(Sender: TObject);
var
  start, stop: Int64;
  i: Integer;
begin
  start:=GetTickCount;

  for i:=1 to 500 do
    CompareImages(Bitmap1, Bitmap2);

  stop:=GetTickCount;
  Caption:=IntToStr(stop-start);
end;
Mit dem QueryPerformanceCounter ginge es zwar noch etwas genauer, aber das fällt bei den großen Unterschieden nicht ins gewicht.

Jetzt zu den Messungen:
Delphi-Quellcode:
(P1^.rgbtRed<>P2^.rgbtRed) or
(P1^.rgbtGreen<>P2^.rgbtGreen) or
(P1^.rgbtBlue<>P2^.rgbtBlue)
ca 1100 ms

Delphi-Quellcode:
(P1^.rgbtRed xor p2^.rgbtRed) or (P1^.rgbtGreen xor P2^.rgbtGreen) or (P1^.rgbtBlue xor P2^.rgbtBlue) <> 0
ca 1450 ms

Hab natürlich mehrere Messungen vorgenommen und den Mittelwert genommen.

Zitat:

Zitat von negaH
3.) der von mir vorfeschlagene 32Bit Zugriff bezog sich auf 24Bit Bitmapdaten, deshalb auch die AND Maske mit $00FFFFFF.

Achso, das ergibt natürlich mehr sinn, hatte mich schon gewundert.

Delphi-Quellcode:
(PInteger(P1)^ xor PInteger(P2)^) and $00FFFFFF <> 0
Bei 24bit ergab meine Messung hier 1100 ms

Zitat:

Zitat von negaH
sehe ich erst jetzt. Vergiß Delphi6,7,D2006 wenn es um Optimierungen geht. In diesen Versionen basiert der Borland Compiler auf einem Intel Produkt. Im Vergleich zu Delphi5 ist der erzeugte Code bis zu 30% langsammer als der vom Original Borland Compiler der bis zum Delphi5 benutzt wurde. Frage dich mal warum ab D7 in deren Licence.txt oä. es strickt verboten wurde Performancevergleiche mit älteren Versionen zu veröffentlichen !!

Sehr interessant, das wusste ich noch nicht, leider hab ich kein Delphi5.

mfg

Hawkeye219 17. Nov 2006 12:44

Re: Bilder schnell miteinander vergleichen
 
and bindet stärker als xor, man sollte also hier Klammern setzen:

Delphi-Quellcode:
(PInteger(P1)^ xor PInteger(P2)^) and $00FFFFFF <> 0
Gruß Hawkeye

Phantom1 17. Nov 2006 13:52

Re: Bilder schnell miteinander vergleichen
 
Zitat:

Zitat von Hawkeye219
and bindet stärker als xor, man sollte also hier Klammern setzen:

Delphi-Quellcode:
(PInteger(P1)^ xor PInteger(P2)^) and $00FFFFFF <> 0
Gruß Hawkeye

Oh ja stimmt, ich habe es oben korrigiert.

Relicted 26. Nov 2006 12:55

Re: Bilder schnell miteinander vergleichen
 
mahlzeit!

jemand ne idee wie ich 2 bilder ( grundstruktur gleich, also gleiches bild ) miteinander vergleiche die aber total unterschiedliche farbwerte haben? also das eine bild hat z.b. nen grünstich das andere nen blaustich...
als basis sind es aber die selben bilder...


ich habe schon überlegt ob man vielleicht alle farbinformationen rausnimmt und dann ein S/W bild benutzt ( geht das überhaupt in delphi ? ) und dann vergleicht - es sollten ja die selben werte dann rauskommen oder vertue ich mich da ?

gruß
reli

PS: ich mach denk ich mal nen neuen thread auf zu dem thema :o)
danke luke schonmal für den hinweis

DGL-luke 26. Nov 2006 15:06

Re: Bilder schnell miteinander vergleichen
 
Du kannst es natürlich in Graustufen umrechnen.

Evtl. kannst du auch mit "farbstich-durchschnittswerten" rechnen, wenn also das eine bild "grüner" als das andere ist, das entsprechend in die toleranz mit hineinrechnen.

aber das gehört eigentlich nicht hierher...

DP-Maintenance 26. Nov 2006 17:55

DP-Maintenance
 
Dieses Thema wurde von "Daniel" von "Neuen Beitrag zur Code-Library hinzufügen" nach "Multimedia" verschoben.

KleinAmann 5. Mär 2009 23:39

Bilder miteinander vergleichen / ungleiche Pixel makieren
 
Hi,

sry dass ich so einen alten Thread aufwühl :D aber ich
kam auf eine Idee für ein neues Programm.

Nun hab ich die Frage ob es sich auch irgendwie machen lässt,
Bereiche wo sich was geändert hat mit einem Kreis zu makieren.

Ich kann die einzelnen Pixel wo unterschiedlich sind färben aber ich
weiß nicht wie ich einen zusammenhängenden bereich umkreisen kann um ihn praktisch zu makieren.

Dann hätte ich noch eine weitere Frage, nehmen wir an man hat 1 Objekt (ein Fingerabdruck) nun ist auf dem Bild mit dem
man es vergleichen will auch dieser Fingerabdruck nur ist dieser nicht auf der selben position und nicht ganz vollständig.
Kann man jetzt irgendwie herausfinden ob sie übereinstimmen? Man siehts oft bei Crime Serien, wo sie die Fingerabdrücke aus ihrer Datenbank vergleichen.

Ich wäre dankbar um vorschläge bzw tipps.

Mfg "Klein"Amann

himitsu 6. Mär 2009 08:49

Re: Bilder schnell miteinander vergleichen
 
am einfachsten du erstellst dir erstmal ein Differenzielles Bild

für jedes Pixel :
Delphi-Quellcode:
DiffImage.PixelX.Red  := Abs(Image1.PixelX.Red  - Image2.PixelX.Red);
DiffImage.PixelX.Green := Abs(Image1.PixelX.Green - Image2.PixelX.Green);
...
dann suchst du dieses Bild nach Farben <> Schwarz ab (eventell mit mindestens einer gewissen Distanz zu Schwarz, damit kleinese unterschiede ignoriert werden)

von einem gefundenen Pixel schaust du dir die umgebenden Pixel an
und bekommst so einen Bereich zusammen ... anhand der Größe und Position dieses Bereiches zeichnest du dann den Kreis
(in etwa Kreisdurchmesser etwas größer als Max(Breite, Höhe) des Bereiches und Kreismittelpunkt = Bereichmittelpunkt)

und dann suchst du nach weiteren Bereichen (die gefundenen Bereiche irgendwo in einer Liste speichern und mit dem neugefundenen Bereich vergleichen, damit nichts mehrfach behandelt wird)

KleinAmann 6. Mär 2009 11:10

Re: Bilder schnell miteinander vergleichen
 
hi vielen Dank erstmals aber
leider gibts es bei mir in Delphi 2009 bei TImage werder Image1.pixel noch Image1.pixelX
was soll ich tun?
mfg DA

FriFra 27. Apr 2009 08:13

Re: Bilder schnell miteinander vergleichen
 
Ich hab die Funktion getestet, wobei die von Phantom mit meinen Testdaten ca. 3x schneller läuft, als die ursprüngliche Version.

Die Sache hat jedoch einen Schönheitsfehler, sie funktioniert nicht zuverlässig. Wenn ich eine 256 Farb Grafik scanne ist die Funktion sehr genau, bei JPGs mit den üblichen Artefakten tendiert die Trefferquote bei mir gegen 0. Ich habe einfache Grafiken und scanne diese nach ähnlichen Bereichen, dabei sind augenscheinlich nahezu identische Bereiche nach dem Ergebnis dieser Funktionen deutlich weniger ähnlich als vollkommen unterschiedliche Bereiche.

Kennt jemand noch eine andere Methode 2 Bilder auf Ähnlichkeit zu prüfen?

FriFra 6. Mai 2009 23:24

Re: Bilder schnell miteinander vergleichen
 
Ich wollte den Threat nochmal pushen... kennt wirklich niemand eine Möglichkeit 2 Bilder schnell auf Ähnlichkeit zu prüfen? Wie gesagt ist diese Methode für mich zu ungenau...

stiftmaster 23. Jul 2009 08:07

Re: Bilder schnell miteinander vergleichen
 
Hallo,

habe mir den "letzten finalen" Quelltext von Phantom1 genauer angeschaut und bin begeistert, wie schnell das ganze klappt - dickes Lob an dieser Stelle!

Dieser Code gibt ja als Int zurück, wie viele Pixel in der Grafik unterschiedlich sind. Nun möchte ich halt nicht nur die Anzahl wissen, sondern a) welche Position und b) wie der neue Wert aussieht. Habe daher den if-Teil wie folgt angepasst:

Delphi-Quellcode:
if (P1^.rgbtRed<>P2^.rgbtRed) or (PWord(P1)^<>PWord(P2)^) then
begin
  SetLength(changes, Length(changes) + 1);
  y := xy div Bitmap1.Width;
  x := xy - (y * Bitmap1.Width);
  changes[Length(changes) - 1].x := x;
  changes[Length(changes) - 1].y := y;
  changes[Length(changes) - 1].Color := Bitmap2.Canvas.Pixels[x, y];
end;
Dabei sieht changes wie folgt aus:
Delphi-Quellcode:
TDifference = record
  x: Integer;
  y: Integer;
  color: TColor;
end;

TDifferences = array of TDifference;

var
  changes: TDifferences;
Zu den Messungen: wenn ich Phantom1 Code nehme, dann braucht mein Rechner mit meinen Bildern bei 500 Durchläufen 4.500 TickCounts. Wenn ich meine Anpassungen integriere, dann sind es 11.391. Das ist natürlich prozentual gesehen ein enormer Verlust an Geschwindigkeit. Daher meine Frage an euch Fachmänner - geht das auch schneller?

Ziel ist grob wie folgt kurz beschreibbar:
Programm1: hat Bild1 und Bild2 => Berechnet Differenz
Programm2: hat Bild1 und bekommt Differenz => berechnet draus Bild2

Vielen Dank für eure Mühen

Stefan


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:25 Uhr.
Seite 1 von 2  1 2      

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