Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Mehrere Bilder vergleichen
HenryHux - Do 23.09.10 13:30
Titel: Mehrere Bilder vergleichen
Hi,
ich habe ja mit eurer Hilfe mitlerweile ein Programm hinbekommen, welches Bilder vergleiche kann. Klappt auch 1A!
Jetzt versuche ich aber ein Bild mit ca 50 verschiedenen zu vergleichen. Wie realisiere ich das am besten? Ich kann ja nicht schlecht 50 TImage erzeugen, oder?
Hier die Funktion, die die Bilder vergleicht :
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| function CompareImages(Bitmap3, Bitmap2: TBitmap): LongWord; var xy: integer; P1, P2: PInteger; begin Result:=0; Bitmap3.PixelFormat:=pf32bit; Bitmap2.PixelFormat:=pf32bit; P1:=Bitmap3.ScanLine[Bitmap3.Height-1]; P2:=Bitmap2.ScanLine[Bitmap2.Height-1]; for xy:=1 to Bitmap3.Height*Bitmap3.Width do begin Inc(Result, Byte(P1^<>P2^)); Inc(P1); Inc(P2); end; end; |
Und hier die, die sie aufruft:
Delphi-Quelltext
1: 2: 3: 4:
| procedure TForm1.Button3Click(Sender: TObject); begin ShowMessage(IntToStr(CompareImages(Image1.Picture.Bitmap,Image2.Picture.Bitmap))); end; |
Vielen Dank!
Gausi - Do 23.09.10 13:42
Wie liegen die Bitmaps denn vor? In Dateien? Dann könnte man das so machen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| EinBild.LoadFromFile('c:\meinBild.bmp');
for i := 1 to 50 do begin NocheinBild.LoadFromFile('c:\NocheinBildNr' + IntTostr(i) + '.bmp'); Diff := CompareImages(EinBild, NocheinBild); ShowMessage(IntToStr(Diff)); end; |
HenryHux - Do 23.09.10 14:31
Ok, denke das könnte so klappen.
Habs jetzt so:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure TForm1.Button4Click(Sender: TObject); var i, diff : integer; EinBild, NocheinBild : TBitmap; begin EinBild.LoadFromFile('D:\image.bmp');
for i := 1 to 2 do begin NocheinBild.LoadFromFile('D:\image' + IntTostr(i) + '.bmp'); Diff := CompareImages(EinBild, NocheinBild); ShowMessage(IntToStr(Diff)); end; end; |
Wenn ichs starte stürtzt er ab mit der Fehlermeldung und zeigt mir EinBild.LoadFromFile('D:\image.bmp'); als Fehlerquelle.
Ne Idee?
---------------------------
Debugger Exception Notification
---------------------------
Project Project2.exe raised exception class EAccessViolation with message 'Access violation at address 0045890D in module 'Project2.exe'. Read of address 00000000'. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------
bummi - Do 23.09.10 14:32
Wenn Du nicht BMP's mit JPG's vergeleichen muß wie wäre es mit:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,Math, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private public end;
var Form1: TForm1;
implementation
{$R *.dfm} function CompareStreams(Stream1, Stream2: TStream): Extended; type TBuffer = array[0..8191] of Byte; const BuffSize = SizeOf(TBuffer); var Buffer1: TBuffer; Buffer2: TBuffer; BytesRead1: Integer; BytesRead2: Integer; DifferenceCount: Int64; Index: Integer; MaxCount: Integer; begin Stream1.Position := 0; Stream2.Position := 0; DifferenceCount := 0; while True do begin BytesRead1 := Stream1.Read(Buffer1, BuffSize); BytesRead2 := Stream2.Read(Buffer2, BuffSize); MaxCount := Min(BytesRead1, BytesRead2); for Index := 0 to MaxCount -1 do if Buffer1[Index] <> Buffer2[Index] then
Inc(DifferenceCount); if (BytesRead1 <> BytesRead2) or (BytesRead1 = 0) or (BytesRead2 = 0) then Break; end; Result := (DifferenceCount * 100) / Max(Stream1.Size, Stream2.Size); end;
procedure TForm1.Button1Click(Sender: TObject); var Stream1: TFileStream; Stream2: TFileStream; Differences: Extended; begin Differences := 0.0000; try Stream1 := TFileStream.Create('C:\temp\1.jpg', fmOpenRead); Stream2 := TFileStream.Create('C:\temp\1.1.jpg', fmOpenRead); Differences := CompareStreams(Stream1, Stream2); finally FreeAndNil(Stream1); FreeAndNil(Stream2); end; ShowMessageFmt('%.4f', [Differences]); end;
end. |
Gausi - Do 23.09.10 14:36
Vorher müssen natürlich die Bitmap-Objekte einmal erzeugt werden:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| EinBild := TBitmap.Create; NochEinBild := TBitmap.Create;
EinBild.Free; NochEinBild.Free; |
Zusätzlich noch Ressourcen-Schutzblöcke, also try...finally drumherum wie im Code von
bummi bei den FileStreams. :)
HenryHux - Do 23.09.10 14:49
Danke!
Hatte die Bilder im Bitmap Format. Aber Jpeg ist auch nicht schlecht zu wissen =)
Gausi hat folgendes geschrieben : |
| Vorher müssen natürlich die Bitmap-Objekte einmal erzeugt werden |
:oops: ..Natürlich. Danke!
Aber was ich nicht verstehe:
Zuerst vergleicht er ja das bmp mit bmp1. Die sind beide gleich, bis auf, dass das Zweite ein wenig mehr nach rechts verschoben ist. Das erkennt er gut und gibt mir als Wert 9967.
Dann vergleicht er bmp mit bmp2. Zwei völlig verschiedene Bilder. Er gibt mir 1000.
Dann bmp mit bmp3. Beide identisch und er gibt mir 0. Wieso? 0 dürfte hier doch nit exat gleich bedeuten?
Edit:
Ok 0 bedeutet 100%...
Eine kleine abschließenden Frage hätte ich aber noch.
Wie kann ich bei
GetShoot2Image(image1,Rect(Breite,Hoehe,Breite + Breite2,Hoehe + Hoehe2),1); das Bild an sich kleiner machen?
Tilman - Do 23.09.10 16:24
Nur kurz zur Erklärung dieser Term: "(P1^<>P2^)", ergibt true wenn P1^ ungleich P2^ ist, und False wenn sie gleich sind. Das wird dann als Byte umgewandelt, true ist als Zahl "1" und False als Zahl "0". Wenn beide Pixel identisch sind, wird result also um 0 erhöht, sind beide verschieden wird Result um 1 erhöht. Vermutlich die schnellste Lösung, die aber dazu führt dass kein Anfänger den Code mehr begreift :D
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!