Jump to content

OCR Texterkennung eines Screenshot-Ausschnitts


Recommended Posts

@duffyduck12

Man braucht nur für den

gewünschten Bildausschnitt einen Hash-Wert ermitteln und vergleicht diesen mit zuvor gespeicherten Werten.

So wird’s gemacht.

Denke aber, dass ihn so etwas noch mehr verwirrt, zumal er zunächst solche Probleme hatte:

Ausserdem müsste die Bildaufnahme sehr genau arbeiten, um zwei exakt gleiche Bilder zu erhalten, um sie z.B. nach Dateigröße vergleichen zu können.

@Zocker85

schau mal nach

FindWindow();

GetWindowRect();

LG

Hütchenspieler :reindeer:

bearbeitet von Hütchenspieler
Link zu diesem Kommentar
Auf anderen Seiten teilen

@duffyduck12

Wie bei vielen Programmierern betrifft meine Arbeit nur einen sehr speziellen Teilbereich. Von OCR hatte ich eben keine Ahnung.

Was kein Problem ist, ist das Vergleichen der Bitmaps mit SHA256hash, so wie ichs jetzt auch umgesetzt hab (Pixel für Pixel vergleich ich natürlich nicht!)

das ganze sieht etwa so aus

public static bool AreBitmapsEqual(Bitmap pic1, Bitmap pic2)
{
if (Bitmap.ReferenceEquals(pic1, pic2)) return true;
if (!pic1.Width.Equals(pic2.Width)) return false;
if (!pic1.Height.Equals(pic2.Height)) return false;
if (!pic1.PixelFormat.Equals(pic2.PixelFormat)) return false;

try
{
ImageConverter conv = new ImageConverter();
Byte[] imgBytes1 = new Byte[1];
Byte[] imgBytes2 = new Byte[1];
imgBytes1 = (Byte[])conv.ConvertTo(pic1, imgBytes1.GetType());
imgBytes2 = (Byte[])conv.ConvertTo(pic2, imgBytes2.GetType());

SHA256Managed sha = new SHA256Managed();
Byte[] imgHash1 = sha.ComputeHash(imgBytes1);
Byte[] imgHash2 = sha.ComputeHash(imgBytes2);

for (int i = 0; i < imgHash1.Length && i < imgHash2.Length; i++)
{
if (!imgHash1[i].Equals(imgHash2[i]))
return false;
}

return true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return false;
}
}

und wie holst du dir die Fensterposition des "Online-Roulette"-Fensters, dass ja nicht zum eigentlichen Programm gehört?

Wie kannst du dieses Fenster über Code ansprechen???

Link zu diesem Kommentar
Auf anderen Seiten teilen

...

Was kein Problem ist, ist das Vergleichen der Bitmaps mit SHA256hash...

Genau so sollte es meiner Meinung nach nicht laufen!

Du vergleichst immer noch zwei Bitmaps:

Also ein Soll-/Ist-Vergleich auf Pixelebene.

Dazu muss jedes Bitmap als Vorlage zunächst gespeichert und für Vergleichszwecke

wieder aufgerufen werden.

Es reicht jedoch, die Hash-Werte (Prüfsummen) zu speichern und für den aktuellen Vergleich

heranzuziehen. Das ist wesentlich effizienter und übersichtlicher.

Natürlich gibt es viele Lösungswege für ein Problem. Ich tendiere jedoch immer zu einer

ressourcenschonenden Programmierung, auch wenn die Hardware heutzutage Leistung im Überfluss bietet.

Link zu diesem Kommentar
Auf anderen Seiten teilen

@Hüttenspieler:

FindWindow();

GetWindowRect();

DAS hab ich gesucht! Danke!

Dazu noch ein kleiner Hinweis.

Bei mir gab es dabei ein kleines Problem mit unterschiedlichen Betriebssystemen, was aber nur

am Anzeigedesign und nicht am Betriebssystem lag.

Wenn unterschiedliche Designs verwendet werden (Windows klassisch, XP Stil, ...) muss die Höhe ggf. leicht nachjustiert werden, weil die Fensterrahmen oben unterschiedlich breit sein können.

LG

Hütchenspieler :reindeer:

bearbeitet von Hütchenspieler
Link zu diesem Kommentar
Auf anderen Seiten teilen

Sowas hab ich schon vermutet. Aber das ist verkraftbar.

Nächste Frage: wie hast du mit FindWindow() den "richtigen" Prozess geholt?

Also ich habs jetzt do gelöst:

Mit dieser Funktion Wird dem Benutzer in einer ComboBox eine Liste aller ProzessFensterNamen bereitgestellt:

[DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount);


public static List<string> GetWindowNames()
{
StringBuilder title;
string strTemp;
List<string> lstProcessTitels = new List<string>();
foreach (Process p in Process.GetProcesses())
{
title = new StringBuilder();
GetWindowText(p.MainWindowHandle, title, int.MaxValue);
strTemp = title.ToString();
if (!String.IsNullOrEmpty(strTemp.Trim()))
lstProcessTitels.Add(strTemp);
}
return lstProcessTitels;
}

Wenn er danach einen ProzessTitel ausgewält hat, greift diese Funktion für die Position des Fensters:

		[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr FindWindow(string strClassName, string strWindowName);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool GetWindowRect(IntPtr hWnd, ref Rectangle rect);

public static Point GetWindowPosition(string strWindowName)
{
IntPtr WindowHandle = FindWindow(null, strWindowName);
Rectangle rect = new Rectangle();
GetWindowRect(WindowHandle, ref rect);

return new Point(rect.X, rect.Y);
}

Weist du da noch was besseres (evtl. ohne Benutzer-Eingabe)?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Habe stumpf den Fenstertitel gesucht.

(Bei DB gibt es ja nur 2 Tische)

Ungefähr so:

CWnd *casinofenster;

casinofenster = FindWindow(NULL,TEXT("DublinBet.com - Roulette 1"));

if (casinofenster != NULL )
{
gefunden = 1;
casinofenster->GetWindowRect(Position);
casino_x = Position->left;
casino_y = Position->top;
casinofenster->SetForegroundWindow();
}

if(gefunden == 0)
{
casinofenster = FindWindow(NULL,TEXT("DublinBet.com - Roulette 2"));
if (casinofenster != NULL )
{
gefunden = 1;
casinofenster->GetWindowRect(Position);
casino_x = Position->left;
casino_y = Position->top;
casinofenster->SetForegroundWindow();
}
}

if(gefunden == 0)
{
wie oben die Tische mit hohen Einsätzen prüfen...
(haben etwas andere Namen)
}

if(gefunden == 0)
{
AfxMessageBox("Casino konnte nicht gefunden werden ..... ");
}

LG

Hütchenspieler :reindeer:

bearbeitet von Hütchenspieler
Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich sach immer:

Im Zweifel lieber kopieren statt kapieren. :reindeer:

Wildcards mag FindWindow nicht.

Aber das ist verkraftbar.

Ist kein Thema.

Nimm einfach einen kleinen Bildausschnitt, der sich nicht verändert.

Beim Start kannst du dann kurz checken, bei welcher Höhe der Hashwert passt.

Die Fensterposition besorge ich mir vor jeder Aktion neu, falls der User das Fenster mal mal verschiebt.

LG

Hütchenspieler :lachen:

bearbeitet von Hütchenspieler
Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich sach immer:

Im Zweifel lieber kopieren statt kapieren. :reindeer:

LOL – der ist gut.

Aber ihr sprecht anscheinend nicht die gleiche Sprache. C# von Zocker85 erkenn' ich, aber was ist das Zeug von dir, Hütchenspieler?

C++ eventuell, da muss ich leider passen.

@Zocker85: Wenn du schon die Liste der Fensternamen dem Benutzer zeigen kannst, dann kannst du doch im Programm auch gleich selber die Liste durchlaufen und das passende Fenster wählen.

Danke euch für den Code... lasst' nur dich nicht abhalten mehr davon zu posten, (C# wenn möglich) mir ist kopieren manchmal auch am liebsten. Da hat man gleich mal eine Ausgangsbasis :lachen::

Gruß, Optimierer

bearbeitet von Optimierer
Link zu diesem Kommentar
Auf anderen Seiten teilen

Genau, das ist C++.

Letztlich geht es hier um den Aufruf von API-Funktionen.

Das ist aus nahezu jeder Sprache möglich.

Ist schon klar.

Welche Sprache brauchst Du?

Am besten C# oder J#oder auch JavaFx. Es soll auch eine Perl-Variante geben, mit der man richtige Anwendungen basteln kann.

Nur C++ kenne ich leider überhaupt nicht :reindeer:.

Gruß, Optimierer

Link zu diesem Kommentar
Auf anderen Seiten teilen

Guten Morgen,

@Optimierer

Wenn du schon die Liste der Fensternamen dem Benutzer zeigen kannst, dann kannst du doch im Programm auch gleich selber die Liste durchlaufen und das passende Fenster wählen.

Ich möchte mit diesem Programm sehr variabel sein, das heißt, wenn ich ein neues Online Casino finde, das ich testen will, will ich später nicht mehr im SourceCode rumspielen müssen.

Aber jetzt klappts auch mit Combobox sehr angenehm. (siehe Screenshot links oben)

Danke euch für den Code... lasst' nur dich nicht abhalten mehr davon zu posten, (C# wenn möglich) mir ist kopieren manchmal auch am liebsten. Da hat man gleich mal eine Ausgangsbasis

Wenn mein Prog fertig ist, werde ich hier im Forum eine Demo-Version kostenlos online stellen.

FALLS die gut ankommt, werde ich über einen kleinen Verkauf nachdenken. (zu einem fairen Preis)

Wer an SoureCode interessiert ist: da kann man dann schon was machen. (kleine Fetzen poste ich gern ins Forum, wenn jemand ne spezielle Frage hat)

Sonderwünsche mit einbauen ist auch (meistens) kein Stress.

Link zu diesem Kommentar
Auf anderen Seiten teilen

...

Aber jetzt klappts auch mit Combobox sehr angenehm. (siehe Screenshot links oben)

...

Also wenn der User schon alles per Mausklick deinem Programm zeigen soll,

dann kann er doch auch das Casinofenster per Klick auf z.B. die Titelleiste auswählen!

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 4 weeks later...

interessantes Thema :-)

Bin selbst auch Softwareentwickler und hatte mir das auch immer vorgenommen,

ansich ja keine allzu komplezierte Sache. Das schwierigste ist wohl die Zahlenerkennung.

Allerdings lohnt sich die ganze Sache ja wirklich nur wenn man ein gewinnbringendes System hat, da muss ich meinem Vorposter recht gebene.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also ich bin noch am Programmieren!

:huhu:

hab leider am Abend nicht immer Bock, dran weiter zu arbeiten, weil ich bei der Arbeit den ganzen Tag schon vorm PC sitze. Aber ich konnte schon mal etwas testen. Das Programm läuft auf jeden Fall! Aber mir fallen immer wieder neue Sachen ein, die ich noch umsetzen kann. (Naja, ich denk mir: Wenn dann gscheit!)

Das mit dem System ist natürlich noch ein anderes Thema :lesen:

Das wäre auch meine erste Wahl gewesen, aber da das mit der Methode "Bild in Hash umwandeln und Hashes vergleichen" super funktioniert, bin ich dabei geblieben.

Vorteil: Fehl-Erkennung einer Zahl ist ausgeschlossen, da nicht die Zahl selber erkannt wird, sondern das Bild, auf dem die Zahl drauf ist.

Nachteil: wenn man in einem OC spielen will, muss man erstmal alle Bilder (bzw. Hashes) der Zahlen abspreichern. Das geht aber relativ flott. In 5 Minuten ist ein Online Casino komplett in meiner Software abgespeichert, mit sämtlichen Zahlen und Koordinaten.

Ich freu mich schon, wenns fertig ist und ich hier ein Demo präsentieren kann. Ich will bis Weihnachten fertig sein, dann hab ich Urlaub und Zeit zum testen. :kaffeepc:

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 5 weeks later...

Also ich bin noch am Programmieren!

:)

hab leider am Abend nicht immer Bock, dran weiter zu arbeiten, weil ich bei der Arbeit den ganzen Tag schon vorm PC sitze. Aber ich konnte schon mal etwas testen. Das Programm läuft auf jeden Fall! Aber mir fallen immer wieder neue Sachen ein, die ich noch umsetzen kann. (Naja, ich denk mir: Wenn dann gscheit!)

Das mit dem System ist natürlich noch ein anderes Thema :clap:

Das wäre auch meine erste Wahl gewesen, aber da das mit der Methode "Bild in Hash umwandeln und Hashes vergleichen" super funktioniert, bin ich dabei geblieben.

Vorteil: Fehl-Erkennung einer Zahl ist ausgeschlossen, da nicht die Zahl selber erkannt wird, sondern das Bild, auf dem die Zahl drauf ist.

Nachteil: wenn man in einem OC spielen will, muss man erstmal alle Bilder (bzw. Hashes) der Zahlen abspreichern. Das geht aber relativ flott. In 5 Minuten ist ein Online Casino komplett in meiner Software abgespeichert, mit sämtlichen Zahlen und Koordinaten.

Ich freu mich schon, wenns fertig ist und ich hier ein Demo präsentieren kann. Ich will bis Weihnachten fertig sein, dann hab ich Urlaub und Zeit zum testen. :fun2:

Lange Rede kurzer Sinn.

Es muß kein Super intelligentes System sein, um Roulettezahlen einzulesen.

Auch nicht wenn man die Casionos wechselt und andere Zahlen Bilder bekommt.

Ich lese hier dauernd .... Ich bin (angehender) Programmierer ... ???

Punkt 1. Bestimme den einzulesenden Bildschirmausschnitt.

Punkt 2. Lese diesen ein, und vergleiche ob er schon bekannt und spezifiziert wurde.

Wenn er bekannt war, ermittelt das Programm einfach die Zahl,

wenn er nicht bekannt war, fragt das Programm (genau 1 mal) nach, welche Ziffer es darstellt.

... und spezifiziert sie.

Ich hab mir tatsache noch die Mühe gemacht, daß in VBA und MS-Excel (und API's )zu programmieren.

Die Möglichkeiten mit Net-Framework machen dies gerade-zu zu einem Kinderspiel.

Allerdings nur, wenn man wirklich schon ein bischen Programmierer ist.

Mein Excel - Tool spielt jedenfalls stundenlang absolut selbstständig, nach vorgegebenen Strategien. (Selbstverständlich Online)

Allerdings ..... gewinnt es genau so wenig wie ich ....

Bei ernsthaftem Interesse wurde ich den VBA-Code einstellen,

möchte danach aber nicht mit Fragen gelöchert werden :-)

Gruß MsoProfi

bearbeitet von msoprofi
Link zu diesem Kommentar
Auf anderen Seiten teilen

@msoprofi

Wäre mal eine gute Idee, wenn du den VBA-Code als Datei zum runterladen rienstellen könntest. :bigsmile:

Grüße

Mike32

Lange Rede kurzer Sinn.

Es muß kein Super intelligentes System sein, um Roulettezahlen einzulesen.

Auch nicht wenn man die Casionos wechselt und andere Zahlen Bilder bekommt.

Ich lese hier dauernd .... Ich bin (angehender) Programmierer ... ???

Punkt 1. Bestimme den einzulesenden Bildschirmausschnitt.

Punkt 2. Lese diesen ein, und vergleiche ob er schon bekannt und spezifiziert wurde.

Wenn er bekannt war, ermittelt das Programm einfach die Zahl,

wenn er nicht bekannt war, fragt das Programm (genau 1 mal) nach, welche Ziffer es darstellt.

... und spezifiziert sie.

Ich hab mir tatsache noch die Mühe gemacht, daß in VBA und MS-Excel (und API's )zu programmieren.

Die Möglichkeiten mit Net-Framework machen dies gerade-zu zu einem Kinderspiel.

Allerdings nur, wenn man wirklich schon ein bischen Programmierer ist.

Mein Excel - Tool spielt jedenfalls stundenlang absolut selbstständig, nach vorgegebenen Strategien. (Selbstverständlich Online)

Allerdings ..... gewinnt es genau so wenig wie ich ....

Bei ernsthaftem Interesse wurde ich den VBA-Code einstellen,

möchte danach aber nicht mit Fragen gelöchert werden :-)

Gruß MsoProfi

Link zu diesem Kommentar
Auf anderen Seiten teilen

...<Bei ernsthaftem Interesse wurde ich den VBA-Code einstellen,

möchte danach aber nicht mit Fragen gelöchert werden :-)

...

Hallo MSO Profi,

ernsthaftes Interesse besteht definitiv. Wäre super, wenn Du Dein Material zur Verfügung stellen könntest. Quasi als Weihnachtsgeschenk :wink4:

Danke

Gruß

silent

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wie ist deine Meinung dazu?

Du kannst jetzt schreiben und dich später registrieren. Bereits registrierter Teilnehmer? Dann melde dich jetzt an, um einen Kommentar zu schreiben.
Hinweis: Dein Beitrag wird nicht sofort sichtbar sein.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Neu erstellen...