Bildschirm nach String durchsuchen

(Firma: privat) #3063955
Lesenswert?

Hi Leute,
Ich würde gerne ein Programm schreien in dem ich ein Arkustisches Signal 
bekomme wenn ich einen bestimmten String im Bildschirm habe.

Zb. wenn ich auf einer beliebigen Internetseite surfe und durch scrolle 
und dann irgendwo das wort "Hallo" steht soll ein Ton erklingen.
Habt ihr irgend einen plan was es da für Befehle gibt um den aktuellen 
Bildschirm nach Strings zu durchsuchen??

Bin Leider nur im Bereich Mikrocontroller unterwegs  und  hab daher fast 
keinen Plan von Windows bzw PC programmierung.

mfg Matthias
Gast #3063963
Lesenswert?

Matthias P. schrieb:
> Zb. wenn ich auf einer beliebigen Internetseite surfe und durch scrolle
> und dann irgendwo das wort "Hallo" steht soll ein Ton erklingen.
> Habt ihr irgend einen plan was es da für Befehle gibt um den aktuellen
> Bildschirm nach Strings zu durchsuchen??

geht im zweifelsfall überhaupt nicht. Es gibt programme die Rendern den 
Text als Bild. Da bräuchte man eine OCR.


sonst könnte man es über
http://msdn.microsoft.com/en-us/library/db50wx7h(v=vs.80).aspx

versuchen-
#3065119
Lesenswert?

Tja, dann sind alle Vorschläge natürlich sinnlos. Deshalb ist es 
manchmal nützlich, das Problem gleich zu nennen...

Solch ein Vorhaben halte ich für relativ knifflig, also zumindest von 
komplett außerhalb des Spiels. Den Framebuffer kannst du jedenfalls 
nicht die ganze Zeit durch OCR jagen*, das ist performancetechnisch 
total unmachbar. Selbst periodisch Screenshots aufzunehmen, sagen wir, 
alle halbe Sekunde... ich bin nicht sicher, ob das nicht ziemliche 
Ruckler verursachen würde.

Und dann muss man natürlich auf den Screenshots ein OCR machen. Das ist 
nochmal ziemlich schwierig, bei dem ganzen Kram der da rumfliegt (das 
OCR-Programm weiß ja erstmal gar nicht wo der Text überhaupt ist).

Fazit, nichts, von dem ich denke, dass ein Freizeitprogrammierer es in 
wenigen Tagen schreiben könnte.

Eine weitere Möglichkeit wäre allerdings, die Diablo-APIs zu 
durchstöbern -- vielleicht gibt's ja da was, was alle Items auf dem 
Bildschirm auflistet oder so. Keine Ahnung.

Oh, oder den Netzwerktraffic mitschneiden und dort nach dem Namen des 
Items greppen. Das könnte potentiell relativ einfach sein -- 
vorausgesetzt, die Kommunikation erfolgt unverschlüsselt (oder ist 
zumindest ohne viel Reverse-Engineering entschlüsselbar). Und falls die 
Namen der Items überhaupt über's Netzwerk gesendet werden, das muss ja 
auch nicht unbedingt der Fall sein.

Grüße,
Sven


_____
* ... außer vielleicht, man implementiert OCR in einem Shader! Das 
klingt doch interessant, ein OCR-Shader, oder?
#3065547
Lesenswert?

die Itemnamen werden mit Sicherheit nicht übers Netzwerk übertragen, da 
die Sprache am Client hängt. Außerdem ist die Kommunikation mit 
Sicherheit verschlüsselt. Auch von Direktmanipulation (Debugger, 
Prozessspeicher auslesen, oder gar patchen des Prozessspeichers) des 
Diablo-Prozesses würde ich absehen.

Das größte Problem ist imho das live-grabben eines screenshots. dafür 
gibt es sicherlich tools, die vielleicht auch eine API haben.
Der Rest ist ein wenig Bildverarbeitung.
die Items heben sich ja relativ gut vom Hintergrund ab und haben nur 
bestimmte Farben und definierte Schriftgröße.
Einfacher ist es wahrscheinlich ohne OCR sondern eher mit 
Templatematching mit gespeichertem Screenshot-Ausschnitt des gesuchten 
Wortes.
Was für einen Einfluss das am Ende in Summe auf die Framerate hat, kann 
ich nicht abschätzen, glaub aber nicht, dass das ein Problem ist mit 
vielleicht 20Hz auf einem eigenen Core das Bild zu verarbeiten. Man 
sollte natürlich nicht über die screenshot auf Festplatte 
speichern-Funktion von Diablo gehen.
Als erstes würde ich schauen, ob ein normales Print-Screen das Fenster 
erfasst, glaubs aber fast nicht, weil das im Direct3d läuft.

Ich finde das ganze aber relativ riskant. Blizzard sperrt gerne mal 
Accounts, wenn der Verdacht aufkommt, dass sich jemand mit Hilfe von 
Zusatzprogrammen Vorteile verschafft.

was für Items willst du denn Finden?
die Farbkodierung grau, weiß, hellblau, blau, gelb und golden ist imho 
recht gut gewählt und Ausreichend.

Edit:
Das Abspielen des Sounds am Ende ist ein Kleinigkeit.
#3065571
Lesenswert?

Vlad Tepesch schrieb:
> die Itemnamen werden mit Sicherheit nicht übers Netzwerk übertragen, da
> die Sprache am Client hängt.
Ok, guter Einwand -- vielleicht wird aber eine ID o.ä. übertragen, die 
sich äquivalent verwenden lässt.

> Außerdem ist die Kommunikation mit Sicherheit verschlüsselt.
Weißt du das oder vermutest du das? ;)

> Auch von Direktmanipulation (Debugger,
> Prozessspeicher auslesen, oder gar patchen des Prozessspeichers) des
> Diablo-Prozesses würde ich absehen.
Wieso? Auch nicht "riskanter" als Screenshots auswerten, wenn man es 
richtig macht, oder?

> Das größte Problem ist imho das live-grabben eines screenshots. dafür
> gibt es sicherlich tools, die vielleicht auch eine API haben.
Hier sehe ich überhaupt kein Problem, zumindest nicht bei der 
Machbarkeit -- bloß bei der Performance. Es gibt sicherlich tausende 
Tools die das können.

> Einfacher ist es wahrscheinlich ohne OCR sondern eher mit
> Templatematching mit gespeichertem Screenshot-Ausschnitt des gesuchten
> Wortes.
Das ist ebenfalls eine sehr gute Idee, die ist so gut, dass sie fast 
funktionieren könnte. ;)
Das ist dann natürlich auch viel schneller als OCR.
Ja, das könnte fast funktionieren: 2D-Cross Correlation von den beiden 
Bildern ausrechnen sollte relativ fix gehen, und dann einfach schauen ob 
das irgendwo einen bestimmten Wert überschreitet. Wenn man dann noch 
vermeidet, den Screenshot erst in PNG zu komprimieren und auf der Platte 
zu speichern, und stattdessen direkt die Pixel aus dem Speicher 
kopiert... könnte gehen.

Aber anscheinend ist der TO daran ja nicht so wirklich interessiert. ;)

Grüße,
Sven
#3065580
Lesenswert?

Evtl. kann man sich zwischen Diablo und DirectX einklinken, und den Text 
abfangen bevor er zu Texturen verwustet wird?
=> Keine OCR nötig?

Bei OpenGL/Linux wär das z.B. ein LD_PRELOAD, welches z.B. 
"glutBitmapCharacter"&co überwacht, oder entsprechende 
freetype-Funktionen.
Halt je nachdem wie im Programm das Text-Zu-Textur implementiert ist.

Aber wenn's nur für exakt ein Programm laufen soll, viel einfacher als 
OCR, und kostet (fast) keine Rechenzeit extra.
#3065748
Lesenswert?

Sven B. schrieb:
>> Außerdem ist die Kommunikation mit Sicherheit verschlüsselt.
> Weißt du das oder vermutest du das? ;)

ich weiß es nicht, bin mir aber extrem sicher, da Blizzard einiges an 
Aufwand treibt um Bots oder ähnliches zu unterbinden.
Deswegen würde ich alles vermeiden, was irgendwie in den Prozess 
eingreift.
Also auch:

Εrnst B✶ schrieb:
> Evtl. kann man sich zwischen Diablo und DirectX einklinken, und den Text
> abfangen bevor er zu Texturen verwustet wird?



Sven B. schrieb:
>> Das größte Problem ist imho das live-grabben eines screenshots. dafür
>> gibt es sicherlich tools, die vielleicht auch eine API haben.
> Hier sehe ich überhaupt kein Problem, zumindest nicht bei der
> Machbarkeit -- bloß bei der Performance.
Genau deswegen sehe ich da ein Problem, da fehlt mir aber die Erfahrung.
man könnte mal nach Open-Source Game-Screen-Recordern schauen.

Sven B. schrieb:
> Ja, das könnte fast funktionieren: 2D-Cross Correlation von den beiden
> Bildern ausrechnen sollte relativ fix gehen, und dann einfach schauen ob
> das irgendwo einen bestimmten Wert überschreitet.

Ich würde versuchen, mit einem möglichst billigem Verfahren sämtliche 
Item-Textboxen zu finden.
Dann in X-Richtung mein Template über die Boxen schieben und die 
Übereinstimmung berechnen.
Die Templates über das gesamte Bild zu schieben ist zu 
rechenzeitaufwendig.
Ein Problem könnte sein, dass man die Box bei dunklem Hintergrund nicht 
erkennen kann. Hier könnten die genauen Farbwerte der Schrift einen 
Anhaltspunkt liefern um eine Box zu generieren, in der man dann 
eventuell aber 2-dimensional das Template drüber schieben muss.
Den Einfluss des Hintergrundes hinter der teil-transparenten Box müsste 
man auch noch untersuchen. Das kriegt man aber sicher durch durch 
geschickte Bildverarbeitung weg. Ebenso wie die unterschiedlichen 
Farben, damit man nicht von jedem Typ ein Screenshot braucht.

Ich glaub ich probiere das heute Abend mal auf ein paar Beispiel 
Screenshots aus.

Mich würde trotzdem interessieren wofür er das will.
Mir würden nur die Rezepte einfallen, die in der Farbe des Items, das 
sie generieren fallen und die man eventuell übersieht, wenn man keine 
blauen sammelt. oder die dämonischen Essenzen, die man übersieht, wenn 
man gelb auch nicht aufhebt.
#3065783
Lesenswert?

Deshalb Cross Correlation: Mit der Box-Methode bist du auf jeden Fall in 
n², weil du im Endeffekt jeden Pixel ausprobieren musst. Nimmst du ein 
FFT-basiertes Verfahren [1], bist du in n log n -- ich denke sogar, dass 
das relativ einfach zu implementieren ist, wenn man die 2D-FFT schon hat 
(und die gibt's überall).

Grüße,
Sven

___
[1] 
http://www.mathworks.com/products/demos/image/cross_correlation/imreg.html?nocookie=true
#3066010
Lesenswert?

Wieso? Eine FFT von n Pixeln sollte in n log n sein. Die Bilder 
pixelweise übereinander zu schieben und zu vergleichen kostet dich n² -- 
ein n für jeden Schritt, und n Schritte.

2D Cross Correlation sollte eigentlich bloß zwei FFTs und eine 
Multiplikation sein.

Edit: Ach so, wahrscheinlich ist das ein Missverständnis: Ich meinte mit 
n die Anzahl der Pixel, du wahrscheinlich die Seitenlänge vom Bild. Dann 
ist das sowas wie n^2 log n vs n^4.
#3066038
Lesenswert?

ach so, ich meinte mit n tatsächlich die Bildkantenlänge (wobei es 
natürlich nicht quadratisch ist)

eigentlich gibts hier 2 Größen

B Anzahl Pixel im Bild (zB: 1960*1080 = 2.116.800)
T Anzahl Pixel des Templates (je nach Buchstabenzahl <4000)

ein einziger Vergleich hat mit FFT also T log T Aufwand (laut dir - 
keine Ahnung ob das stimmt. FTs sind nicht so meins)
ein einziger Vergleich mit SAD hat den Aufwand T

Diesen Vergleich macht man je nach Ansatz
 - über das gesamte Bild ~B mal
oder
 - nur an Fundstellen von Textboxen n*b*h mal
   n - Anzahl Textboxen(kandidaten) n<200
   b - Breite der Textboxen - Templatebreite b<150
   h - Höhe der Textboxen - Templatehöhe h<10


Die Frage ist, wie aufwendig die Detektion von Itemtextboxen ist.
wenn man mehrere Templates hat hat man auf jeden Fall durch die 
Einschränkung der möglichen Positionen schon mal enorm gewonnen.
#3066099
Lesenswert?

Ne! Der Witz an der FFT-Methode ist, dass sie das Template gleichzeitig 
mit allen Stellen vom Bild vergleicht. Du musst nur die beiden 
Fouriertransformierten ausrechnen, die eine komplex konjugieren, mit der 
anderen multiplizieren, rücktransformieren, Betrag bilden, und da wo der 
größte Wert ist, ist die beste Übereinstimmung zwischen den beiden 
Bildern. Man muss das nicht für jeden Pixel machen, sondern braucht 
nur genau 3 FFTs pro Template und Bild.

Für eine FFT von einer Million Punkten braucht numpy etwa eine zehntel 
Sekunde, also könnte das performancetechnisch machbar sein.

Grüße,
Sven
#3066661
Lesenswert?

Ok, das raff ich nicht.
kannst du das mal mit Matlab/Octave Code ausführen?
Ich kann es mir aber auch nicht wirklich vorstellen.
Wenn das so einfach wäre, würde es ja jeder fürs Template-Matching 
verwenden.

Bin gestern habend nicht zu so viel gekommen.
Die Boxen zu Extrahieren ist nicht ganz so einfach, das sie ziemlich 
schmal um den Text sind und scheinbar einem Transparenz-Gradienten 
haben.
Am erfolgversprechendsten sieht da noch eine Farbsegmentierung im 
HSV-Farbraum aus, wobei hier bei meinem Testbild bei der Unique-Farbe 
ziemlich viel Schrott mit aufsammelt wird. rare und set sieht ganz gut 
aus.

Übrigens:
die oben von dir verlinkte normxcross2 Funktion faltet auch das 
Eingabebild mit dem Template
#3067077
Lesenswert?

Hab das mal in python implementiert (Code unten).

Das erste Bild ist ein Beispiel-Bild was ich mit Gimp gemalt habe.
Das zweite ist dasselbe Bild um ein Stück verschoben (könnte auch ein 
Ausschnitt sein, kannst du gern ausprobieren).
Das dritte Bild ist die Cross correlation, die in n log n (n -> Anzahl 
der Pixel) berechnet werden kann (siehe Code für den Nachweis dafür, es 
werden nur FFTs und punkteweise Multiplikationen verwendet).
Das vierte Bild zeigt die Cross Correlation über das ursprüngliche Bild 
gelegt; der rote Punkt markiert, wie weit man example2.png verschieben 
muss, sodass es sich mit example1.png deckt. Es ist gut zu sehen, dass 
der hellste Punkt der Cross Correlation sich mit diesem roten Punkt 
gerade deckt.

Die Ausgabe vom hellsten Punkt in numpy passt irgendwie nicht, ich 
glaube man muss das noch spiegeln oder so, hatte jetzt aber keine Lust 
mehr das hinzubiegen.

Viel Spaß damit und viele Grüße,
Sven
1
#!/usr/bin/env python2
2
# -*- Coding:utf-8 -*-
3

4
# you need numpy and PIL to run this
5
import numpy as np
6
import Image, ImageOps
7

8
def imageToArray(image):
9
    grey = ImageOps.grayscale(image)
10
    data = grey.tostring()
11
    # there should be 1 byte for each pixel in that data
12
    assert len(data) == grey.size[0] * grey.size[1]
13
    # convert to an array, data type is unsigned char (8-bit greyscale)
14
    arr = np.fromstring(data, dtype=np.uint8)
15
    arr = arr.reshape(grey.size[0], grey.size[1])
16
    assert arr.shape == grey.size
17
    return arr
18

19
def arrayToImage(array):
20
    size = array.shape
21
    array -= array.min()
22
    array = array / array.max() * 255
23
    array = np.array(array, dtype=np.uint8).flatten()
24
    data = array.tostring()
25
    return Image.fromstring("L", size, data)
26

27
def register(image1, image2):
28
    input1 = imageToArray(image1)
29
    input2 = imageToArray(image2)
30

31
    # do fourier transform on both images
32
    fft1 = np.fft.fft2(input1)
33
    fft2 = np.fft.fft2(np.fliplr(np.flipud(input2)))
34

35
    arrayToImage(abs(fft1)).save("fft1.png")
36
    arrayToImage(abs(fft2)).save("fft2.png")
37

38
    # calculate F(im1) element-wise-multiply F(im2)
39
    fft_result = fft1 * fft2
40
    output = np.abs(np.fft.ifft2(fft_result))
41
    output = output / np.max(output) * 255
42

43
    print(np.unravel_index(np.argmax(output), output.shape))
44
    return arrayToImage(output)
45

46
if __name__ == '__main__':
47
    register(Image.open('example.png'), Image.open('example2.png')).save("result.png")
Angehängte Dateien:
#3068358
Lesenswert?

Sven B. schrieb:
> Hab das mal in python implementiert (Code unten).

kannst du die bilder mal erklären?
die fft-Bilder sind komplett schwarz (wert 0)
des result-bild sagt was aus?
Ich seh da zwei überlappte eingangsbilder.

wenn man nur ein paar dickere linien einzeichnet (ohne das pattern zu 
zerstören) findet er es schon nicht mehr.
AUf den Originalbildern aus dem Spiel funktioniert ganze natürlich 
überhaupt nicht. Dann zeigt die ausgegebene Position auf weißen Bereich, 
wo überhaupt nix zu sehen ist.

wirklich überzeugt bin ich von dem Ansatz nicht.


Da Dieter schrieb:
> Cheater haben kleine Schwänze.
was soll daran ein cheat sein?
Man erkennt, wenn ein bestimmtes item gedropt wird - und? Außer den 
Vorteil, dass man es so nicht übersieht hat das genze überhaupt keinen 
Einfluss.
#3068516
Lesenswert?

Vlad Tepesch schrieb:
> Sven B. schrieb:
>> Hab das mal in python implementiert (Code unten).
>
> kannst du die bilder mal erklären?
> die fft-Bilder sind komplett schwarz (wert 0)
Das bezweifle ich, schau mal genauer hin. Es sind viele Pixel schwarz, 
ja, aber nicht alle. Die beiden Bilder sind die Fouriertransformierten 
der zwei Eingangsbilder.

> des result-bild sagt was aus?
Das ist das rücktransformierte Korrelations-Bild, der hellste Punkt ist 
der Punkt bester Korrelation.

> Ich seh da zwei überlappte eingangsbilder.
Hm? Poste mal eins davon.

> wenn man nur ein paar dickere linien einzeichnet (ohne das pattern zu
> zerstören) findet er es schon nicht mehr.
> AUf den Originalbildern aus dem Spiel funktioniert ganze natürlich
> überhaupt nicht. Dann zeigt die ausgegebene Position auf weißen Bereich,
> wo überhaupt nix zu sehen ist.
Soweit ich weiß, muss der Pattern im Muster-Bild links oben vom 
Vorkommen im tatsächlichen Bild sein. Dazu kommt halt, dass einfach so 
mit harten Kanten einen Pattern rausschneiden nicht so gut ist, man 
sollte ein geeignetes Fenster wählen (quadratusch oder exponentiell oder 
was auch immer). In meinem Beispiel hab ich mir das gespart, indem ich 
das Bild gar nicht zerschnitten habe.

> wirklich überzeugt bin ich von dem Ansatz nicht.
Mathematisch gesehen ist die Methode perfekt. Klar ist natürlich, dass 
das so ohne geeignete Filter in der Realität nicht funktionieren wird. 
Damit muss man sich halt noch beschäftigen ;)
Insbesondere ist es wichtig, für den gewählten Bildausschnitt die Kanten 
auf die richtige Weise zu glätten.

Davon abgesehen bin ich mir zugegebenermaßen auch nicht hundertprozentig 
sicher, dass ich das richtig implementiert habe, vielleicht ist da noch 
was falsch *g

Grüße,
Sven
#3068544
Lesenswert?

Ah, hier ist der Fehler: fft2 mag keine nicht-quadratischen Bilder, nimm 
mal quadratische Eingabedateien, dann funktioniert es sehr gut. Daher 
kommen auch die komischen Streifen.

Im Anhang nochmal ein Beispiel für Text.

Wegen der FFT-Bilder, hm, ja irgendwas ist da schon komisch, es sind 
zuviele Pixel schwarz, da hast du Recht (nicht alle!). Finde das Problem 
aber gerade nicht...
Ah, doch, ersetze mal das abs durch np.abs in der Zeile wo die 
ausgegeben werden. Dann passt es.
Angehängte Dateien:
#3068835
Lesenswert?

Sven B. schrieb:
> Ah, hier ist der Fehler: fft2 mag keine nicht-quadratischen Bilder, nimm
> mal quadratische Eingabedateien, dann funktioniert es sehr gut. Daher
> kommen auch die komischen Streifen.

ahh, hetzt sind die bilder nachvollziehbar.

im anhang mal zwei praxisbeispiele.

schwarzweis ist natürlich nicht optimal, da die Farbe hier sehr viel 
Information trägt. Man könnte im HSV Farbraum die 3 Kanäle separat 
bearbeiten und die Ergebnisse verunden und dann Maxima suchen.
Angehängte Dateien:
Gast #3068881
Lesenswert?

Zurück zum ursprünglichen Tema:

Nein, es geht nicht.

Zu Zeiten der ersten PC's gab es noch einen Bildschirmspeicher, in dem 
tatsächlich die dargestellten Zeichen standen - lang, lang ist's her.

Wenn heutzutage überhaupt Zeichen dargestellt werden, so sind die durch 
den gerade aktuellen Zeichensatz, Renderer und anderes kräftig 
durchgerührt worden.

Ein einfacher Versuch, den Du jederzeit machen kannst ist: Rufe ein 
beliebiges Textdokument auf und Fummel am Zeichensatz rum. Der Text 
bleibt zwar der gleiche, das Aussehen ist aber, je nach Zeichensatz oder 
Zeichengröße, verschieden. Jedes Programm, das das lesen wollte, müsste 
sich mit dem "Aussehen" rumärgern.

Im Grunde gibt es nur zwei Möglichkeiten, zu lesen was auf dem 
Bildschirm angezeigt ist.
1. Du kommst irgendwie an die Quelldaten (txt, html ...) ran und
   liest diese.
2. Du lässt einen Screenreader (OCR) auf deinen Bildschirm los.
#3068955
Lesenswert?

Hä? Wie nahe am ursprünglichen Thema sollten wir denn noch sein?

--

Ha! Jetzt hab ich's aber komplett verstanden: was hier noch fehlte, war 
eine Normalisierung des Produkts. Deshalb war die Korrelation auch immer 
scheinbar dort größer, wo die Bilder heller waren, was natürlich keinen 
Sinn macht (um das nochmal klar zu sagen: der Code, den ich oben 
gepostet habe, funktioniert nicht vernünftig). Jetzt aber funktioniert 
es perfekt! Deine Bilder habe ich noch leicht trivial modifiziert, um 
Randeffekte zu vermeiden, und habe das perfekt zur weiteren Verarbeitung 
geeignete Ergebnis aus dem Anhang erhalten (man muss Rechtsklick -> view 
image machen und dann vergrößern, sonst sieht man nix -- sind nur wenige 
helle Pixel).

Um das nochmal klar zu erwähnen: Die bearbeiteten Bilder dürfen keine 
künslichen scharfen Kanten haben. Solche scharfen Kanten verursachen 
in der FFT große Störungen und beeinträchtigen die Qualität des 
Ergebnisses enorm.

Grüße,
Sven

Ach, hier noch der korrigierte Code:
1
#!/usr/bin/env python2
2
# -*- Coding:utf-8 -*-
3

4
import numpy as np
5
import Image, ImageOps
6

7
def imageToArray(image):
8
    grey = ImageOps.grayscale(image)
9
    data = grey.tostring()
10
    # there should be 1 byte for each pixel in that data
11
    assert len(data) == grey.size[0] * grey.size[1]
12
    # convert to an array, data type is unsigned int
13
    arr = np.fromstring(data, dtype=np.uint8)
14
    arr = arr.reshape(grey.size[0], grey.size[1])
15
    assert arr.shape == grey.size
16
    return arr
17

18
def arrayToImage(array):
19
    size = array.shape
20
    array -= array.min()
21
    array = array / array.max() * 255
22
    array = np.array(array, dtype=np.uint8).flatten()
23
    data = array.tostring()
24
    return Image.fromstring("L", size, data)
25

26
def register(image1, image2):
27
    input1 = imageToArray(image1)
28
    input2 = imageToArray(image2)
29
    # normalize images
30
    input1 = ( input1 - np.mean(input1) ) / np.std(input1)
31
    input2 = ( input2 - np.mean(input2) ) / np.std(input2)
32

33
    # do fourier transform on both images
34
    fft1 = np.fft.fft2(input1)
35
    fft2 = np.fft.fft2(np.fliplr(np.flipud(input2)))
36

37
    # calculate F(im1) element-wise-multiply F(im2)
38
    fft_result = fft1 * fft2 / np.abs(fft1 * fft2)
39
    output = np.abs(np.fft.ifft2(fft_result))
40
    output = output / np.max(output) * 255
41

42
    print(np.unravel_index(np.argmax(output), output.shape))
43
    return arrayToImage(output)
44

45
if __name__ == '__main__':
46
    register(Image.open('example.png'), Image.open('example2.png')).save("result.png")
Angehängte Dateien:
#3068991
Lesenswert?

Heh, noch ein Beitrag, zum Abschluss der Verwirrung: Das Problem kam 
daher, dass man nicht die Cross Correlation, sondern die punktweise 
normierte Cross Correlation berechnen muss. Dieser Artikel erklärt das 
Verfahren [1]. Man nimmt also nur die Phase von dem Produkt im 
Frequenzraum, und wirft die Amplitude weg.

Grüße,
Sven
__
[1] http://en.wikipedia.org/wiki/Phase_correlation

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren