PythonJogaPong — Parte 1 Capturando a tela e extraindo informações

Lucas Oliveira
pilotorobo
Published in
3 min readOct 15, 2017

Esse post faz parte de uma série onde explico o projeto PythonJogaPong, que usa redes neurais para jogar o jogo clássico de atari Pong. Veja também as outras partes: Parte 2 Parte 3 Parte 4

Para o projeto iremos usar uma implementação de pong no browser, acessada por https://pong-2.com, mas obviamente você pode usar qualquer implementação de pong que quiser, desde que faça as adaptações necessárias no projeto.

O arquivo completo está disponível em: https://github.com/pilotorobo/pongplay/blob/master/screen_features.py

from grabscreen import grab_screen                       
import cv2
import numpy as np

Primeiro importamos 3 coisas:

A função get_screen retorna uma região da tela da tela em escalas de cinza. Primeiro a função grab_screen retorna a região definida pelos pontos x1=200, y1=200, x2=720+200 e y2=405+200. Colocamos os valores finais em forma de soma (720+200) devido a facilidade de modificar o tamanho da região capturada e seu offset, no caso a região de tamanho 720x405 com offset de 200 na horizontal e 200 na vertical será retornada. A função cvtColor converte as cores da imagem capturada para escalas de cinza.

Essa função recebe a imagem da tela do jogo em escalas de cinza e retorna 6 valores dentro de um vetor: A posição horizontal e vertical da bola, a posição horizontal e vertical da primeira barra e a posição horizontal e vertical da segunda barra (que controlamos). Ela inicia chamando a função connectedComponentsWithStats para capturar grupos de pixels conectados na imagem. Então usamos algumas heurísticas entre as linhas 8 e 20 para determinar a localização da bola do jogo e das barras dos jogadores:

  • A bola do jogo costuma ser um quadrado perfeito, logo seu comprimento dividido pela sua altura deve ser aproximadamente 1. Como não possui furos ou buracos, a área ocupada pela figura (número de pixels ‘ativos’) é igual a área do quadrado que delimita a figura, logo a área dela deve ser igual ao comprimento x altura.
  • Como as barras são um retângulos, a idéia é semelhante, a única diferença que com experimentos verificamos que a razão da altura pelo comprimento é aproximadamente 4.6.

Com isso em mão, calculamos para todos os elementos valores baseados nessas heurísticas, que tendem a ser 0 em seu valor absoluto caso seja a bola do jogo ou as barras. Então pegamos os elementos com esses valores mais próximos de 0 e escolhemos eles como os elementos do jogo. É um método relativamente frágil facilmente “enganavel”, mas como a imagem do jogo é bem regular e praticamente não existe ruído, esse método é suficiente.

Aqui combinamos as funções get_screen e get_object locations para mostrar a localização dos objetos na tela com círculos cinzas para fins de debug.

Por fim, ao executar o arquivo, capturamos a tela e as informações dos objetos do jogo; Em seguida fazemos uma stream do conteúdo da imagem capturada em uma tela auxiliar até que o programa seja fechado ou a tecla ‘q’ for pressionada.

Siga o blog e fique ligado para os próximos posts sobre como jogar python com pong! Veja também as outras partes: Parte 2 Parte 3 Parte 4

Qualquer dúvida ou sugestão poste nos comentários!

Se gostou, bata algumas palmas 👏 para nós ! e ajude outros encontrar este artigo!

--

--

Lucas Oliveira
pilotorobo

Working at the intersection of artificial intelligence and education.