2

Hey there I am using Opencv3.3 and Pyhton2.7 for recognizing a Maze in an image. I have to find the outermost limit of the Maze in the image. I tried closing the entrance and exit gaps of the maze and finding the outermost shape. I worked on this for closing the gaps but it is useless for my problem because I need these gaps to solve the maze.

This is the original image

This is the original image

I want to find outermost limit of the maze.

This is what I want

This is what I want

How can I extract outermost contour?

Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
Yoko Bolt
  • 112
  • 1
  • 6
  • 1
    Surely you aren't really working from a JPEG image? Weren't you given a PNG? – Mark Setchell Aug 29 '18 at 16:36
  • 2
    If you find coloured pixels and make them white, you can remove the red and green wording, then the problem is simple... find first and last row that contains any black pixels, and likewise find first and last columns that contains any black pixels. Does that help? If not, please say what you are still stuck with. – Mark Setchell Aug 29 '18 at 16:39
  • There is no trouble in destroying color writing. To find the shortest exit path of the maze, I first need to write a code that finds the outermost periphery of the maze. but I do not know how to develop an algorithm. Would you elaborate on the black pixel solution you mentioned in the commentary? @MarkSetchell – Yoko Bolt Aug 30 '18 at 09:35

1 Answers1

3

I would do this with numpy rather than OpenCV, but the two are compatible so you can mix and match anyway, or you can adapt the technique to OpenCV once you get the idea of how I am tackling it.

The strategy is to sum all the pixels across every row and make a single pixel wide image (shown on the right below) that is the sum of all the pixels in each row. I then find the biggest value in that column and divide by that to normalise everything to the range 0..100. Now any pixel that is less than 30 in that single pixel wide image means that the corresponding row had less than 30% of white pixels in the original image - i.e. it was largely black.

Then I make the same summation of all the columns to produce the column sums - shown across the bottom of the image below:

enter image description here

I think some folks refer to this technique as a "projection" if you want to Google it.

So, the code looks like this:

#!/usr/local/bin/python3

import numpy as np
from PIL import Image

# Load image - you can use OpenCV "imread()" just the same and convert to grayscale
im = np.array(Image.open('maze.jpg').convert('L'))

# Get height and width
h,w = im.shape[0:2]

# Make a single pixel wide column, same height as image to store row sums in
rowsums=np.empty((h))      
# Sum all pixels in each row
np.sum(im,axis=1,out=rowsums)        
# Normalize to range 0..100, if rowsum[i] < 30 that means fewer than 30% of the pixels in row i are white
rowsums /= np.max(rowsums)/100      

# Find first and last row that is largely black
first = last = -1
for r in range(h):
    if first < 0 and rowsums[r] < 30:
        first = r
    if rowsums[r] < 30:
        last = r

print(first,last)

# Make a single pixel tall row, same width as image to store col sums in
colsums=np.empty((w))      
# Sum all pixels in each col
np.sum(im,axis=0,out=colsums)        
# Normalize to range 0..100, if colsum[i] < 30 that means fewer than 30% of the pixels in col i are white
colsums /= np.max(colsums)/100      

# Find first and last col that is largely black
first = last = -1
for c in range(w):
    if first < 0 and colsums[c] < 30:
        first = c
    if colsums[c] < 30:
        last = c

print(first,last)

That outputs:

62 890
36 1509

So the top row of the maze is row 62, and the bottom one is row 890. The left column of the maze is column 36 and the rightmost column is col 1509.

If I draw on an 80% transparent red rectangle to match those locations, I get:

enter image description here

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • 1
    Wow !! You are really good at mathematics. The solution is very successfull. But I have new problem in order to your method. On the project there is a rover outside the maze and the aruco marker on it. When I try to solve the problem with this method, the black markers on the outside influence the solution. I thought I would remove the marker with the method of removing small objects, but it would be useless because it may also remove the small walls of the maze. Do you have a suggestion to solve this problem ? I editted the question with new images. @MarkSetchell – Yoko Bolt Aug 30 '18 at 13:04
  • 1
    yes, that definetely works but locations are changing with respect to the aruco marker. When you draw a red rectangle, does it still give the same result ? – Yoko Bolt Aug 30 '18 at 13:12
  • 1
    The coordinates are the "answer". I only drew the rectangle so you could see what the coordinates encompass. If I draw the rectangle with the new coordinates it still exactly maps to the maze and ignores the aruco marker. – Mark Setchell Aug 30 '18 at 13:40
  • 1
    I really appreciate. That was my bad. Because I used different images. Also I used the skimage.draw library to match locations, the fact is that your drawing is more beautiful. Could you please also tell me how you drew red rectangle ? @MarkSetchell – Yoko Bolt Aug 30 '18 at 14:00
  • I drew it with **ImageMagick** which is installed on most Linux distros and is available for macOS and Windows. Just in Terminal, I type `convert maze.jpg -fill "rgba(255,0,0,0.2)" -draw "rectangle 135,32 1219,641" result.png` – Mark Setchell Aug 30 '18 at 14:18