Buscar

Guias

OCR Python com Tesseract para bot de jogo Android

Dê a um bot de jogo Android o OCR do Tesseract com read_text: escolha uma região no Asset Lab, ajuste psm e conversão de cor, e leia contadores e timers.

  • Windows
  • Mac
  • Emulador
  • Dispositivo na nuvem
  • Celular
  • Studio
  • SDK Python
Intermediário Atualizado em 7 min de leitura
Nesta página
  1. Antes de começar
  2. Como o OCR Python com Tesseract funciona em um bot de jogo Android
  3. Escolha uma região de OCR no Asset Lab
  4. Escolha o modelo
  5. Escolha um modo de segmentação de página
  6. Corrija texto claro sobre fundo escuro
  7. Defina um tempo limite
  8. Extraia números do texto
  9. Use a confiança
  10. Reaproveite uma captura de tela
  11. Ler texto em um emulador Android com Python: um exemplo completo
  12. Solução de problemas
  13. O OCR retorna uma string vazia
  14. Dígitos lidos errado
  15. OCR lento

O template matching diz a um bot de jogo Android se um botão está na tela. O OCR do Tesseract, chamado do Python, diz o que um contador mostra: energia 8 de 50, um timer em 00:42, um número de nível. Este guia leva mas.read_text de uma região desenhada no Asset Lab até uma macro que para quando a energia cai abaixo de um limite. Ele é para quem escreve macros do Macro Automation Studio (MAS) em Python em um emulador, em um dispositivo na nuvem ou em um celular.

Antes de começar

  • Um projeto Baseado em código está aberto no Code Editor e um dispositivo está selecionado. Veja Primeiros passos.
  • O app ou jogo mostra o texto que você quer ler, na resolução que você vai manter.
  • Você leu o guia de reconhecimento de imagem ou sabe o que é uma Region.

Como o OCR Python com Tesseract funciona em um bot de jogo Android

read_text envia uma captura de tela, ou a parte dela dentro de uma região, ao Tesseract OCR dentro do app. Ele retorna o que o motor leu.

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

O resultado é um TextRecognitionResult com três campos: text (a string), confidence (0.0 a 1.0) e region (onde ele olhou). Ler a tela inteira funciona, mas uma região justa é mais rápida e muito mais precisa, então o primeiro passo é sempre a região.

Escolha uma região de OCR no Asset Lab

  1. Leve o dispositivo até a tela com o contador.
  2. No Code Editor, abra o painel Assets e clique em Abrir o Asset Helper. O Asset Lab abre com a tela ao vivo.
  3. Desenhe uma caixa em volta do texto. Inclua uma pequena margem, mas nenhum ícone, borda ou número vizinho.
  4. Rode o teste de OCR ao vivo. Ajuste a caixa até o texto voltar limpo; o teste usa o mesmo motor que o seu script.
  5. Copie as quatro coordenadas para uma 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)

Imprima com repr enquanto ajusta: ele mostra espaços e quebras de linha perdidos que o print esconde. As regiões são coordenadas em pixels na resolução da captura, então mantenha todo dispositivo nessa resolução. Veja Asset Lab.

Escolha o modelo

model seleciona os dados do Tesseract. "eng_best" é o padrão e o mais preciso; "eng_fast" troca precisão por velocidade em texto limpo; "eng" é o conjunto padrão de inglês. Comece pelo padrão e só troque quando um loop ler dezenas de vezes por minuto.

Escolha um modo de segmentação de página

psm diz ao Tesseract que forma de texto esperar. O modo errado é a causa mais comum de resultados vazios ou embaralhados.

psmEsperaUse para
7Uma única linha de texto (padrão)Contadores, timers, rótulos de uma linha
8Uma única palavraUm número sozinho ou um selo curto
6Um bloco uniforme de textoUm parágrafo em um diálogo
11Texto esparso em qualquer lugar, sem ordemUma tela inteira, uma 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)

Os valores vão de 0 a 13, mas esses quatro cobrem quase toda macro. Quando uma região de uma linha não retorna nada, tente 8 primeiro, depois 6.

Corrija texto claro sobre fundo escuro

O Tesseract espera texto escuro sobre fundo claro. Os contadores de jogos costumam ser o oposto, dígitos brancos sobre uma barra escura, muitas vezes com um contorno colorido. color_conversion pré-processa o recorte antes do OCR.

python
from mas import ColorConversion

energy = mas.read_text(
    region=ENERGY,
    psm=7,
    color_conversion=ColorConversion.BLACK_WHITE,
)
  • ColorConversion.NONE (padrão) envia os pixels como estão.
  • ColorConversion.BLACK_WHITE converte para escala de cinza e aplica um limiar automático, dando preto e branco puros. É a melhor primeira tentativa para texto de alto contraste sobre fundos ruidosos ou coloridos.
  • ColorConversion.BGR_TO_GRAY ou RGB_TO_GRAY dá escala de cinza simples, o que ajuda quando o limiar de BLACK_WHITE come traços finos.

Teste cada opção no Asset Lab na tela real. Não existe um membro GRAYSCALE; use um dos nomes acima.

Defina um tempo limite

timeout_ms tem 30000 como padrão. Uma região justa com psm=7 retorna bem abaixo de um segundo; uma leitura de tela inteira com psm=11 em uma tela cheia demora mais. Reduza o tempo limite em um loop que precisa continuar responsivo, e envolva a chamada para que uma leitura lenta não encerre a execução.

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

Extraia números do texto

result.text é uma string, às vezes com espaços, vírgulas, uma barra ou uma letra perdida. Interprete-a com uma expressão regular e trate “nenhum número” como um 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")1250; current_and_max("8/50")(8, 50). As trocas de O e l corrigem as duas leituras erradas de dígito mais comuns; aplique-as só a regiões que contêm apenas dígitos.

Use a confiança

confidence vai de 0.0 a 1.0 sobre as palavras que o Tesseract encontrou. Um contador limpo lê a 0.9 ou mais. Quando ela cair, leia de novo antes de agir sobre o valor, e registre os dois para ver o padrão depois.

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

Reaproveite uma captura de tela

Todo read_text captura um quadro novo, a menos que você passe um. Quando um loop lê várias regiões de uma vez, tire uma captura e passe-a a cada chamada; os valores então pertencem ao mesmo instante.

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

Ler texto em um emulador Android com Python: um exemplo completo

O script toca em um botão até o contador de energia cair abaixo de um limite ou o limite de tempo passar. Troque a região, o ID da imagem e o limite pelos seus.

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

Ler antes de cada toque mantém a macro honesta: ela nunca gasta energia que não consegue ver. O contador unreadable transforma uma região quebrada em uma execução com falha, que um webhook em macro.failed pode informar. Veja Loops e agendamento. Se preferir descrever a tarefa, o MAS Agent mede a região e escreve esse código para você.

Solução de problemas

O OCR retorna uma string vazia

A região não pega o texto, o modo está errado, ou o texto é claro sobre escuro. Confira a região no Asset Lab, troque psm para 8 para um único número ou 6 para um bloco, e adicione color_conversion=ColorConversion.BLACK_WHITE. Texto muito pequeno também é lido como nada. Se os dígitos têm só alguns pixels de altura, aumente a resolução do emulador nas configurações de tela e capture todas as regiões de novo.

Dígitos lidos errado

Zero lido como a letra O, um como l, oito como B, ou uma vírgula que some. Primeiro aperte a região para nenhum ícone tocar nos dígitos. Depois tente BLACK_WHITE e, se os traços quebrarem, BGR_TO_GRAY em vez disso. Por fim, normalize no código: troque O por 0 e l por 1 em regiões só de dígitos, remova as vírgulas e rejeite valores que saltam demais entre leituras.

OCR lento

Leituras de tela inteira com psm=11 e eng_best são o caso lento. Leia uma região, não a tela; use psm=7 ou 8; e passe uma única screenshot a várias chamadas. model="eng_fast" ajuda em texto limpo. Se uma leitura ainda leva segundos, a região provavelmente é grande; um contador precisa de uma caixa de no máximo algumas centenas de pixels de largura.

Nenhuma ferramenta de automação é 100% livre de riscos, por isso automatize com responsabilidade e a seu próprio critério.

Próximos passos

Páginas relacionadas

Esta página foi útil?

Dúvidas? Pergunte no Discord