Buscar

Guías

OCR Tesseract en Python para un bot de juego Android

OCR Tesseract en Python para tu bot de juego Android con read_text en MAS: elige una región en Asset Lab, ajusta psm y el color, y lee contadores.

  • Windows
  • Mac
  • Emulador
  • Dispositivo en la nube
  • Teléfono
  • Studio
  • SDK de Python
Intermedio Actualizado 7 min de lectura
En esta página
  1. Antes de empezar
  2. Cómo funciona el OCR Tesseract en Python dentro de un bot de juego
  3. Elegir una región OCR en Asset Lab
  4. Elegir el modelo
  5. Elegir un modo de segmentación de página
  6. Arreglar texto claro sobre fondo oscuro
  7. Fijar un tiempo límite
  8. Extraer números del texto
  9. Usar la confianza
  10. Reutilizar una captura
  11. Leer texto en un emulador Android con Python: ejemplo completo
  12. Solución de problemas
  13. El OCR devuelve una cadena vacía
  14. Dígitos mal leídos
  15. OCR lento

La coincidencia de plantillas le dice a un bot de juego Android si un botón está en pantalla. El OCR Tesseract en Python le dice qué marca un contador: energía 8 de 50, un temporizador en 00:42, un número de nivel. Esta guía lleva mas.read_text desde una región dibujada en Asset Lab hasta una macro que se detiene cuando la energía baja de un límite. Está pensada para quien escribe macros de Macro Automation Studio (MAS) en Python en un emulador, un dispositivo en la nube o un móvil.

Antes de empezar

  • Un proyecto basado en código está abierto en el Code Editor y hay un dispositivo seleccionado. Consulta Primeros pasos.
  • La app o el juego muestra el texto que quieres leer, a la resolución que vas a mantener.
  • Has leído la guía de reconocimiento de imagen o sabes qué es una Region.

Cómo funciona el OCR Tesseract en Python dentro de un bot de juego

read_text envía una captura, o la parte de ella dentro de una región, al Tesseract OCR que va dentro de la app. Devuelve lo que leyó el motor.

python
def read_text(
    region: Region | None = None,
    screenshot: Screenshot | None = None,
    model: str = "eng_best",
    psm: int = 7,
    color_conversion: ColorConversion = ColorConversion.NONE,
    timeout_ms: int = 30000,
) -> TextRecognitionResult

El resultado es un TextRecognitionResult con tres campos: text (la cadena), confidence (de 0.0 a 1.0) y region (dónde miró). Leer toda la pantalla funciona, pero una región ajustada es más rápida y mucho más precisa, así que el primer paso es siempre la región.

Elegir una región OCR en Asset Lab

  1. Lleva el dispositivo a la pantalla con el contador.
  2. En el Code Editor, abre el panel Recursos y haz clic en Abrir Asset Helper. Asset Lab se abre con la pantalla en directo.
  3. Dibuja un recuadro alrededor del texto. Incluye un poco de margen, pero ningún icono, borde ni número vecino.
  4. Ejecuta la prueba de OCR en directo. Ajusta el recuadro hasta que el texto salga limpio; la prueba usa el mismo motor que tu script.
  5. Copia las cuatro coordenadas a una Region(x1, y1, x2, y2).
python
import mas
from mas import Region

ENERGY = Region(x1=380, y1=20, x2=520, y2=60)

result = mas.read_text(region=ENERGY)
print(repr(result.text), result.confidence)

Imprime con repr mientras ajustas: muestra los espacios y saltos de línea sueltos que print esconde. Las regiones son coordenadas en píxeles a la resolución de captura, así que mantén todos los dispositivos en esa resolución. Consulta Asset Lab.

Elegir el modelo

model selecciona los datos de Tesseract. "eng_best" es el predeterminado y el más preciso; "eng_fast" cambia precisión por velocidad en texto limpio; "eng" es el conjunto estándar en inglés. Empieza con el predeterminado y cambia solo cuando un bucle lee decenas de veces por minuto.

Elegir un modo de segmentación de página

psm le dice a Tesseract qué forma de texto esperar. El modo equivocado es la causa más común de resultados vacíos o ilegibles.

psmEsperaÚsalo para
7Una sola línea de texto (predeterminado)Contadores, temporizadores, etiquetas de una línea
8Una sola palabraUn número suelto o una insignia corta
6Un bloque uniforme de textoUn párrafo en un diálogo
11Texto disperso en cualquier sitio, sin ordenUna pantalla entera, una lista de resultados
python
level = mas.read_text(region=Region(x1=20, y1=20, x2=90, y2=60), psm=8)
dialog = mas.read_text(region=Region(x1=60, y1=300, x2=480, y2=600), psm=6)

Los valores van de 0 a 13, pero estos cuatro cubren casi todas las macros. Cuando una región de una sola línea no devuelve nada, prueba primero 8 y luego 6.

Arreglar texto claro sobre fondo oscuro

Tesseract espera texto oscuro sobre fondo claro. Los contadores de los juegos suelen ser lo contrario, dígitos blancos sobre una barra oscura, muchas veces con un contorno de color. color_conversion preprocesa el recorte antes del OCR.

python
from mas import ColorConversion

energy = mas.read_text(
    region=ENERGY,
    psm=7,
    color_conversion=ColorConversion.BLACK_WHITE,
)
  • ColorConversion.NONE (predeterminado) envía los píxeles tal cual.
  • ColorConversion.BLACK_WHITE convierte a escala de grises y aplica un umbral automático, dando blanco y negro puros. Es la mejor primera opción para texto de alto contraste sobre fondos con ruido o de color.
  • ColorConversion.BGR_TO_GRAY o RGB_TO_GRAY dan escala de grises simple, que ayuda cuando el umbral de BLACK_WHITE se come los trazos finos.

Prueba cada opción en Asset Lab sobre la pantalla real. No existe un miembro GRAYSCALE; usa uno de los nombres de arriba.

Fijar un tiempo límite

timeout_ms es 30000 por defecto. Una región ajustada con psm=7 responde en mucho menos de un segundo; una lectura de pantalla completa con psm=11 sobre una pantalla cargada tarda más. Baja el tiempo límite en un bucle que deba seguir respondiendo y envuelve la llamada para que una lectura lenta no termine la ejecución.

python
try:
    result = mas.read_text(region=ENERGY, timeout_ms=5000)
except mas.RPCError as e:
    mas.log(f"OCR failed: {e}", level="warning")
    result = None

Extraer números del texto

result.text es una cadena, a veces con espacios, comas, una barra o una letra suelta. Analízala con una expresión regular y trata “sin número” como un resultado real.

python
import re

def first_int(text: str) -> int | None:
    cleaned = text.replace(",", "").replace("O", "0").replace("l", "1")
    m = re.search(r"\d+", cleaned)
    return int(m.group()) if m else None

def current_and_max(text: str) -> tuple[int | None, int | None]:
    m = re.search(r"(\d+)\s*/\s*(\d+)", text.replace(",", ""))
    return (int(m.group(1)), int(m.group(2))) if m else (None, None)

first_int("Energy 1,250") da 1250; current_and_max("8/50") da (8, 50). Los cambios de O y l arreglan las dos confusiones de dígitos más comunes; aplícalos solo a regiones que no contengan más que dígitos.

Usar la confianza

confidence va de 0.0 a 1.0 sobre las palabras que Tesseract encontró. Un contador limpio se lee a 0.9 o más. Cuando baja, vuelve a leer antes de actuar sobre el valor, y registra ambos para ver el patrón más tarde.

python
for attempt in range(3):
    result = mas.read_text(region=ENERGY, psm=7)
    value = first_int(result.text)
    if value is not None and result.confidence >= 0.8:
        break
    mas.log(f"Low confidence {result.confidence:.2f} for {result.text!r}", level="warning")

Reutilizar una captura

Cada read_text captura un fotograma nuevo salvo que le pases uno. Cuando un bucle lee varias regiones a la vez, haz una captura y pásala a cada llamada; los valores pertenecen entonces al mismo instante.

python
shot = mas.take_screenshot()
energy = mas.read_text(region=ENERGY, screenshot=shot)
gold = mas.read_text(region=GOLD, screenshot=shot)

Leer texto en un emulador Android con Python: ejemplo completo

El script toca un botón hasta que el contador de energía baja de un límite o se agota un presupuesto de tiempo. Sustituye la región, el ID de imagen y el límite por los tuyos.

python
import random
import re
import sys
import time

import mas
from mas import ColorConversion, Region

images = mas.images({"attack_button": 101})

ENERGY = Region(x1=380, y1=20, x2=520, y2=60)
MIN_ENERGY = 10
TIME_BUDGET_S = 15 * 60


def read_energy() -> int | None:
    for _ in range(3):
        result = mas.read_text(
            region=ENERGY,
            psm=7,
            color_conversion=ColorConversion.BLACK_WHITE,
            timeout_ms=5000,
        )
        m = re.search(r"\d+", result.text.replace(",", "").replace("O", "0"))
        if m and result.confidence >= 0.7:
            return int(m.group())
        mas.log(f"Unclear energy {result.text!r} ({result.confidence:.2f})", level="warning")
        time.sleep(1)
    return None


def main():
    started = time.monotonic()
    unreadable = 0

    while time.monotonic() - started < TIME_BUDGET_S:
        energy = read_energy()
        if energy is None:
            unreadable += 1
            if unreadable >= 5:
                mas.log("Energy unreadable five times, stopping", level="error")
                sys.exit(2)
            continue
        unreadable = 0
        if energy < MIN_ENERGY:
            mas.log(f"Energy {energy} is below {MIN_ENERGY}, done")
            break

        button = mas.find_object_retry(images.attack_button, total_tries=3, time_sleep=2.0)
        if button is None:
            mas.log("Attack button not found", level="warning")
            continue
        mas.click(button.x, button.y, delay_ms=1000)
        time.sleep(random.uniform(0.8, 2.0))

    mas.log("Finished")


if __name__ == "__main__":
    main()

Leer antes de cada toque mantiene la macro honesta: nunca gasta energía que no puede ver. El contador unreadable convierte una región rota en una ejecución fallida, que un webhook en macro.failed puede notificar. Consulta Bucles y programación. Si prefieres describir la tarea, MAS Agent mide la región y escribe este código por ti.

Solución de problemas

El OCR devuelve una cadena vacía

La región no abarca el texto, el modo es incorrecto o el texto es claro sobre oscuro. Revisa la región en Asset Lab, cambia psm a 8 para un solo número o a 6 para un bloque, y añade color_conversion=ColorConversion.BLACK_WHITE. El texto muy pequeño también se lee como nada. Si los dígitos miden solo unos píxeles de alto, sube la resolución del emulador en sus ajustes de pantalla y vuelve a capturar todas las regiones.

Dígitos mal leídos

El cero se lee como la letra O, el uno como l, el ocho como B, o desaparece una coma. Primero ajusta la región para que ningún icono toque los dígitos. Luego prueba BLACK_WHITE y, si los trazos se rompen, BGR_TO_GRAY en su lugar. Por último, normaliza en el código: sustituye O por 0 y l por 1 en regiones de solo dígitos, quita las comas y rechaza valores que salten de forma disparatada entre lecturas.

OCR lento

Las lecturas de pantalla completa con psm=11 y eng_best son el caso lento. Lee una región, no la pantalla; usa psm=7 u 8; y pasa una sola screenshot a varias llamadas. model="eng_fast" ayuda con texto limpio. Si una lectura sigue tardando segundos, la región probablemente es grande; un contador necesita un recuadro de como mucho unos cientos de píxeles de ancho.

Ninguna herramienta de automatización está libre de riesgos al 100 %, así que automatiza con responsabilidad y bajo tu propio criterio.

Siguientes pasos

Páginas relacionadas

¿Te ha servido esta página?

¿Dudas? Pregunta en Discord