Jaki jest najlepszy sposób na przedstawienie i rozwiązanie labiryntu na podstawie obrazu?
Biorąc pod uwagę obraz JPEG (jak pokazano powyżej), jaki jest najlepszy sposób, aby go odczytać, przeanalizować w jakiejś strukturze danych i rozwiązać labirynt? Moim pierwszym instynktem jest odczytanie obrazu piksel po pikselu i zapisanie go na liście (tablicy) wartości boolowskich: True
dla białego piksela i False
dla innego niż biały piksel (kolory można odrzucić). Problem z tą metodą polega na tym, że obraz może nie być „w pikselach idealny”. Rozumiem przez to, że jeśli gdzieś na ścianie jest biały piksel, może on stworzyć niezamierzoną ścieżkę.
Inną metodą (która przyszła mi do głowy po namyśle) jest konwersja obrazu do pliku SVG - który jest listą ścieżek narysowanych na płótnie. W ten sposób ścieżki mogą zostać wczytane do tego samego rodzaju listy (wartości boolowskie), gdzie True
wskazuje ścieżkę lub ścianę, False
wskazując przestrzeń, którą można przejechać. Problem z tą metodą powstaje, jeśli konwersja nie jest w 100% dokładna i nie łączy w pełni wszystkich ścian, tworząc luki.
Problemem przy konwersji do SVG jest również to, że linie nie są „idealnie” proste. Powoduje to, że ścieżki są sześciennymi krzywymi Beziera. Z listą (tablicą) wartości boolowskich indeksowanych liczbami całkowitymi krzywe nie byłyby łatwe do przeniesienia, a wszystkie punkty na linii musiałyby zostać obliczone, ale nie pasowałyby dokładnie do indeksów listy.
Zakładam, że chociaż jedna z tych metod może działać (choć prawdopodobnie nie), to są one niestety nieefektywne, biorąc pod uwagę tak duży obraz i że istnieje lepszy sposób. Jak to się robi najlepiej (najbardziej wydajnie i / lub przy najmniejszej złożoności)? Czy jest jakiś najlepszy sposób?
Potem przychodzi rozwiązanie labiryntu. Jeśli użyję jednej z dwóch pierwszych metod, zasadniczo skończę na matrycy. Zgodnie z tą odpowiedzią dobrym sposobem na przedstawienie labiryntu jest użycie drzewa, a dobrym sposobem jego rozwiązania jest użycie algorytmu A * . Jak stworzyć drzewo z obrazu? Jakieś pomysły?
TL; DR
Najlepszy sposób na parsowanie? W jakiej strukturze danych? W jaki sposób wspomniana struktura pomaga / utrudnia rozwiązywanie?
AKTUALIZACJA
Próbowałem swoich sił we wdrażaniu tego, co @Mikhail napisał w Pythonie, używając numpy
zgodnie z zaleceniami @Thomas. Wydaje mi się, że algorytm jest poprawny, ale nie działa zgodnie z oczekiwaniami. (Kod poniżej.) Biblioteka PNG to 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)
pod a for.if
i zastąpić go visited.append(np)
. Wierzchołek jest odwiedzany po dodaniu do kolejki. W rzeczywistości tablica ta powinna mieć nazwę „w kolejce”. Możesz także zakończyć BFS, gdy dotrzesz do mety.