How to solve the maze of pictures with Python code _python

Source: Internet
Author: User
Tags data structures


The original is stackoverflow on how to use the program to read the maze picture and solve the problem, several participants enthusiastically discussed and gave their own code, involving the use of Python image processing and breadth first (BFS) algorithm.



Problem by Whymarrh:






When given a JPEG image above, how can you better transform this diagram into a suitable data structure and solve the maze?



My first instinct is to read this graph in pixels, and store it in a list or array that contains a Boolean type element, where true stands for white pixels, and false for a non-white pixel (or color can be processed into a two-valued image). But there is a problem with the idea that a given picture is often not a perfect "pixel". Considering that if an unexpected white pixel appears on the maze wall for the reason of the image conversion, then one by one unexpected paths may be created.



After thinking, I came up with another way: first convert the picture to a scalable, appropriate graphic (SVG) file that consists of a list of vector lines on a canvas, and the vector lines are read in order of the list, and the read out is still a Boolean: Where True represents the wall, and false represents the range that can be passed. However, if this method does not guarantee that the image can be fully and accurately converted, especially if the wall can not be completely accurately connected, then the maze may appear cracks.



Another problem with converting images to SVG is that the lines are not perfect lines. Because the SVG line is a three-time Bezier curve, and a boolean list of integer indexes increases the difficulty of curve conversion, all the points on the maze line must be computed on the curve, but not necessarily the index values in the list.



Assuming that the above methods can be implemented (although most likely not), they are not competent when given a large image. So is there a better way to balance efficiency and complexity?



This is going to talk about how to solve the maze. If I use either of these two methods, I will eventually get a matrix. And according to this question and answer (http://stackoverflow.com/questions/3097556/programming-theory-solve-a-maze/3097677#3097677), A better way to find a maze is to use the tree structure and use a * search algorithm to solve the maze. So how do you construct a maze of trees from a maze picture? Is there a better way?



The above nonsense too much, summed up the question is: How to transform Maze picture? What data structure does the transformation become? What data structures are used to help or hinder the maze?






Answer by Mikhail:



This is my solution:



1. Convert the picture to grayscale image (not direct two values), adjust the weights of different colors to make the final grayscale look more unified, you can simply adjust the Photoshop image-> adjust the-> black and White menu control bar to achieve.
2. Converts the grayscale picture obtained in the previous step to a two-value picture, which can be achieved by setting the appropriate threshold value in the PS image-> adjustment-> threshold Menu
3. Ensure that thresholds are set correctly. Select an empty area using the Magic Wand tool (Parameter settings: Tolerance 0, sampling point, continuous, and anti-aliasing) to check that the edge of the selected area is not a false edge caused by an incorrect threshold setting. In fact, this maze from start to end should be connected by the blank area.
4. Artificially add boundaries outside the maze to ensure that the Maze Rover ^_^ does not run around the maze from start to finish. :)
5. Select the language implementation breadth First search algorithm (BFS), starting from the start to let the program run. The following code I choose to implement with Matlab. As Thomas mentions, there is no need to dwell on the representation of the image, you can run it directly on the binary image.



The following is the implementation of the BFS code with 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];
 %-percent 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


This is a simple implementation that should be easily rewritten as Python or other language, and the following is the result of the program's operation:






Questioner UPDATE:



I used Python to implement the Mikhail method, which used the NumPy library, thanks to Thomas's recommendation. I feel this algorithm is correct, but the effect is not as expected, the following is the relevant code, using the Pypng library to process the picture.



Unfortunately, the code I provided with the questioner did not run through the program and seemed to have a problem with code indentation, and the following other participant's code was able to execute and worked well.


Import PNG, NumPy, Queue, operator, Itertools
 
def is_white (coord, image): ""
 "Returns whether (x, y) is approx. a White pixel.
 "" " A = True for
 i-xrange (3):
  if not a:break
  a = image[coord[1]][coord[0] * 3 + i] >
 a
 
D EF BFS (S, E, I, visited): "" "
 perform a breadth-first search. "" "
 Frontier = Queue.queue () while
 s!= e:
  with 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 # Ensur E The file is RGB
 image2d = Numpy.vstack (Itertools.imap (numpy.uint8, pixels))
 start, end = (402, 985), (398, 27)
 print BFS (start, End, image2d, [])


Answer by Joseph Kern:


#!/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 [.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])


Dynamic execution Effect:






Answer by Jim



The use of tree search is too complicated, the maze itself with the solution path is divided. For this reason, you can use the connected area lookup algorithm to mark the connected areas in the maze, which will iterate through the two pixel points. If you want a better solution, you can use a two-dollar operation (binary operations) on a structural unit to populate a dead end in each connected area.



The following is the relevant MATLAB code and operation results:


% read in and invert the image
im = 255-imread (' maze.jpg ');
 
% sharpen it to address small the fuzzy channels
% threshold to binary 15%
% run connected
= Components Abel (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 < result
    (result==i) = 0;
  End
of
 
% 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
= 255-im;
For x = 1:1002
  to y = 1:800
    if closed (x,y) = = 0 out
      (x,y,:) = 0;
    End-end
-imshow (out);





Answer by Stefano



Stefano shoes gives the code Maze-solver-python (GitHub) of GIF and AVI files generated during the search process.





Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.