Qual è il modo migliore per rappresentare e risolvere un labirinto dato un'immagine?
Data un'immagine JPEG (come visto sopra), qual è il modo migliore per leggerlo, analizzarlo in qualche struttura di dati e risolvere il labirinto? Il mio primo istinto è leggere l'immagine in pixel per pixel e memorizzarla in un elenco (array) di valori booleani: True
per un pixel bianco e False
per un pixel non bianco (i colori possono essere scartati). Il problema con questo metodo è che l'immagine potrebbe non essere "pixel perfetta". Con ciò intendo semplicemente che se c'è un pixel bianco da qualche parte su un muro, potrebbe creare un percorso non intenzionale.
Un altro metodo (che mi è venuto in mente dopo un po 'di riflessione) è quello di convertire l'immagine in un file SVG - che è un elenco di percorsi disegnati su una tela. In questo modo, i percorsi potrebbero essere letti nello stesso tipo di elenco (valori booleani) in cui True
indica un percorso o un muro, che False
indica uno spazio percorribile . Un problema con questo metodo sorge se la conversione non è accurata al 100% e non collega completamente tutti i muri, creando spazi vuoti.
Anche un problema con la conversione in SVG è che le linee non sono "perfettamente" diritte. Ciò si traduce in curve cubiche più bezier dei percorsi. Con un elenco (array) di valori booleani indicizzati da numeri interi, le curve non si trasferirebbero facilmente e tutti i punti che si allineano sulla curva dovrebbero essere calcolati, ma non corrisponderanno esattamente agli indici dell'elenco.
Suppongo che mentre uno di questi metodi può funzionare (anche se probabilmente non lo è) che sono terribilmente inefficienti, data un'immagine così grande, e che esiste un modo migliore. Come si fa meglio (in modo più efficiente e / o con la minima complessità)? C'è anche un modo migliore?
Poi arriva la risoluzione del labirinto. Se uso uno dei primi due metodi, finirò essenzialmente con una matrice. Secondo questa risposta , un buon modo per rappresentare un labirinto è usare un albero e un buon modo per risolverlo è usare l' algoritmo A * . Come si potrebbe creare un albero dall'immagine? Qualche idea?
TL; DR Il
modo migliore per analizzare? In quale struttura di dati? In che modo la struttura potrebbe aiutare / ostacolare la risoluzione?
AGGIORNAMENTO
Ho provato a implementare ciò che @Mikhail ha scritto in Python, usando numpy
, come raccomandato da @Thomas. Sento che l'algoritmo è corretto, ma non funziona come sperato. (Codice sotto.) La libreria 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)
sotto a for.if
e sostituirlo con visited.append(np)
. Un vertice viene visitato una volta aggiunto alla coda. In effetti, questo array dovrebbe essere chiamato "in coda". Puoi anche terminare BFS una volta che hai raggiunto il traguardo.