복붙노트

[PYTHON] 이미지가 주어진 미로를 표현하고 해결합니다.

PYTHON

이미지가 주어진 미로를 표현하고 해결합니다.

이미지가 주어진 미로를 표현하고 해결하는 가장 좋은 방법은 무엇입니까?

위에서 볼 수 있듯이 JPEG 이미지가 주어지면 그것을 읽는 가장 좋은 방법은 무엇이며 어떤 데이터 구조로 파싱하고 미로를 푸는 것일까 요? 필자의 첫 번째 본능은 픽셀 단위로 이미지를 읽고 부울 값의 목록 (배열)에 저장하는 것입니다 : 흰색 픽셀의 경우 True, 흰색이 아닌 픽셀의 경우 False (색을 버릴 수 있음). 이 방법의 문제점은 이미지가 "픽셀 완벽"하지 않을 수 있다는 것입니다. 간단히 말해서 벽면에 흰색 픽셀이 있으면 어딘가에 의도하지 않은 경로가 생길 수 있습니다.

또 다른 방법은 이미지를 SVG 파일로 변환하는 것입니다.이 파일은 캔버스에 그려진 경로 목록입니다. 이 방법을 사용하면 경로를 같은 종류의 목록 (부울 값)으로 읽을 수 있습니다. 여기서 True는 경로 또는 벽을 나타내고 False는 이동 가능한 공간을 나타냅니다. 전환이 100 % 정확하지 않고 모든 벽을 완전히 연결하지 않아서 틈을 만드는 경우이 방법의 문제가 발생합니다.

또한 SVG로 변환 할 때의 문제는 선들이 "완벽하게"직선이 아닐 수 있다는 것입니다. 결과적으로 경로는 3 차 베 지어 커브가됩니다. 정수로 인덱싱 된 부울 값의 목록 (배열)을 사용하면 커브가 쉽게 전송되지 않고 커브에 줄을 모두 표시해야하지만 목록 인덱스와 정확히 일치하지는 않습니다.

나는이 방법들 중 하나가 그렇게 큰 이미지가 주어지면 비참하게 비효율적이며 더 나은 방법이 존재한다고 생각한다. 가장 효과적이고 (최소한의 복잡성으로) 어떻게 최선입니까? 가장 좋은 방법이 있습니까?

그런 다음 미로를 해결합니다. 처음 두 가지 방법 중 하나를 사용하면 본질적으로 행렬로 끝납니다. 이 대답에 따르면, 미로를 나타내는 좋은 방법은 트리를 사용하는 것이고, 좋은 방법은 A * 알고리즘을 사용하는 것입니다. 어떻게 이미지에서 나무를 만들 수 있습니까? 어떤 아이디어?

TL, DR 구문 분석하는 가장 좋은 방법은? 어떤 데이터 구조에? 구조가 어떻게 도움을 주 었는가 / 해결하는데 어려움이 있습니까?

최신 정보 @Thomas가 추천 한대로 @Mikhail이 numpy를 사용하여 Python으로 작성한 것을 구현할 때 손을 사용해 보았습니다. 나는 알고리즘이 정확하다고 생각하지만 희망대로 작동하지 않습니다. (아래 코드) 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, [])

해결법

  1. ==============================

    1.여기에 해결책이 있습니다.

    여기에 해결책이 있습니다.

    다음은 BFS 용 MATLAB 코드입니다.

    function path = solve_maze(img_file)
      %% Init data
      img = imread(img_file);
      img = rgb2gray(img);
      maze = img > 0;
      start = [985 398];
      finish = [26 399];
    
      %% Init BFS
      n = numel(maze);
      Q = zeros(n, 2);
      M = zeros([size(maze) 2]);
      front = 0;
      back = 1;
    
      function push(p, d)
        q = p + d;
        if maze(q(1), q(2)) && M(q(1), q(2), 1) == 0
          front = front + 1;
          Q(front, :) = q;
          M(q(1), q(2), :) = reshape(p, [1 1 2]);
        end
      end
    
      push(start, [0 0]);
    
      d = [0 1; 0 -1; 1 0; -1 0];
    
      %% Run BFS
      while back <= front
        p = Q(back, :);
        back = back + 1;
        for i = 1:4
          push(p, d(i, :));
        end
      end
    
      %% Extracting path
      path = finish;
      while true
        q = path(end, :);
        p = reshape(M(q(1), q(2), :), 1, 2);
        path(end + 1, :) = p;
        if isequal(p, start) 
          break;
        end
      end
    end
    

    정말 간단하고 표준 적입니다. 파이썬이나 다른 곳에서 구현할 때 어려움이 있어서는 안됩니다.

    그리고 대답은 다음과 같습니다.

  2. ==============================

    2.이 솔루션은 파이썬으로 작성되었습니다. 이미지 준비에 대한 조언을 주신 Mikhail에게 감사드립니다.

    이 솔루션은 파이썬으로 작성되었습니다. 이미지 준비에 대한 조언을 주신 Mikhail에게 감사드립니다.

    움직이는 폭 넓은 우선 검색 :

    완성 된 미로 :

    #!/usr/bin/env python
    
    import sys
    
    from Queue import Queue
    from PIL import Image
    
    start = (400,984)
    end = (398,25)
    
    def iswhite(value):
        if value == (255,255,255):
            return True
    
    def getadjacent(n):
        x,y = n
        return [(x-1,y),(x,y-1),(x+1,y),(x,y+1)]
    
    def BFS(start, end, pixels):
    
        queue = Queue()
        queue.put([start]) # Wrapping the start tuple in a list
    
        while not queue.empty():
    
            path = queue.get() 
            pixel = path[-1]
    
            if pixel == end:
                return path
    
            for adjacent in getadjacent(pixel):
                x,y = adjacent
                if iswhite(pixels[x,y]):
                    pixels[x,y] = (127,127,127) # see note
                    new_path = list(path)
                    new_path.append(adjacent)
                    queue.put(new_path)
    
        print "Queue has been exhausted. No answer was found."
    
    
    if __name__ == '__main__':
    
        # invoke: python mazesolver.py <mazefile> <outputfile>[.jpg|.png|etc.]
        base_img = Image.open(sys.argv[1])
        base_pixels = base_img.load()
    
        path = BFS(start, end, base_pixels)
    
        path_img = Image.open(sys.argv[1])
        path_pixels = path_img.load()
    
        for position in path:
            x,y = position
            path_pixels[x,y] = (255,0,0) # red
    
        path_img.save(sys.argv[2])
    

    참고 : 흰색 방문 픽셀을 회색으로 표시합니다. 이렇게하면 방문 목록이 필요 없지만 경로를 그리기 전에 디스크에서 이미지 파일을 두 번째로드해야합니다 (최종 경로와 모든 경로를 합성 한 이미지가 필요없는 경우).

    내가 사용한 미로의 빈 버전.

  3. ==============================

    3.나는이 문제에 대한 A-Star 검색을 구현하려고 노력했다. 프레임 워크와 알고리즘 의사 코드에 대한 Joseph Kern의 구현을 자세히 설명합니다.

    나는이 문제에 대한 A-Star 검색을 구현하려고 노력했다. 프레임 워크와 알고리즘 의사 코드에 대한 Joseph Kern의 구현을 자세히 설명합니다.

    def AStar(start, goal, neighbor_nodes, distance, cost_estimate):
        def reconstruct_path(came_from, current_node):
            path = []
            while current_node is not None:
                path.append(current_node)
                current_node = came_from[current_node]
            return list(reversed(path))
    
        g_score = {start: 0}
        f_score = {start: g_score[start] + cost_estimate(start, goal)}
        openset = {start}
        closedset = set()
        came_from = {start: None}
    
        while openset:
            current = min(openset, key=lambda x: f_score[x])
            if current == goal:
                return reconstruct_path(came_from, goal)
            openset.remove(current)
            closedset.add(current)
            for neighbor in neighbor_nodes(current):
                if neighbor in closedset:
                    continue
                if neighbor not in openset:
                    openset.add(neighbor)
                tentative_g_score = g_score[current] + distance(current, neighbor)
                if tentative_g_score >= g_score.get(neighbor, float('inf')):
                    continue
                came_from[neighbor] = current
                g_score[neighbor] = tentative_g_score
                f_score[neighbor] = tentative_g_score + cost_estimate(neighbor, goal)
        return []
    

    A-Star는 경험적 탐색 알고리즘이므로 목표에 도달 할 때까지 남은 비용 (여기서는 거리)을 계산하는 기능이 필요합니다. 차선책을 갖고 있지 않다면 비용을 과대 평가해서는 안됩니다. 보수적 인 선택은 맨하튼 (또는 택시) 거리가 될 것입니다. 사용 된 폰 노이만 지역의 그리드에서 두 점 사이의 직선 거리를 나타냅니다. (이 경우 비용을 과대 평가하지 않습니다.)

    그러나 이것은 주어진 미로에 대한 실제 비용을 현저히 과소 평가합니다. 그러므로 나는 두 개의 다른 거리 메트릭을 유클리드 거리에 제곱하고 맨하탄 거리에 네를 곱하여 비교했다. 그러나 이는 실제 비용을 과대 평가할 수 있으므로 차선책 결과를 초래할 수 있습니다.

    코드는 다음과 같습니다.

    import sys
    from PIL import Image
    
    def is_blocked(p):
        x,y = p
        pixel = path_pixels[x,y]
        if any(c < 225 for c in pixel):
            return True
    def von_neumann_neighbors(p):
        x, y = p
        neighbors = [(x-1, y), (x, y-1), (x+1, y), (x, y+1)]
        return [p for p in neighbors if not is_blocked(p)]
    def manhattan(p1, p2):
        return abs(p1[0]-p2[0]) + abs(p1[1]-p2[1])
    def squared_euclidean(p1, p2):
        return (p1[0]-p2[0])**2 + (p1[1]-p2[1])**2
    
    start = (400, 984)
    goal = (398, 25)
    
    # invoke: python mazesolver.py <mazefile> <outputfile>[.jpg|.png|etc.]
    
    path_img = Image.open(sys.argv[1])
    path_pixels = path_img.load()
    
    distance = manhattan
    heuristic = manhattan
    
    path = AStar(start, goal, von_neumann_neighbors, distance, heuristic)
    
    for position in path:
        x,y = position
        path_pixels[x,y] = (255,0,0) # red
    
    path_img.save(sys.argv[2])
    

    다음은 결과를 시각화하기위한 몇 가지 이미지입니다 (Joseph Kern이 게시 한 이미지에서 영감을 얻음). 애니메이션은 메인 while-loop를 10000 회 반복 한 후에 각각 새로운 프레임을 보여줍니다.

    폭 넓은 우선 검색 :

    스타 - 맨하탄 거리 :

    A-Star 제곱 유클리드 거리 :

    A-Star Manhattan 거리에 4를 곱한 값 :

    결과는 미로의 탐색 된 영역이 사용 된 휴리스틱 스에 대해 상당히 다르다는 것을 보여줍니다. 따라서, 제곱 된 유클리드 거리는 다른 메트릭과 다른 (차선의) 경로를 생성합니다.

    해지 될 때까지 런타임 측면에서 A-Star 알고리즘의 성능에 관해서는 거리 및 비용 기능에 대한 많은 평가가 BFS (Breadth-First Search)와 비교할 때 더 중요하다는 점에 유의하십시오. 각 후보 위치. 이러한 추가 기능 평가 비용 (A-Star)이 많은 수의 노드 점검 비용 (BFS)보다 비용이 중요한지, 특히 성능이 애플리케이션에 전혀 문제가되는지 여부는 개별적인 인식의 문제입니다 물론 일반적으로 대답 할 수는 없습니다.

    정보 검색 알고리즘 (예 : A-Star)이 철저한 검색 (예 : BFS)과 비교하여 더 나은 선택 일 수 있는지에 대해 일반적으로 말할 수있는 것은 다음과 같습니다. 미로의 차원의 수, 즉 탐색 트리의 브랜칭 인자에 따라, 철저한 검색 (철저하게 검색)의 단점이 기하 급수적으로 증가한다. 복잡성이 커짐에 따라 실행 가능성이 낮아지고 실현 가능성이 낮아지고 어느 시점에서 (거의) 최적의 결과 경로로 인해 어떤 결과 경로로도 매우 만족합니다.

  4. ==============================

    4.트리 검색이 너무 많습니다. 미로는 본질적으로 솔루션 경로를 따라 분리 가능합니다.

    트리 검색이 너무 많습니다. 미로는 본질적으로 솔루션 경로를 따라 분리 가능합니다.

    (reddit의 Rainman002에게 감사의 말을 전하고 싶습니다.)

    이 때문에 연결된 구성 요소를 신속하게 사용하여 미로 벽의 연결된 섹션을 식별 할 수 있습니다. 이렇게하면 픽셀을 두 번 반복합니다.

    이를 솔루션 경로의 멋진 다이어그램으로 바꾸려면 요소를 구성하는 이진 연산을 사용하여 연결된 각 영역의 "막 다른 방향"경로를 채우십시오.

    MATLAB의 데모 코드는 다음과 같습니다. 더 나은 결과를 정리하고, 더 일반화 할 수있게하며, 더 빠르게 실행할 수 있도록 조정할 수 있습니다. (언젠가 오전 2시 30 분이 아닌 경우)

    % read in and invert the image
    im = 255 - imread('maze.jpg');
    
    % sharpen it to address small fuzzy channels
    % threshold to binary 15%
    % run connected components
    result = bwlabel(im2bw(imfilter(im,fspecial('unsharp')),0.15));
    
    % purge small components (e.g. letters)
    for i = 1:max(reshape(result,1,1002*800))
        [count,~] = size(find(result==i));
        if count < 500
            result(result==i) = 0;
        end
    end
    
    % close dead-end channels
    closed = zeros(1002,800);
    for i = 1:max(reshape(result,1,1002*800))
        k = zeros(1002,800);
        k(result==i) = 1; k = imclose(k,strel('square',8));
        closed(k==1) = i;
    end
    
    % do output
    out = 255 - im;
    for x = 1:1002
        for y = 1:800
            if closed(x,y) == 0
                out(x,y,:) = 0;
            end
        end
    end
    imshow(out);
    

  5. ==============================

    5.임계 값 연속 채우기를 위해 대기열을 사용합니다. 입구 왼쪽에있는 픽셀을 대기열로 밀어 넣은 다음 루프를 시작합니다. 대기중인 픽셀이 충분히 어두우면 밝은 회색 (임계 값 초과)으로 표시되고 모든 인접 픽셀이 대기열로 푸시됩니다.

    임계 값 연속 채우기를 위해 대기열을 사용합니다. 입구 왼쪽에있는 픽셀을 대기열로 밀어 넣은 다음 루프를 시작합니다. 대기중인 픽셀이 충분히 어두우면 밝은 회색 (임계 값 초과)으로 표시되고 모든 인접 픽셀이 대기열로 푸시됩니다.

    from PIL import Image
    img = Image.open("/tmp/in.jpg")
    (w,h) = img.size
    scan = [(394,23)]
    while(len(scan) > 0):
        (i,j) = scan.pop()
        (r,g,b) = img.getpixel((i,j))
        if(r*g*b < 9000000):
            img.putpixel((i,j),(210,210,210))
            for x in [i-1,i,i+1]:
                for y in [j-1,j,j+1]:
                    scan.append((x,y))
    img.save("/tmp/out.png")
    

    해결책은 회색 벽과 색 벽 사이의 복도입니다. 이 미로에는 여러 가지 해결책이 있음에 유의하십시오. 또한 이것은 단지 작동하는 것처럼 보입니다.

  6. ==============================

    6.여기에 간다 : maze-solver-python (GitHub)

    여기에 간다 : maze-solver-python (GitHub)

    나는 이것에 놀고 재미를 가지고 있고 조셉 컨의 대답에 늘였다. 그것에서 떨어지기 위하여 아닙니다; 나는 이것으로 주변에 놀기에 흥미있을지도 모르는 다른 누군가를 위해 약간 작은 추가를 만들었다.

    BFS를 사용하여 최단 경로를 찾는 Python 기반 솔버입니다. 내 주요 추가 내용은 다음과 같습니다.

    시작 / 종료점은이 샘플 미로에 대해 하드 코딩되어 있지만 적절한 픽셀을 선택할 수 있도록 확장 할 계획입니다.

  7. ==============================

    7.나는 matrix-of-bools 옵션을 사용할 것입니다. 표준 파이썬리스트가 너무 비효율적이라면 numpy.bool 배열을 대신 사용할 수 있습니다. 1000x1000 픽셀 미로의 저장 용량은 1MB입니다.

    나는 matrix-of-bools 옵션을 사용할 것입니다. 표준 파이썬리스트가 너무 비효율적이라면 numpy.bool 배열을 대신 사용할 수 있습니다. 1000x1000 픽셀 미로의 저장 용량은 1MB입니다.

    트리 또는 그래프 데이터 구조를 만들지 마십시오. 그것은 단지 그것에 대해 생각하는 방법 일 뿐이지 만 반드시 메모리에서 표현하는 좋은 방법은 아닙니다. 부울 행렬은 코드 작성이 쉽고 효율적입니다.

    그런 다음 A * 알고리즘을 사용하여이를 해결하십시오. 거리 발견 적 방법의 경우 맨하탄 거리 (distance_x + distance_y)를 사용하십시오.

    노드를 (행, 열) 좌표의 튜플로 나타냅니다. 알고리즘 (Wikipedia 의사 코드)에서 "이웃"을 호출 할 때마다 네 개의 가능한 이웃을 반복하는 것이 간단합니다 (이미지의 가장자리를 유의하십시오!).

    여전히 너무 느리다면 이미지를로드하기 전에 크기를 축소 할 수 있습니다. 과정에서 좁은 길을 잃지 않도록주의하십시오.

    어쩌면 파이썬에서 1 : 2 축소를 수행하여 실제로 가능한 경로를 잃지 않았는지 확인하는 것도 가능합니다. 흥미로운 옵션이지만 조금 더 생각해야합니다.

  8. ==============================

    8.다음은 몇 가지 아이디어입니다.

    다음은 몇 가지 아이디어입니다.

    (1. 이미지 처리 :)

    1.1 이미지를 RGB 픽셀 맵으로로드하십시오. C #에서는 system.drawing.bitmap을 사용하면 간단합니다. 이미징에 대한 간단한 지원이없는 언어에서 이미지를 휴대용 픽스맵 형식 (PPM) (유닉스 텍스트 표현, 큰 파일 생성) 또는 BMP 또는 TGA와 같이 쉽게 읽을 수있는 간단한 바이너리 파일 형식으로 변환하십시오. Unix의 ImageMagick 또는 Windows의 IrfanView.

    1.2 이전에 언급했듯이 각 픽셀에 대해 (R + G + B) / 3을 그레이 톤의 표시기로 사용하여 데이터를 단순화 한 다음 값을 임계 값으로 설정하여 흑백 테이블을 만들 수 있습니다. 0 = 검은 색과 255 = 흰색으로 가정하면 200에 가까운 것이 JPEG 유물을 제거합니다.

    (2. 해결책 :)

    2.1 Depth-First Search : 시작 위치가있는 빈 스택을 초기화하고, 사용 가능한 후속 동작을 수집하고, 무작위로 하나를 선택하여 스택으로 밀어 넣거나, 끝까지 도달 할 때까지 진행하십시오. 스택을 튕겨서 막 다른 골목길에서지도에서 어떤 위치를 방문했는지 추적해야하므로 사용 가능한 이동을 수집 할 때 동일한 경로를 두 번 사용하지 마십시오. 애니메이션을 적용하는 것은 매우 흥미 롭습니다.

    2.2 폭 넓은 우선 검색 : 위와 비슷하지만 대기열 만 사용합니다. 애니메이션 효과도 있습니다. 이것은 이미지 편집 소프트웨어의 홍수 채우기처럼 작동합니다. 나는이 트릭을 사용하여 포토샵에서 미로를 풀 수있을 것이라고 생각합니다.

    2.3 벽 추종자 (Wall Follower) : 기하학적으로 말해서, 미로는 접혀진 / 뒤얽힌 관입니다. 벽에 손을 얹으면 결국 출구를 발견 할 것입니다.) 이것이 항상 작동하는 것은 아닙니다. 예를 들어 완벽한 미로 등 특정 가정은 섬을 포함합니다. 그것을 봐라. 그것은 매혹적이다.

    (3. 댓글 :

    이것은 까다 롭습니다. 단순한 배열 형식으로 표현되는 미로를 해결하는 것은 쉽습니다. 각 요소는 북쪽, 동쪽, 남쪽 및 서쪽 벽이있는 셀 유형이고 방문 깃발 필드입니다. 그러나 당신이 손으로 그려진 스케치가 주어진다면, 이것은 지저분 해집니다. 나는 정직하게 스케치를 합리화하려고 노력하면 너트가 몰리게 될 것이라고 생각한다. 이것은 상당히 관련되어있는 컴퓨터 비전 문제와 유사합니다. 이미지 맵에 직접 들어가는 것이 더 쉽고 낭비 일 수도 있습니다.

  9. ==============================

    9.다음은 R을 사용하는 솔루션입니다.

    다음은 R을 사용하는 솔루션입니다.

    ### download the image, read it into R, converting to something we can play with...
    library(jpeg)
    url <- "https://i.stack.imgur.com/TqKCM.jpg"
    download.file(url, "./maze.jpg", mode = "wb")
    jpg <- readJPEG("./maze.jpg")
    
    ### reshape array into data.frame
    library(reshape2)
    img3 <- melt(jpg, varnames = c("y","x","rgb"))
    img3$rgb <- as.character(factor(img3$rgb, levels = c(1,2,3), labels=c("r","g","b")))
    
    ## split out rgb values into separate columns
    img3 <- dcast(img3, x + y ~ rgb)
    

    RGB를 그레이 스케일로 변환하려면 다음을 참조하십시오. https://stackoverflow.com/a/27491947/2371031

    # convert rgb to greyscale (0, 1)
    img3$v <- img3$r*.21 + img3$g*.72 + img3$b*.07
    # v: values closer to 1 are white, closer to 0 are black
    
    ## strategically fill in some border pixels so the solver doesn't "go around":
    img3$v2 <- img3$v
    img3[(img3$x == 300 | img3$x == 500) & (img3$y %in% c(0:23,988:1002)),"v2"]  = 0
    
    # define some start/end point coordinates
    pts_df <- data.frame(x = c(398, 399),
                         y = c(985, 26))
    
    # set a reference value as the mean of the start and end point greyscale "v"s
    ref_val <- mean(c(subset(img3, x==pts_df[1,1] & y==pts_df[1,2])$v,
                      subset(img3, x==pts_df[2,1] & y==pts_df[2,2])$v))
    
    library(sp)
    library(gdistance)
    spdf3 <- SpatialPixelsDataFrame(points = img3[c("x","y")], data = img3["v2"])
    r3 <- rasterFromXYZ(spdf3)
    
    # transition layer defines a "conductance" function between any two points, and the number of connections (4 = Manhatten distances)
    # x in the function represents the greyscale values ("v2") of two adjacent points (pixels), i.e., = (x1$v2, x2$v2)
    # make function(x) encourages transitions between cells with small changes in greyscale compared to the reference values, such that: 
    # when v2 is closer to 0 (black) = poor conductance
    # when v2 is closer to 1 (white) = good conductance
    tl3 <- transition(r3, function(x) (1/max( abs( (x/ref_val)-1 ) )^2)-1, 4) 
    
    ## get the shortest path between start, end points
    sPath3 <- shortestPath(tl3, as.numeric(pts_df[1,]), as.numeric(pts_df[2,]), output = "SpatialLines")
    
    ## fortify for ggplot
    sldf3 <- fortify(SpatialLinesDataFrame(sPath3, data = data.frame(ID = 1)))
    
    # plot the image greyscale with start/end points (red) and shortest path (green)
    ggplot(img3) +
      geom_raster(aes(x, y, fill=v2)) +
      scale_fill_continuous(high="white", low="black") +
      scale_y_reverse() +
      geom_point(data=pts_df, aes(x, y), color="red") +
      geom_path(data=sldf3, aes(x=long, y=lat), color="green")
    

    짜잔!

    이것은 테두리 픽셀 (하!)을 채우지 않으면 어떻게됩니까?

    전체 공개 : 나는 이것을 발견하기 전에 나에게 매우 비슷한 질문을 던지고 대답했다. 그런 다음 SO의 마술을 통해이 하나를 최고 "관련 질문"중 하나로 찾아 냈습니다. 나는이 미로를 추가 테스트 케이스로 사용할 것이라고 생각했다. 거기에 대한 나의 대답은 아주 작은 수정으로이 애플리케이션에서도 작동한다는 것을 발견하게되어 매우 기뻤다.

  10. from https://stackoverflow.com/questions/12995434/representing-and-solving-a-maze-given-an-image by cc-by-sa and MIT license