Forum: PC-Programmierung Bildschirm nach String durchsuchen


von Matthias P. (Firma: privat) (sogge)


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

von Peter II (Gast)


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-

von LoL (Gast)


Lesenswert?

screenshot => OCR => search => ton

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

Wenn es nur um Webseiten geht, kann Proxomitron Text erkennen und auch 
ändern, und ist da relativ einfach machbar. Hm, über den Ton müßte man 
nochmal nachdenken. Reicht ein Alert-Dialog? Das geht auf jeden Fall. Hm 
hm, Sound abspielen können Webseiten doch auch, dann gehts auch in 
Proxomitron.

von Markus B. (markusborti)


Lesenswert?

Eventuell würde dir Javascript + GreaseMonkey helfen.

Da könntest du mit Javascript ein HTML-5-Element erzeugen und das direkt 
abspielen.
Dürfte auch mit einer Datei auf dem eigenen Rechner funktionieren

von ul5255 (Gast)


Lesenswert?


von Matthias P. (Firma: privat) (sogge)


Lesenswert?

Danke schon mal.
Also um es komplett auf zu klären.
Das ganze soll für Diablo3 sein ich möchte quasi ein Programm im 
hintergrund laufen lassen das mir einen Ton gibt wenn bestimmte 
Itemnamen auftauchen.

von Sven B. (scummos)


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?

von Matthias P. (Firma: privat) (sogge)


Lesenswert?

mhh ja ka ich weiß nur das es funktioniert weil ich es in nem youtube 
Vid. gesehen habe :)

Naja dachte das man einfach den Outstream von der Grafikkarte 
druchsuchen könnte :-P
Hab ich mich wohl getäuscht.

Aber Trotzdem danke :-P

von Frank (Gast)


Lesenswert?

Es gibt im Web ein Open Source Projekt zum Scannen von Autonummern 
"automate number plate scanning" im laufenden Verkehr, das beruht auf 
der mittlerweile freien OCR-Software Tesseract. Da dürften die 
Anforderungen änhlich sein ... vlt. lässt sich davon etwas ableiten.

http://www.youtube.com/watch?v=9vzR_H-jjHk

von Sven B. (scummos)


Lesenswert?

Tesseract braucht bei mir ca. 1.6 Sekunden, um ein Fullscreen-Bild zu 
durchsuchen. Gut, angenommen man hat 8 CPU-Cores und kann irgendwie 4 
davon komplett für 4 parallel laufende Tesseract-Instanzen abzweigen... 
trotzdem irgendwie zweifelhaft, ob das zufriedenstellend funktioniert ;)

von Vlad T. (vlad_tepesch)


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.

von Vlad T. (vlad_tepesch)


Lesenswert?

Matthias P. schrieb:
> mhh ja ka ich weiß nur das es funktioniert weil ich es in nem youtube
> Vid. gesehen habe :)

dann frag doch den Autor, was er für ein Programm benutzt.

von Sven B. (scummos)


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

von Εrnst B. (ernst)


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.

von Robert L. (lrlr)


Lesenswert?

ist das ein Online Spiel?

die haben doch sicher (einige) Vorkehrungsmaßnahmen um solche Cheats zu 
verhindern..

von Sven B. (scummos)


Lesenswert?

Robert L. schrieb:
> ist das ein Online Spiel?
>
> die haben doch sicher (einige) Vorkehrungsmaßnahmen um solche Cheats zu
> verhindern..
Deine Hardware zeichnet den Text, also kann dich prinzipiell nichts 
daran hindern, das zu überwachen wie du willst.

von PaulPanzer (Gast)


Lesenswert?

Ich weiss von anderen Online Games dass man dort Addons schreiben kann.

Geht das  nicht auch für Diablo III? Dass Addon müsste nur den Chat 
parsen und entsprechend eine Rückmeldung geben.

von Vlad T. (vlad_tepesch)


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.

von Sven B. (scummos)


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

von Vlad T. (vlad_tepesch)


Lesenswert?

was ich beschreibe ist doch auch eine Cross Correlation Analyse.
Auf das Vergleichskriterium hab ich mich doch gar nicht festgelegt.

Ich hatte aber eher SAD im Sinn.

Mir ist aber auch nicht klar, wie du auf nlogn kommst.
2d-cross correlation an sich ist doch schon n²

von Sven B. (scummos)


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.

von Vlad T. (vlad_tepesch)


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.

von Sven B. (scummos)


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

von Vlad T. (vlad_tepesch)


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

von Sven B. (scummos)


Angehängte Dateien:

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")

von Da D. (dieter)


Lesenswert?

Cheater haben kleine Schwänze.

von Sven B. (scummos)


Lesenswert?

Ich glaube der Thread hat sich inzwischen weit genug vom ursprünglichen 
Thema entfernt, dass es hier kaum mehr um's cheaten geht :D

von Stefanie B. (sbs)


Lesenswert?

@Sven:

Wenn man nun deinen Ansatz nimmt und noch eine Maximumssuche durchführt 
(hellster pixel in der crosscorrelation) und darauf einen entscheider 
aufsetzt, kann man die Texte finden ;) und damit sind wir wieder beim 
cheaten :P

von Sven B. (scummos)


Lesenswert?

Ja, aber wer von den Leuten hier in dem Thread, die in der Lage sind, 
das Proof-of-Concept-Skript zum funktionierenden Cheat-Tool umzubauen, 
wird das tun? Ich jedenfalls nicht. ;)

von Vlad T. (vlad_tepesch)


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.

von Sven B. (scummos)


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

von Sven B. (scummos)


Angehängte Dateien:

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.

von Vlad T. (vlad_tepesch)


Angehängte Dateien:

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.

von amateur (Gast)


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.

von Sven B. (scummos)


Angehängte Dateien:

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")

von Sven B. (scummos)


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

von Vlad T. (vlad_tepesch)


Lesenswert?

oh, das sieht gut aus. AUch auf fremden Bildern.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.