Entwickler-Ecke

Multimedia / Grafik - Bilder mit einander vergleichen


DeltaEx - So 22.06.03 14:50
Titel: Bilder mit einander vergleichen
Also ich will 2 Bilder miteinander vergleichen. Ich habe diesen Code verwenden:


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:
procedure TForm1.Button1Click(Sender: TObject); 
var 
  b1, b2: TBitmap; 
  c1, c2: PByte; 
  x, y, i, 
  different: Integer; // Counter for different pixels 
begin 
  b1 := Image1.Picture.Bitmap; 
  b2 := Image2.Picture.Bitmap; 
  Assert(b1.PixelFormat = b2.PixelFormat); // they have to be equal 
  different := 0
  for y := 0 to b1.Height - 1 do 
  begin 
    c1 := b1.Scanline[y]; 
    c2 := b2.Scanline[y]; 
    for x := 0 to b1.Width - 1 do 
      for i := 0 to BytesPerPixel - 1 do // 1, to 4, dep. on pixelformat 
      begin 
        Inc(different, Integer(c1^ <> c2^)); 
        Inc(c1); 
        Inc(c2); 
      end
  end
end;


Aber der macht einen Fehler bei mir und zwar sagt er:
Zitat:
[Fehler] Unit1.pas(46): Undefinierter Bezeichner: 'BytesPerPixel'


Moderiert von user profile icontommie-lie: Code- durch Delphi-Tags ersetzt, Fehlermeldung in Quote-Tags gesetzt


Andreas Pfau - So 22.06.03 15:27

Hallo,

du musst BytesPerPixel auch festelgen!!!

Quelltext
1:
2:
const
  BytesPerPixel = 12345;


Welche Zahl weiß ich nicht, da ich den Code ehrlich gesagt nicht verstehe. Ich wusste gar nicht, dass man Scanlines AUF DIESE ART verwenden kann. Ich mache das immer über PByteArray;

Aber probiere es so: setze Pixelformat der Bitmaps auf pf24Bit, und BytesPerPixel auf 3, dann müsste es normalerwiese funzen.


DeltaEx - So 22.06.03 16:18

Ich verstehe den code auch nicht. hast du vieleicht eine dessere methode?
wäre dankbar


Andreas Pfau - So 22.06.03 17:05
Titel: erprise
Hallo,

OK, hier der Code:

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:
procedure TForm1.Button1Click(Sender: TObject);
var
 B1, B2: TBitmap;
 S1, S2: PByteArray;
 X, Y: Integer;
 Diff: Integer;
begin
 // Bilder zuweisen, ich lade sie hier aus 2 TImages
 B1 := TBitmap.Create;
 B1.Assign(Image1.Picture.Bitmap);
 B2 := TBitmap.Create;
 B2.Assign(Image2.Picture.Bitmap);
 // Wenn du auch unterscheidlich große Bilder vergleichen willst, setz die beiden folgenden Zeilen ein:
// B2.Canvas.StretchDraw(B2.Canvas.ClipRect, B1);
// B1.Assign(Image2.Picture.Bitmap);

 // Auf Größe prüfen (wie wollen wir Pixel vergleichen, wenn das eine Bild mehr hat???)
 If (B1.Width <> B2.Width) Or (B1.Height <> B2.Height) Then
  ShowMessage('Die Bilder sind nicht gleich groß!')
 Else begin
  // PixelFormat auf 24Bit, dann können wir erst mit Scanlines arbeiten
  B1.PixelFormat := pf24Bit;
  B2.PixelFormat := pf24Bit;

  // Zähler auf 0
  Diff := 0;

  For Y := 0 To B1.Height - 1 Do begin
   // ScanLines laden
   S1 := B1.ScanLine[Y];
   S2 := B2.ScanLine[Y];
   For X := 0 To B1.Width - 1 Do begin
    // Vergleichen
    If (PByte(Integer(S1) + X * 3    )^ <> PByte(Integer(S2) + X * 3    )^) Or    // Blau
       (PByte(Integer(S1) + X * 3 + 1)^ <> PByte(Integer(S2) + X * 3 + 1)^) Or    // Grün
       (PByte(Integer(S1) + X * 3 + 2)^ <> PByte(Integer(S2) + X * 3 + 2)^) Then  // Rot
     // Wenn unterschiedlich, Zähler erhähen
     Inc(Diff);
   end;
  end;

  ShowMessageFmt('Die Bilder haben %d Unterschiedliche Pixel.'#13#10+
                 'Dies ist ein Unterscheid von %d%%.',
                 [Diff, (Diff * 100div (B1.Width * B1.Height)]);
 end;

 B1.Free;
 B2.Free;
end;

Ich weiß nicht, wie gut du dich mit ScanLines auskennst, daher frag' nur, wenn du was nicht verstanden hast.


Moderiert von user profile icontommie-lie: Code- durch Delphi-Tags ersetzt


DeltaEx - So 22.06.03 20:30

Jo danke es funktioniert super!!


Andreas Pfau - So 22.06.03 20:42

Hallo,

*erfreut bin* :D

Aber: das bringt doch alles nix. Ich gehe jede Wette ein, wenn du was 2mal hintereinander einscannst hast du über 75% unterschiede, denn dieser Algo vergleicht jeden Pixle, und eine Abweichung von 1/255 pro Farbkanal erhöht den Counter. Und der Code ganz oben, der die Größe enpasst, ist völlig Sinnlos (hab's nur zum Debuggen eingebaut).

Wenn du 2 Bilder wirklich verbinden willst, musst du jeden Pixel mit umliegenden Pixeln vergleichen, Farbabweichungen miteinkalkulieren, usw. Total kompliziert. der obige Code taugt nur, um zu überprüfen, ob die Kopie eines Bildes verändert wurde.

Aber, wenn es den Zweck erfüllt, ist ja alles OK.


DeltaEx - So 22.06.03 22:18

ne hab keine probleme es funkt sehr gut und schnell was wichtig ist.