Dúvida: Iterando por múltiplos diretórios até encontrar imagem correspondente

250 views
Skip to first unread message

Alexandre Rosas

unread,
Aug 22, 2022, 9:17:05 AM8/22/22
to Python Brasil
Olá, boa noite a todos! Apreciaria uma ajudinha:

Dúvida:
- Como iterar por múltiplos diretórios até encontrar alguma imagem semelhante a que está aparecendo na tela, e só então parar a busca?

Obs: Criei este código executar esta tarefa (envio anexo: exemplo Mínimo, Completo e Verificável) e aparentemente era pra funcionar (pois parece que está tudo ok), mas dá este erro dizendo: "Falha ao ler imagem1.png porque o arquivo está faltando, tem permissões impróprias, ou é um arquivo com formato inválido ou não suportado." 


Segue exemplo Mínimo, Completo e Verificável do código:

import os
import pyautogui

pasta1 = "C:/Pasta1/"
pasta2 = "C:/Pasta2/"

def visualizar(imagens_pasta1_pasta2):
    for img in imagens_pasta1_pasta2:
        if pyautogui.locateOnScreen(img, confidence=0.6) is not None:
            print(f"Tô vendo: {img}")

parametros = [
    (os.listdir(pasta1)),
    (os.listdir(pasta2))
]

if any(visualizar(params) for params in parametros):
    break


Sendo que:
1. Os arquivos/ imagens estão nas pastas informadas
2. Já tentei salvar em .jpg e deu o mesmo erro
3. As imagens não estão corrompidas (Já até salvei novas versões e deu o mesmo erro)

Desde já agradeço pela atenção.

Marcelo Valle

unread,
Aug 22, 2022, 9:44:50 AM8/22/22
to python...@googlegroups.com
Olha, não executei seu código, mas qual a intenção da lista de tuplas ao invés de uma lista simples? 
Ao invés de 
```
if any(visualizar(params) for params in parametros):
```

Voce nao quis dizer 

```
if any(visualizar(*params) for params in parametros):
```

eu te recomendo imprimir na tela o path completo do arquivo que está tentando abrir para debugar o que está acontecendo


--
--
------------------------------------
Grupo Python-Brasil
https://wiki.python.org.br/AntesDePerguntar
 
<*> Para visitar o site do grupo na web, acesse:
http://groups.google.com/group/python-brasil
 
<*> Para sair deste grupo, envie um e-mail para:
python-brasi...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "Python Brasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para python-brasi...@googlegroups.com.
Para ver essa discussão na Web, acesse https://groups.google.com/d/msgid/python-brasil/cf9b8249-408d-4ece-8af2-bba2796d19acn%40googlegroups.com.

Alexandre Rosas

unread,
Aug 22, 2022, 3:48:45 PM8/22/22
to Python Brasil
Olá, amigo. Agradeço por seu feedback!
De forma resumida, é isso que estou querendo fazer:
  1. Dentro da pasta principal do projeto, eu criei outras 2 pastas e coloquei imagens diferentes dentro de cada uma.
  2. Era pra sair do loop, ao ver qualquer uma destas imagens.

Minha intenção é fazer ele percorrer estes 2 diretórios, buscando por alguma imagem semelhante a que ele estará vendo na tela.
E se encontrar, avisa que encontrou e sai do loop.


Aqui está o código 'retificado' e 'comentado' (coloquei *args em params, assim como você sugeriu) e ainda assim dá erro:

# Módulos
import os
import pyautogui

# Subpastas com as imagens de referência
# Coloquei os.listdir pra que ele entenda que eu quero tudo o que for listado nestes 2 diretórios
grupo1 = os.listdir("C:/Projeto1/Pasta1/")
grupo2 = os.listdir("C:/Projeto1/Pasta2/")

# Criei esta 'def' com 2 variáveis: imagens (que receberá as variáveis 'grupo1' e 'grupo2')
# e texto (apenas para facilitar a identificação)

def visualizar(imagens, texto):
    for img in imagens:

        if pyautogui.locateOnScreen(img, confidence=0.6) is not None:
            print(f"Tô vendo a imagem: {img}, da {texto}, nº {item}")
            return True
    return False

# Aqui eu declarei o conteúdo das varíaveis contidas na 'def' acima
parametros = [
(grupo1, 'Pasta 1'),
(grupo2, 'Pasta 2')
]

# E por fim, criei um loop while para 'se ver qualquer imagem, das 2 pastas que declarei em parametros', encerrar o loop.
while True:

    if any(visualizar(*params) for params in parametros):
    break



Alexandre Rosas

unread,
Aug 22, 2022, 3:58:19 PM8/22/22
to Python Brasil
Favor desconsiderar estaa última parte ( , nº {item}) desta linha. Na correção, acabei esquecendo de tirar:

    print(f"Tô vendo a imagem: {img}, da {texto}, nº {item}")

Obs:  A 'def' possui apenas 2 parâmetros.

Marcelo Valle

unread,
Aug 22, 2022, 6:13:15 PM8/22/22
to python...@googlegroups.com
Estou te sugerindo fazer algo como abaixo, para descobrir o que está errado com o seu programa:

def visualizar(imagens, texto):
    for img in imagens:
        print(f"Tô vendo a imagem: {img}, da {texto}")
        if pyautogui.locateOnScreen(img, confidence=0.6) is not None:
            print(f"return True: {img} na pasta {texto}")
            return True
    print(f"return False: {img} na pasta {texto}")
    return False

Depois que você executar, a saída do programa deve te dar algum indicativo do que pode estar errado. 
Outra opção é você debugar e ir linha por linha pra descobrir o problema. 

Eu posso te colocar um código aqui para percorrer pastas e subpastas se você quiser, mas vai parecer mágica, vai funcionar e sua confiança continuará baixa. 
O melhor é você seguir tentando e usar prints ou debug pra tentar achar o erro na lógica do seu programa.

[]s

 

Alexandre Rosas

unread,
Aug 22, 2022, 7:04:27 PM8/22/22
to Python Brasil
Mais uma vez, agradeço pelo retorno.

Fiz exatamente o que me sugeriu (acima) e coloquei uma linha de 'print' entre cada linha do código.
Então, ele me retornou o resultado da linha do 1º 'print' (OK) e logo em seguida (na linha da condicional 'if') deu a mensagem de erro, indicando que o problema está ali naquela linha.

Obs: Eu já até tentei concatenar as variáveis dos caminhos de cada diretório ('grupo1' e 'grupo2') ao item 'img' (que representa cada imagem listada nos 2 diretórios), e ficou assim:
          if pyautogui.locateOnScreen(((grupo1 + img) or (grupo2 + img)), confidence=0.6) is not None:
  • Mas ainda assim retorna o erro.

Obs2: Com a ajuda do PyCharm eu já debuguei cada linha deste trechinho de código. Está livre de qualquer tipo de erro.


Eu realmente não faço ideia do que pode estar ocasionando este erro e, portanto, aprecio qualquer tipo de ajuda neste momento.

...Pois, o parâmetro 'img' (que a linha da condicional 'if pyautogui...' está tentando localizar) criado no loop 'for', aponta corretamente para 'imagens' (que recebe um os.listdir para o diretório de cada pasta)...


Grato.

Marcelo Valle

unread,
Aug 22, 2022, 7:57:05 PM8/22/22
to python...@googlegroups.com

Alexandre Rosas

unread,
Aug 22, 2022, 10:20:38 PM8/22/22
to Python Brasil
Olá novamente, perdoe-me a demora!
Ficou um pouco extenso, mas estão aí as 2 mensagens de erro. Organizado e comentado.

###
Primeiro erro (quando coloco uma linha 'print...' , conforme você orientou, entre cada linha do código)
A mensagem que aparece é esta:

Tô vendo a imagem: botaoAlta.png, da Pasta 1
[ WARN:0...@0.120] global D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp (239) cv::findDecoder imread_('botaoAlta.png'): can't open/read file: check file path/integrity
Traceback (most recent call last):
  File "C:\Python (Gustavo)\Meus Projetos\PyCharm\Bot05\venv\lib\site-packages\pyautogui\__init__.py", line 175, in wrapper
    return wrappedFunction(*args, **kwargs)
  File "C:\Python (Gustavo)\Meus Projetos\PyCharm\Bot05\venv\lib\site-packages\pyautogui\__init__.py", line 213, in locateOnScreen
    return pyscreeze.locateOnScreen(*args, **kwargs)
  File "C:\Python (Gustavo)\Meus Projetos\PyCharm\Bot05\venv\lib\site-packages\pyscreeze\__init__.py", line 373, in locateOnScreen
    retVal = locate(image, screenshotIm, **kwargs)
  File "C:\Python (Gustavo)\Meus Projetos\PyCharm\Bot05\venv\lib\site-packages\pyscreeze\__init__.py", line 353, in locate
    points = tuple(locateAll(needleImage, haystackImage, **kwargs))
  File "C:\Python (Gustavo)\Meus Projetos\PyCharm\Bot05\venv\lib\site-packages\pyscreeze\__init__.py", line 207, in _locateAll_opencv
    needleImage = _load_cv2(needleImage, grayscale)
  File "C:\Python (Gustavo)\Meus Projetos\PyCharm\Bot05\venv\lib\site-packages\pyscreeze\__init__.py", line 170, in _load_cv2
    raise IOError("Failed to read %s because file is missing, "
OSError: Failed to read botaoAlta.png because file is missing, has improper permissions, or is an unsupported or invalid format


Process finished with exit code 1


###
E o segundo erro (quando tento concatenar os diretórios com 'img')

Obs: Neste segundo caso, após colocar ((grupo1 + img) or (grupo2 + img)) dentro da instrução 'if', eu tive que transformar as variáves dos diretórios ('grupo1' e 'grupo2')  em strings (str).
Ficou assim:

grupo1 = str(os.listdir("C:/Pasta1/"))
grupo2 = str(os.listdir("C:/Pasta2/"))


...E a mensagem que aparece é esta (obs: não sei porque apareceu um colchetes no lugar do nome da imagem):

Tô vendo a imagem: [, da Pasta 1
[ WARN:0...@0.114] global D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp (239) cv::findDecoder imread_('['botaoAlta.png']['): can't open/read file: check file path/integrity
Traceback (most recent call last):
  File "C:\Python (Gustavo)\Meus Projetos\PyCharm\Bot05\venv\lib\site-packages\pyautogui\__init__.py", line 175, in wrapper
    return wrappedFunction(*args, **kwargs)
  File "C:\Python (Gustavo)\Meus Projetos\PyCharm\Bot05\venv\lib\site-packages\pyautogui\__init__.py", line 213, in locateOnScreen
    return pyscreeze.locateOnScreen(*args, **kwargs)
  File "C:\Python (Gustavo)\Meus Projetos\PyCharm\Bot05\venv\lib\site-packages\pyscreeze\__init__.py", line 373, in locateOnScreen
    retVal = locate(image, screenshotIm, **kwargs)
  File "C:\Python (Gustavo)\Meus Projetos\PyCharm\Bot05\venv\lib\site-packages\pyscreeze\__init__.py", line 353, in locate
    points = tuple(locateAll(needleImage, haystackImage, **kwargs))
  File "C:\Python (Gustavo)\Meus Projetos\PyCharm\Bot05\venv\lib\site-packages\pyscreeze\__init__.py", line 207, in _locateAll_opencv
    needleImage = _load_cv2(needleImage, grayscale)
  File "C:\Python (Gustavo)\Meus Projetos\PyCharm\Bot05\venv\lib\site-packages\pyscreeze\__init__.py", line 170, in _load_cv2
    raise IOError("Failed to read %s because file is missing, "
OSError: Failed to read ['botaoAlta.png'][ because file is missing, has improper permissions, or is an unsupported or invalid format


Process finished with exit code 1


Talvez com estes exemplos você consiga perceber o que (possivelmente) eu estou fazendo de 'errado'.
Sou iniciante em python, além de ser auto-didata e tudo o que eu aprendi, até agora, foi pesquisando na internet (YouTube e Google).
Mas confesso que enrosquei neste erro já tem uns 4 dias e não consigo sair do lugar...
Já tentei procurar de diversas formas o que pode estar ocasionando este erro e não consigo descobrir... 

Qualquer dúvida estou a disposição. Grato!

Marcelo Valle

unread,
Aug 23, 2022, 5:02:34 AM8/23/22
to python...@googlegroups.com
Ok, agora, com essas informações, fica mais fácil sabermos o que está acontecendo. 

Vamos focar no primeiro erro, depois que você resolver o primeiro te ajudo com o segundo.

Pelo visto, o conteúdo da variável img eh exatamente o nome do arquivo: `botaoAlta.png` - veja que os.listdir retornou o nome do arquivo dentro da pasta.
Contudo, os.listdir não retornou o PATH completo do arquivo. Esse arquivo, `botaoAlta.png`, poderia estar em qualquer pasta do seu computador. Quando você não passa o caminho completo, o que o sistema operacional faz? Ele usa o caminho corrente, o famoso `CWD` - Current Working Directory. Então se você estava na pasta "Meus documentos", por exemplo, quando executou seu programa, ele vai tentar carregar o arquivo `botaoAlta.png` de dentro dessa pasta. Como o arquivo não está nessa pasta, seu programa dá erro pra carregar. 

Para solucionar isso, você pode colocar o caminho completo na sua tupla. Uma forma de fazer isso eh como abaixo:


import os

def lista_dir_retornando_caminho_completo(pasta_pai):
resultado = []
for arquivo in os.listdir(pasta_pai):
caminho_completo = os.path.join(pasta_pai, arquivo)
resultado.append(caminho_completo)
return resultado

# Subpastas com as imagens de referência
grupo1 = lista_dir_retornando_caminho_completo("C:/Projeto1/Pasta1/")
grupo2 = lista_dir_retornando_caminho_completo("C:/Projeto1/Pasta2/")



Alexandre Rosas

unread,
Aug 23, 2022, 1:22:11 PM8/23/22
to Python Brasil
Isso resolveu o problema, meus parabéns!
Não sei nem como te agradecer... 

Muiiiiiito obrigado meu amigo, eu fico te devendo uma.

Tenha um exceleeeente dia!
:D
Reply all
Reply to author
Forward
0 new messages