Farb/Schrift erkennung

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
OcolusNoun
User
Beiträge: 9
Registriert: Freitag 14. August 2020, 14:33

Hallo alle miteinander :)

Ich habe mich gefragt ob es möglich ist eine Bildschirmabfrage in einem bestimmten Berreich zu machen und daraufhin gewisse Actionen zu machen.
Beispiel: Checke diesen Berreich. Wenn er Gelb schreib das. Wenn er Blau ist schreib das.
Das ganze soll in Kombination mit dem pynput.keyboard funktionieren.
Das gleiche dann auch mit der Erkennung von Schrift und Zahlen in einem bestimmten Berreich.

Vielen dank im vorraus für eure Antworten.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

ZB mit https://python-mss.readthedocs.io/ und OpenCV geht das.
Benutzeravatar
Briter
User
Beiträge: 4
Registriert: Freitag 14. August 2020, 18:31

Dies kann durch eine Bereichsabfrage implementiert werden, habe ich richtig verstanden, dass der Text ersetzt werden muss?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich denke hier geht es um einen Game Bot. Reagieren auf spielgrafik & dann Eingaben simulieren. Was von ersetzen kommt da nicht vor.
OcolusNoun
User
Beiträge: 9
Registriert: Freitag 14. August 2020, 14:33

@__deets__ exakt das soll es werden. Dann gucke ich mir OpenCV mal an. Vielen Dank.
OcolusNoun
User
Beiträge: 9
Registriert: Freitag 14. August 2020, 14:33

Hey ich bins nochmal :)

ich hab jetzt die Tage bisschen was probiert und mein Script nimmt langsam form an. Leider hat es ein kleines Problem...es funktioniert nicht.

import time
import pyautogui
from pynput.keyboard import Key, Controller
keyboard = Controller()

##Common 13 91 245
##Uncommon 14 181 229
##Rare 251 137 34
##Superrare 248 242 65
##Legendary 161 38 242
##Legendary2 122 250 67
##Shiny 255 155 202

##Kordinaten 392 860


print("Starting", end="")
for i in range(0, 5):
print(".", end="")
time.sleep(1)
print("Go")

x = 1

while x < 10:
keyboard.type(';p')
keyboard.press(Key.enter)
time.sleep(3)
if pyautogui.pixelMatchesColor(392, 860, (13, 91, 245)):
keyboard.type('pb')
keyboard.press(Key.enter)
elif pyautogui.pixelMatchesColor(392, 860, (14, 181, 229)):
keyboard.type('pb')
keyboard.press(Key.enter)
elif pyautogui.pixelMatchesColor(392, 860, (251, 137, 34)):
keyboard.type('gb')
keyboard.press(Key.enter)
elif pyautogui.pixelMatchesColor(392, 860, (248, 242, 65)):
keyboard.type('ub')
keyboard.press(Key.enter)
elif pyautogui.pixelMatchesColor(392, 860, (161, 38, 242)):
keyboard.type('mb')
keyboard.press(Key.enter)
elif pyautogui.pixelMatchesColor(392, 860, (122, 250, 67)):
keyboard.type('mb')
keyboard.press(Key.enter)
elif pyautogui.pixelMatchesColor(392, 860, (255, 155, 202)):
keyboard.type('mb')
keyboard.press(Key.enter)
else:
keyboard.type('pb')
keyboard.press(Key.enter)
time.sleep(9)


Er springt immer bis zum else: durch da er mit den angaben vorher nichts anfangen kann. Die "392, 860" sind die "Bildschirmkordinaten". Die drei danach die RGB angabe.
Hat einer von euch eine Idee wie ich das zum laufen bekomme?
OcolusNoun
User
Beiträge: 9
Registriert: Freitag 14. August 2020, 14:33

Ich muss dazu noch sagen das ich mir OpenCV angeguckt habe aber als blutiger Anfänger hab ich mir da die Zähne ausgebissen :D Einen Screenshot konnte ich erstellen und auch wieder löschen lassen aber in Richtung Farberkennung war da bei mir vorbei.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Bitte deinen Code in die dazugehörigen Tags setzten, so sind alle Einrückungen verloren.
OcolusNoun
User
Beiträge: 9
Registriert: Freitag 14. August 2020, 14:33

Ah ja okay... Da hätte ich selbst drauf kommen können das das Sinn machen würde. Hier nochmal in vernümpftig.

Code: Alles auswählen

import time
import pyautogui
from pynput.keyboard import Key, Controller
keyboard = Controller()

##Seltenheit    R   G   B
##Common        13  91  245
##Uncommon      14  181 229
##Rare          251 137 34
##Superrare     248 242 65
##Legendary     161 38  242
##Legendary2    122 250 67
##Shiny         255 155 202

##Kordinaten 392 860

##Start
print("Starting", end="")
for i in range(0, 5):
    print(".", end="")
time.sleep(1)
print("Go")


x = 1
while x < 10:
    keyboard.type(';p')
    keyboard.press(Key.enter)
    time.sleep(3)
if pyautogui.pixelMatchesColor(392, 860, (13, 91, 245)):
        keyboard.type('11')
        keyboard.press(Key.enter)
elif pyautogui.pixelMatchesColor(392, 860, (14, 181, 229)):
        keyboard.type('11')
        keyboard.press(Key.enter)
elif pyautogui.pixelMatchesColor(392, 860, (251, 137, 34)):
        keyboard.type('22')
        keyboard.press(Key.enter)
elif pyautogui.pixelMatchesColor(392, 860, (248, 242, 65)):
        keyboard.type('33')
        keyboard.press(Key.enter)
elif pyautogui.pixelMatchesColor(392, 860, (161, 38, 242)):
        keyboard.type('44')
        keyboard.press(Key.enter)
elif pyautogui.pixelMatchesColor(392, 860, (122, 250, 67)):
        keyboard.type('44')
        keyboard.press(Key.enter)
elif pyautogui.pixelMatchesColor(392, 860, (255, 155, 202)):
        keyboard.type('44')
        keyboard.press(Key.enter)
else:
        keyboard.type('11')
        keyboard.press(Key.enter)
        time.sleep(9)
einfachTobi
User
Beiträge: 512
Registriert: Mittwoch 13. November 2019, 08:38

Bist du sicher, dass die jeweiligen Pixel zum Zeitpunkt der Prüfung GENAU diese Farbe haben? Ich weiß nicht wie pyautogui da arbeitet, aber gerade bei "bewegten Bildern" (bzw.Schnappschüssen davon) weichen die Farben ja gerne leicht ab. In OpenCV gibt man üblicherweise einen Bereich an, in dem die Farbe liegen soll.

Weitere Anmerkungen:
- der Startblock erfüllt absolut keine Funktion und kann weg. Wozu so kompliziert eine einfache Ausgabe machen? Wozu das sleep?
- du solltest die Farbtupel gleich in eine passende Datenstruktur mit sprechenden Namen bringen. Dann tauchen in deinem Code nicht plötzlich "magische" Zahlen auf, sondern z. B. colors["red"].
- Ereignisse, welche die gleiche Handlung zur Folge haben, können auch in einem if geprüft werden (if foo or bar: ...).
OcolusNoun
User
Beiträge: 9
Registriert: Freitag 14. August 2020, 14:33

Ich habe den Farbwert mit Paint ermittelt. Da kann es bestimmt zu abweichungen kommen. Wie würde der Code den grob in OpenCV aussehen?

Der Startblock ist eine kleine Spielerei. Er gibt "Starting" aus und tippt bis zum "Go" jede Sekunde einen Punkt. Die Zeit hat man um in das Fenster zu wechseln in dem der Bot aktiv werden soll.
Ja so anschaulich ist mein Code noch nicht. Da es mein erster ist und ich keine Ahnung von den Basics habe wird das auch etwas dauern bis der schick ist befürchte ich.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn die Frage nicht passt, liegst du entweder von der Koordinate daneben, oder vom Farbton. Um das rauszufinden, musst du den von pyautogui ausgelesenen farbwert bestimmen, dafür hat das doch garantiert auch eine Funktion.
einfachTobi
User
Beiträge: 512
Registriert: Mittwoch 13. November 2019, 08:38

Was im Startblock passiert, das sehe ich ja. Es ist halt unnütz - zumindest solange dort nicht so was steht wie "Du hast 5 Sekunden Zeit ins andere Fenster zu wechseln.". Und auch dann ist keine Ausgabe nötig - die sieht man ja in der Regel nicht mehr.
Hier gibt es eine nette Anleitung zu genau dem Thema: https://www.pyimagesearch.com/2014/08/0 ... detection/. Allgemein ist PyImageSearch.com empfehlenswert, um in den Umgang mit OpenCV reinzuschnuppern. Letztlich wirst du dich aber mit OpenCV und Numpy befassen müssen, da opencv die Bilddaten in Numpy-Arrays organisiert.

Wenn du allerdings bei pyautogui bleibst, solltest du zunächst mal prüfen, welche Farbe du da überhaupt einfängst und ob das plausibel ist.
OcolusNoun
User
Beiträge: 9
Registriert: Freitag 14. August 2020, 14:33

Ja nur diese funktioniert leider nicht bei mir. Er gibt mir auch keine Fehlermeldung. Dann werd ich mich erstmal darauf fokussieren das zu lösen.
OcolusNoun
User
Beiträge: 9
Registriert: Freitag 14. August 2020, 14:33

Okay. Danke euch beiden. Ich meld mich dann wenn alles funktioniert :P
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@OcolusNoun: Anmerkungen zu dem Quelltext:

Eingerückt wird in Python per Konvention vier Leerzeichen pro Ebene.

Der Code funktioniert nicht weil der überhaupt nie zu den ganzen Farbvergleichen kommt. Denn die ``while x < 10:``-Schleife nie endet, denn `x` ändert sich in der Schleife überhaupt nicht. Sollte `x` einfach nur hochgezählt werden, also die Schleife 10× durchlaufen werden, dann nimmt man dafür eine ``for``-Schleife. Hast Du bei der Ausgabe der Punkte beim Warten vorher auch gemacht.

0 ist der Default-Startwert bei `range()`, das muss man nicht angeben.

Wenn man aus syntaktischen Gründen einen Namen braucht, den Namen selbst dann aber gar nicht verwendet, ist die Konvention `_` als Namen zu verwenden um deutlich zu machen, dass das Absicht ist, das dort ein unbenutzter Name im Programm steht.

Die ”magischen” Zahlen für Farben und Koordinaten würde man eher als Konstanten am Anfang des Programms definieren, statt die im Programmcode zu verteilen. Bei den Farben kann man da auch gleich die Farbe und die zugeordnete Benutzereingabe in eine Datenstruktur stecken und damit diese lange ``if``/``elif``-Kaskade ersetzen.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import time

import pyautogui
from pynput.keyboard import Controller, Key

PIXEL_COORDINATES = 329, 860
DEFAULT_TEXT = "11"
COLOR_TO_TEXT = {
    (13, 91, 245): "11",  # common
    (14, 181, 229): "11",  # uncommon
    (251, 137, 34): "22",  # rare
    (248, 242, 65): "33",  # super rare
    (161, 38, 242): "44",  # legendary
    (122, 250, 67): "44",  # legendary 2
    (255, 155, 202): "44",  # shiny
}


def main():
    print("Starting", end="")
    for _ in range(5):
        print(".", end="")
    time.sleep(1)
    print("Go")

    keyboard = Controller()

    for _ in range(10):
        keyboard.type(";p")
        keyboard.press(Key.enter)
        time.sleep(3)

    x, y = PIXEL_COORDINATES
    text = COLOR_TO_TEXT.get(pyautogui.pixel(x, y))
    if text is None:
        keyboard.type(DEFAULT_TEXT)
        keyboard.press(Key.enter)
        time.sleep(9)
    else:
        keyboard.type(text)
        keyboard.press(Key.enter)


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
OcolusNoun
User
Beiträge: 9
Registriert: Freitag 14. August 2020, 14:33

Vielen dank für die ausführliche Antwort. Ich werde das morgen mal testen :)
Antworten