Qual é a melhor maneira de representar e resolver um labirinto com uma imagem?
Dada uma imagem JPEG (como vista acima), qual é a melhor maneira de lê-la, analisá-la em alguma estrutura de dados e resolver o labirinto? Meu primeiro instinto é ler a imagem em pixel por pixel e armazená-la em uma lista (matriz) de valores booleanos: True
para um pixel branco e False
para um pixel não branco (as cores podem ser descartadas). O problema com esse método é que a imagem pode não ser "pixel perfeita". Com isso, quero dizer simplesmente que, se houver um pixel branco em algum lugar na parede, ele poderá criar um caminho não intencional.
Outro método (que veio a mim depois de um pouco de reflexão) é converter a imagem em um arquivo SVG - que é uma lista de caminhos desenhados em uma tela. Dessa forma, os caminhos podem ser lidos no mesmo tipo de lista (valores booleanos) em que True
indica um caminho ou parede, False
indicando um espaço passível de deslocamento. Um problema com esse método surge se a conversão não for 100% precisa e não conectar totalmente todas as paredes, criando lacunas.
Também um problema com a conversão para SVG é que as linhas não são "perfeitamente" retas. Isso resulta nos caminhos sendo curvas cúbicas de bezier. Com uma lista (matriz) de valores booleanos indexados por números inteiros, as curvas não seriam transferidas facilmente e todos os pontos que alinham na curva precisariam ser calculados, mas não corresponderiam exatamente aos índices da lista.
Suponho que, embora um desses métodos possa funcionar (embora provavelmente não o seja), eles são lamentavelmente ineficientes, dada uma imagem tão grande e que existe uma maneira melhor. Como isso é feito (com mais eficiência e / ou com a menor complexidade)? Existe mesmo a melhor maneira?
Depois vem a resolução do labirinto. Se eu usar um dos dois primeiros métodos, acabarei essencialmente com uma matriz. De acordo com esta resposta , uma boa maneira de representar um labirinto é usar uma árvore, e uma boa maneira de resolvê-lo é usar o algoritmo A * . Como alguém criaria uma árvore a partir da imagem? Alguma ideia?
TL; DR
Melhor maneira de analisar? Em que estrutura de dados? Como essa estrutura ajudaria / dificultaria a solução?
ATUALIZAÇÃO
Tentei implementar o que o @Mikhail escreveu em Python, usando numpy
, como o @Thomas recomendado. Eu sinto que o algoritmo está correto, mas não está funcionando como esperado. (Código abaixo.) A biblioteca PNG é PyPNG .
import png, numpy, Queue, operator, itertools
def is_white(coord, image):
""" Returns whether (x, y) is approx. a white pixel."""
a = True
for i in xrange(3):
if not a: break
a = image[coord[1]][coord[0] * 3 + i] > 240
return a
def bfs(s, e, i, visited):
""" Perform a breadth-first search. """
frontier = Queue.Queue()
while s != e:
for d in [(-1, 0), (0, -1), (1, 0), (0, 1)]:
np = tuple(map(operator.add, s, d))
if is_white(np, i) and np not in visited:
frontier.put(np)
visited.append(s)
s = frontier.get()
return visited
def main():
r = png.Reader(filename = "thescope-134.png")
rows, cols, pixels, meta = r.asDirect()
assert meta['planes'] == 3 # ensure the file is RGB
image2d = numpy.vstack(itertools.imap(numpy.uint8, pixels))
start, end = (402, 985), (398, 27)
print bfs(start, end, image2d, [])
visited.append(s)
sob um for.if
e substituí-lo por visited.append(np)
. Um vértice é visitado quando é adicionado à fila. De fato, essa matriz deve ser denominada "na fila". Você também pode encerrar o BFS quando chegar ao fim.