Seite 1 von 2

Grafik pixelweise vergleichen

Verfasst: 01.11.2010 19:32
von torstenh
Hallo zusammen,

ich möchte gern zwei .bmp Dateien pixelweise vergleichen. Habe es mit "fingerprint" probiert aber hier kann ich kein Range einstellen. Das heißt das ich die Genauigkeit einstellen möchte.
Es werden immer nur zwei Bilder verglichen. Kann mir jemand auf die Sprünge helfen? ich benutze PUREBASIC 4.00. Habe im Forum einige Threads gelesen, mit for/next Schleife usw aber ich habe keinen Ansatz.
Ein Link würde mir genügen z.B. welche Befehle ich nehmen könnte um z.B. den gleichen Bereich zweier Bilder zu vergleichen.


Danke euch!

Grüße,
Torsten

Re: Grafik pixelweise vergleichen

Verfasst: 01.11.2010 19:49
von RSBasic
Wenn du wirklich zwei Bilder pixelweise vergleichen möchtest, dann erstell zwei Zählschleifen (For To Next) für y und x und ermittel für jede Position des Pixels mit Point().
Hoffe, es hilft dir weiter.

\\Edit:
Also etwa so, aber dieser Code kann man bestimmt optimieren, habs einfach mal rasch so geschrieben:

Code: Alles auswählen

EnableExplicit

Define y
Define x
Define width=4
Define height=4
Define color1
Define color2

CreateImage(1,width,height,32)
CreateImage(2,width,height,32)

If StartDrawing(ImageOutput(1))
  Box(0,0,width,height,RGB(255,0,0))
  StopDrawing()
EndIf
If StartDrawing(ImageOutput(2))
  Box(0,0,width,height,RGB(255,0,0))
  Plot(1,2,RGB(255,255,255));1. Differenz
  Plot(2,3,RGB(255,255,255));2. Differenz
  StopDrawing()
EndIf

For y=0 To height-1
  For x=0 To width-1
    If StartDrawing(ImageOutput(1))
      color1 = Point(x,y)
      StopDrawing()
    EndIf
    If StartDrawing(ImageOutput(2))
      color2 = Point(x,y)
      StopDrawing()
    EndIf
    
    If color1<>color2
      Debug Str(x)+"x"+Str(y)
    EndIf
  Next x
Next y

Re: Grafik pixelweise vergleichen

Verfasst: 01.11.2010 20:13
von RSBasic
Etwas optimiert, so dass es schneller beim Ermitteln ist:

Code: Alles auswählen

EnableExplicit

Define y
Define x
Define width=40
Define height=40
Define color1
Define color2

Dim Image1_Values(width-1,height-1)
Dim Image2_Values(width-1,height-1)

CreateImage(1,width,height,32)
CreateImage(2,width,height,32)

If StartDrawing(ImageOutput(1))
  Box(0,0,width,height,RGB(255,0,0))
  StopDrawing()
EndIf
If StartDrawing(ImageOutput(2))
  Box(0,0,width,height,RGB(255,0,0))
  Plot(1,2,RGB(255,255,255));1. Differenz
  Plot(2,3,RGB(255,255,255));2. Differenz
  Plot(4,4,RGB(255,255,255));3. Differenz
  StopDrawing()
EndIf

If StartDrawing(ImageOutput(1))
  For y=0 To height-1
    For x=0 To width-1
      Image1_Values(x,y) = Point(x,y)
    Next x
  Next y
  StopDrawing()
EndIf

If StartDrawing(ImageOutput(2))
  For y=0 To height-1
    For x=0 To width-1
      Image2_Values(x,y) = Point(x,y)
    Next x
  Next y
  StopDrawing()
EndIf

For y=0 To height-1
  For x=0 To width-1
    color1 = Image1_Values(x,y)
    color2 = Image2_Values(x,y)
   
    If color1<>color2
      Debug Str(x)+"x"+Str(y)
    EndIf
  Next x
Next y
Nun wird nicht bei jedem Durchlauf immer wieder StartDrawing() und StopDrawing() ausgeführt, sondern nur einmal am Anfang jeweils für jede Grafik und die Daten werden in ein Array gespeichert, so dass die Daten am Ende schnell verglichen werden können.

Re: Grafik pixelweise vergleichen

Verfasst: 01.11.2010 21:22
von torstenh
oje! meine erste Danksagung kam nicht durch! Es hilft sicherlich um besser zu verstehen. Danke für deine Hilfe!!!!!
Da kann ich ein wenig rumprobieren.


Grüße,
Torsten

Re: Grafik pixelweise vergleichen

Verfasst: 01.11.2010 22:36
von torstenh
:allright:

Super Sache Danke nochmals für die schnelle Antwort. Genau das habe ich gesucht, muss es noch an meine Bedürfnisse anpassen aber sonst super!


Grüße,
Torsten

Re: Grafik pixelweise vergleichen

Verfasst: 02.11.2010 14:11
von Regenduft
Folgender Code ist gleichzeitig Antwort und Frage.

Antwort: Wenn Du Dich bereits mit Zeigern auskennst ist's so noch schneller.
Frage: Ist das zuverlässig? Die Adressen müssten ja eigentlich statisch sein...

Habe einfach mal grob den Code von RSBasic umgepflügt (und nur 32Bit-Grafiken beachtet).
Achtung: Ich habe kein DrawingBufferPitch() verwendet! Funktioniert also nur bei "Pitch = Breite*4"!

Code: Alles auswählen

EnableExplicit

Define x
Define y
Define width=40
Define height=40
Define x_max=width-1
Define y_max=height-1
Define *color1.Long
Define *color2.Long
Define reverse

CreateImage(1,width,height,32)
CreateImage(2,width,height,32)

If StartDrawing(ImageOutput(1))
  *color1 = DrawingBuffer()
  If DrawingBufferPixelFormat()|#PB_PixelFormat_ReversedY
    reverse=1
  EndIf
  Box(0,0,width,height,RGB(255,0,0))
  StopDrawing()
EndIf
If StartDrawing(ImageOutput(2))
  *color2 = DrawingBuffer()
  Box(0,0,width,height,RGB(255,0,0))
  Plot(1,2,RGB(255,255,255));1. Differenz
  Plot(2,3,RGB(255,255,255));2. Differenz
  Plot(4,4,RGB(255,255,255));3. Differenz
  StopDrawing()
EndIf

If reverse
  For y=0 To y_max
    For x=0 To x_max
      If *color1\l <> *color2\l
        Debug Str(x)+"x"+Str(y_max-y)
      EndIf
      *color1 + 4
      *color2 + 4
    Next x
  Next y
Else
  For y=0 To y_max
    For x=0 To x_max
      If *color1\l <> *color2\l
        Debug Str(x)+"x"+Str(y)
      EndIf
      *color1 + 4
      *color2 + 4
    Next x
  Next y
EndIf
Und ganz nebenbei an RSBasic: Ich hatte immer gedacht man solle in Zählschleifenköpfe keine Berechnungen reinbasteln, weil die bei jedem Durchlauf neu berechnet werden. Ist das falsch oder hast Du das nur aus "schnell mal zusammengeschrieben" Gründen so gemacht?

Re: Grafik pixelweise vergleichen

Verfasst: 02.11.2010 16:26
von RSBasic
@Regenduft
Ich habs "schnell mal zusammengeschrieben".
Mit dem Buffer kann man allerdings auch machen, so spart man zwei Arrays.

Re: Grafik pixelweise vergleichen

Verfasst: 03.11.2010 19:37
von Thorium
Regenduft hat geschrieben: Frage: Ist das zuverlässig? Die Adressen müssten ja eigentlich statisch sein...
Die Adressen sind schon statisch, zuverlässig ist dein Code trotzdem nicht, weil du den Pitch missachtest. Also wie lang eine Bildzeile im Speicher ist, die kann durchaus länger als Breite*4 sein. Aus Alignmentgründen kann die Breite z.B. immer durch 16 teilbar sein.

Re: Grafik pixelweise vergleichen

Verfasst: 04.11.2010 00:23
von c4s
Regenduft hat geschrieben:Und ganz nebenbei an RSBasic: Ich hatte immer gedacht man solle in Zählschleifenköpfe keine Berechnungen reinbasteln, weil die bei jedem Durchlauf neu berechnet werden. Ist das falsch oder hast Du das nur aus "schnell mal zusammengeschrieben" Gründen so gemacht?
Bemängelst du folgendes?

Code: Alles auswählen

  For y=0 To height-1
    For x=0 To width-1
Ich hatte nämlich komischerweise mal festgestellt, dass "height-1" im Schleifenkopf schneller ist als es bereits vorher abzuziehen.
Optimiert PureBasic da was? Sonst kann ich mir das nicht erklären...

Re: Grafik pixelweise vergleichen

Verfasst: 07.11.2010 21:21
von Regenduft
Regenduft hat geschrieben:Habe einfach mal grob den Code von RSBasic umgepflügt (und nur 32Bit-Grafiken beachtet).
(...) Die Adressen müssten ja eigentlich statisch sein...
Thorium hat geschrieben:Die Adressen sind schon statisch, zuverlässig ist dein Code trotzdem nicht, weil du den Pitch missachtest. Also wie lang eine Bildzeile im Speicher ist, die kann durchaus länger als Breite*4 sein. Aus Alignmentgründen kann die Breite z.B. immer durch 16 teilbar sein.
Ich hatte den Pitch ignoriert, da ich dachte er wäre bei 32Bit Grafiken immer Breite*4.

Ich habe jetzt mal ein paar tausend Sprite- und Imagegrafiken (32 Bit) jeweils in verschiedensten Abmessungen (Random) erstellt und der Pitch war immer Breite*4 (WinXP x86).

Bist Du sicher, dass der Pitch auch mal z.B. 16 sein kann? Ist das Harware bedingt (Grafikkarte und/oder 32-/64-Bit Prozessor)?
c4s hat geschrieben:Ich hatte nämlich komischerweise mal festgestellt, dass "height-1" im Schleifenkopf schneller ist als es bereits vorher abzuziehen.
Optimiert PureBasic da was? Sonst kann ich mir das nicht erklären...
:? Das verwirrt mich jetzt aber sehr. Bei mir sind "vorberechnete Schleifenwerte" immer schneller.