Reconhecimento de imagens

Artigos, manuais, conselhos e dicas sobre programação em AutoHotkey

Moderator: Gio

User avatar
Gio
Posts: 705
Joined: 30 Sep 2013, 10:54
Location: Brazil

Reconhecimento de imagens

30 Nov 2019, 11:31

... Em construção !! ...

Bom dia :)

Vi que vários usuários têm interesse neste tema, e decidi fazer este tutorial explicando em pormenores como fazer.

O AutoHotkey possui algumas funcionalidades para efetuar reconhecimento de imagens, como os comandos ImageSearch e PixelSearch. Essa ferramentas podem ser bastante úteis no campo da automação, pois alguns controles, programas e até mesmo jogos não oferecem suporte para automação via códigos. Por este motivo, se desejarmos implementar automação nestes casos, seremos forçados a usar a própria interface visual que o usuário opera para simular uma operação automatizada no programa.


Vamos aprender a fazer? :thumbup:


Índice de conteúdos deste tutorial:
1. O que é reconhecimento de imagens
2. ImageSearch, um comando mais prático
3. PixelSearch, um comando mais poderoso


1. O que é reconhecimento de imagens


Imagine que você quer automatizar um programa. Para o correto funcionamento do programa, o usuário precisa apertar um botão. Quando ele clica no botão, o programa faz algo útil e essa operação que você quer automatizar.

Mas após tentar efetuar o clique no botão através dos comandos control (controlclick, controlfocus, controlsend, etc), você percebe que o eles não vão funcionar porque o botão em questão não foi implementado da forma usual das DLLs do Windows: ele é apenas uma imagem na tela e o programa apenas usa um clique naquelas coordenadas para acionar a rotina.

Para piorar, imagine que o botão nem sempre está no mesmo lugar, pois o script deverá funcionar em todo e qualquer computador, e a tela pode estar maximizada, minimizada, puxada para o lado, em outro monitor, etc, etc, etc... Assim não adianta tentar escrever as coordenadas direto no script (ou seja, sem hardcode).

Então como você faria para encontrar as coordenadas certas e clicar nesse "botão"?

Uma maneira relativamente simples de fazê-lo é atraves do comandos de reconhecimento de imagem (ImageSearch e PixelSearch).

Vamos aprender a utilizá-los? :thumbup:



2. ImageSearch, um comando mais prático

O comando ImageSearch é um comandos relativamente simples que faz o seguinte: através de um arquivo de imagem que você possua no seu computador, ele vai buscar a mesma imagem na tela do computador, e se encontrar, vai avisar através da variável embutida ErrorLevel, além de colocar as coordenadas onde a imagem foi localizada em duas variáveis: uma com a posição horizontal em pixels da esquerda para a direita da tela (Coordenada X) e a outra com a posição vertical em pixels da parte de cima para baixo da tela (Coordenada Y). Essas são as mesmas coordenadas que outros comandos (como o MouseClick e o MouseMove) utilizam.

Com essas informações podemos então definir duas coisas: SE a imagem foi localizada na tela, e ONDE ela está na tela. Naturalmente, isto é tudo que precisamos para efetuar uma ação tal como clicar naquela imagem através do comando MouseClick, por exemplo.

Então o que vamos fazer para implementar essa rotina? É bem simples, e vamos fazer passo a passo!

:arrow: Imagine que queira clicar no botão "Fórum" localizado na página inicial do AutoHotkey (https://www.autohotkey.com/).

1. Primeiro, nós vamos tirar um print da tela da página do AutoHotkey

forum.png
forum.png (449.01 KiB) Viewed 229 times

2. Depois, nós vamos abrir a imagem do print no paint, e recortar a imagem do botão. Dai, é só colar essa imagem sozinha em uma nova tela do paint (diminua bastante o tamanho da imagem de fundo antes de colar para que a imagem final não fique com bordas brancas).

botao isolado.png
botao isolado.png (28.95 KiB) Viewed 229 times

3. Depois, salvamos a imagem isolada do botao em um arquivo chamado "botao_a_apertar.png" dentro da pasta do nosso script.

imagem na pasta.png
imagem na pasta.png (42.53 KiB) Viewed 229 times

4. Por fim, rodamos o código abaixo, abrimos novamente a página do AutoHotkey e apertamos o F2 para ativar a rotina.

Code: Select all

F2::
CoordMode, Pixel, Screen ; Primeiro configuramos as coordenadas XY para serem relativas à tela inteira (e não somente à janela ativa).
ImageSearch, PosX, PosY, 0, 0, %A_ScreenWidth%, %A_ScreenHeight%, %A_ScriptDir%/botao_a_apertar.png ; Depois efetuamos o comando.
If (ErrorLevel = 0) ; Se depois de rodar o comando não houverem erros, então a imagem foi corretamente localizada !
{
	X_Um_Pouco_Mais_A_Esquerda := PosX + 20 ; Como o comando retorna a posição superior-esquerda da imagem, vamos clicar um pouco mais à esquerda (pois alguns botões tem bordas que não são clicáveis)
	Y_Um_Pouco_Mais_Abaixo := PosY + 20 ; Como o comanod retorna a posição superior-esquerda da imagem, vamos clicar um pouco mais abaixo (novamente: isto é para evitar bordas!)
	MouseMove, %X_Um_Pouco_Mais_A_Esquerda%, %Y_Um_Pouco_Mais_Abaixo% ; Movemos o mouse para a posição calculada.
}
else ; Mas se deupos de rodar o comando houverem erros...
{
	msgbox, 0x10, Erro, Não foi possível localizar a imagem ! ; informamos ao usuário
}
Return
Se tudo der certo, o script vai mover o mouse para o botão "fórum" sempre que apertarmos F2 na página do AutoHotkey. Experimente mover o mouse em várias direções e depois clicar o F2.

:arrow: O script está localizando a posição do botão através do comando ImageSearch e depois movendo o mouse para a posição localizada (com 10 pixels a mais para evitar bordas). Se quiséssemos, poderíamos também configurar um clique nas coordenadas desejadas, mas acredito que isso você já saiba fazer.

:arrow: DICA: note que apesar de estarmos usando a imagem do botão inteira no exemplo, podemos recortar apenas um pedaço do botão para usar como imagem a ser buscada no comando. Essa estratégia pode melhorar as chances de uma imagem ser localizada (caso a imagem esteja parcialmente escondida, por exemplo).

:arrow: O comando ImageSearch possui ainda algumas outras opções que podem ajudar na hora de localizar uma imagem. Uma delas é aceitar uma variação nas tonalidades da imagem que você determina o grau. Assim, se os pixels da imagem forem um pouco mais escuros ou um pouco mais claros, ou se a cor variar um pouquinho, ainda será possível encontrar a imagem. A variação pode ser indicada no parâmetro de caminho do arquivo, escrevedo asterisco seguido do grau de variação desejado antes de escrever o caminho do arquivo (separado por um espaço simples). Exemplo: *10 c:/imagens/exemplo.png. Outra opção que pode ser bastante útil é determinar uma cor para servir como background. Dessa forma, se torna possível utilizar uma imagem que contenha fundo branco para localizar a imagem ainda que o fundo mude para verde (basta determinar que o branco será uma cor "transparente"). Nesse caso, você pode escrever um asterisco, seguido da palavra "Trans" e depois seguido da cor escolhida antes do caminho do arquivo. (Exemplos: *TransWhite c:/imagens/exemplo.png ou *Trans0x9DAF99 c:/imagens/exemplo.png (Falaremos de códigos de cores no item seguinte deste tutorial).

3. PixelSearch, um comando mais poderoso

Conforme vimos na parte 2 deste tutorial, podemos utilizar o comando ImageSearch para buscar facilmente imagens na tela quando elas estiverem inteiramente visíveis (ou parcialmente desde que usemos um pedaço que estiver visível) e desde que elas não tenham muita variação (apenas um pouco na tonalidade).

Mas o que fazer quando a imagem em questão pode variar de alguma forma?

Imagine que você está tentar encontrar a posição de um boneco dentro de um jogo. A imagem do boneco está sempre visível na tela, mas ocorre que como se trata de uma animação, ela nem sempre será a mesma. Estudando um pouco o funcionamento de uma animação, percebemos que ela é feita basicamente de duas formas: ou colocando várias imagens pré-prontas (os sprites 2D) ou gerando na hora as várias imagens 2D a partir de objeto 3D (através da renderização), e depois passando em qualquer caso as imagens uma a uma sequencialmente e rapidamente (para criar o efeito da animação). Em ambos os casos, as imagens de fato variam e fazem isso rapidamente. Assim o comando ImageSearch se tornará inútil para localizar o boneco, pois não há como garantir a sincronia entre as chamadas ao comando e a imagem em exibição naquele exato instante (ainda que chamassemos o comando uma vez para cada sprite, a velocidade de mudança é tal que é mais provável que em nenhum caso coincidiria - pois o comando não é processado tão rápidamente assim).

Neste caso, como faremos então para criar um script que encontre uma imagem dentro de uma animção?

:arrow: Simples! Vamos usar o comando PixelSearch, que encontra apenas 1 pixel de determinada cor na tela.

Parece estranho que isso possa resolver o nosso problema? Saiba que a possibilidade de buscar um único pixel é mais flexível do que buscar uma imagem inteira, e que ela permite que coloquemos mais inteligência em nossas rotinas.

Vemos ver como isso funciona?

3.1 As cores em uma imagem

Os monitores de hoje em dia são capazes de gerar imagens com milhões de cores diferentes. Isso ocorre porque cada pixel da tela é iluminado em vários graus por cada uma das três cores básicas: vermelho, verde e azul.

Essas três cores formam a base do sistema aditivo de cores, e isso significa que a partir delas, podemos formar quaisquer outras cores. Quer um exemplo? Se você iluminar um pixel com um vermelho bem e com um azul bem forte, e mantiver o verde dele bem fraco, você terá uma cor violeta forte. Assim, perceba que qualquer uma das milhões de cores possível em um monitor é basicamente um resultado da força de iluminação variável entre as três cores básicas (incluindo até mesmo o preto e o branco).

No computador, podemos então formar qualquer cor indicando os valores de iluminação de cada cor no mesmo pixel.

!! --- Em contrução --- !!

Return to “Tutoriais”

Who is online

Users browsing this forum: No registered users and 4 guests