0

Background:

I am making a program that detects the grid of a maze (like this). The way I do this is by getting the average color of each row/column and graphing it to locate the general grid lines (like this). With these grid lines I can group each row/column that is under the color threshold and map a line on the maze.

Problem:

What I am running into is a problem with certain mazes where there are no vertical lines. This will cause my algorithm to not detect a line and create errors as shown below. enter image description here

Question:

What methods would you suggest for a fix to this problem?

Note: I was thinking something like pattern detection to fill in the missing data?

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36

3 Answers3

1

You could try implementing a Hough transform extraction. It's purpose is detecting distances between imperfect object classes - and with a little bit of tweaking you can make it extract/detect your maze grid.

A transform extraction can perform groupings of edge points into object candidates.

Here's the Wikipedia article, which gives in-depth explanations on how it works: https://en.wikipedia.org/wiki/Hough_transform#Detecting_lines

I hope this helps :)

Eric Dirla
  • 81
  • 7
  • I think this is more relevant for actual line detection. I thin OP already does a nice job detecting the lines, but they are rather asking about how to find the entire grid, which includes some lines that are "invisible" in the input image. – Berthur Aug 02 '22 at 12:50
  • Exactly correct @Berthur – Carlos Cuartas Aug 03 '22 at 12:22
1

If your input maze is guaranteed to be based on a grid, like the images you show, then I would suggest a more deterministic approach.

It is probably sufficient to find one wall on each column. So instead of averaging all pixels in a column (which loses a lot of useful information), you can measure e.g. the longest consecutive list of black pixels. If this is much longer than the width of a wall, then you know it is the length of a wall and thus you know the column lies on a grid line.

When you have done this for all columns, you get a discrete graph instead and you can choose a value somewhere in the middle of each peak for the actual column line.

Some grid lines might not have vertical walls at all though, but you can easily interpolate these when you have found at least 3 grid lines.

Another approach would be performing some signal processing and find the period of your function, but I think simple interpolation would be easier to implement and understand.

Edit: The interpolation can be done in different ways. In the easiest case, you assume that at least one column has a "neighbour", i.e., two detected columns that are adjacent in the grid, and that you detect the first and last column.

In this case, all you need to do is find the smallest distance between neighbours to find the grid cell width. You can also compare it with the cell height and choose whichever is smaller. Then, apply this width between the first and last columns to get all the columns.

Another approach, if you can't make this assumption, is that you repeatedly apply every column you detect with the same period throughout the grid, counting from the front and from the back, like so:

|_ _ _ _|_ _ _ _ _ _| => |_ _ _ _|_ _ _ _|_ _| => |_ _|_ _|_ _|_ _|_ _|

and repeating until no more edits are being made.

Berthur
  • 4,300
  • 2
  • 14
  • 28
  • "but you can easily interpolate these when you have found at least 3 grid lines." This is what I want to do but need an appropriate method to do so accurately. – Carlos Cuartas Aug 03 '22 at 12:26
  • @CarlosCuartas Understood. I added two possible approaches to my answer. – Berthur Aug 03 '22 at 12:52
0

if I understand your approach correctly you are counting the "whiteness" or "blackness" over a row/column and want to use those distributions to determine the grid

what about extracting the grid lines like you planned to do, and measure them, to find a candidate value for the grid spacing sp(the whole procedure is the same for rows and columns and can be done independantly)

from there you can create a candidate grid with that spacing

now measure the candidate the same way you measured the source...

extract only the spikes in your graph as discrete values, do that for the source image s and the candidate grid c, we are are only interested in the coordinate axis, and we will have to offset said axis so one of their respective spikes match

now for each value x_s in your discrete value list for s, find the corresponding value x_c in c, with (x_s - sp/2) < x_c < (x_s + sp/2)

if there's at least one x_s that has no x_c, consider the test a fail (abort criteria for later, or the sp candidate was way off)

once all x_s values have a corresponding x_c, calculate their difference and adjust sp with the mean difference and test the new candidate ...

we are looking for the biggest sp that passes the test, and since only smaller sp values could pass (think: if sp is the grid spacing, sp/(2^x) will also pass the test), you can test if sp*2 still passes or you can look at how many x_c values have no x_s value

DarkSquirrel42
  • 10,167
  • 3
  • 20
  • 31
  • I'm not sure if I follow, you lost me here: "find the corresponding value x_c in c, with (x_s - sp/2) < x_c < (x_s + sp/2)" – Carlos Cuartas Aug 03 '22 at 12:31
  • c and s are lists of values with x_c and x_s being items in these lists. the lists contain the coordinate values of the peaks you detected in the source image and the candidate image containing the candidate grid... sp is the spacing in the candidate grid ... for each x_s look into c and find one x_c that satisfies the inequation ... in general you match each peak of s to a peak in c corresponding to grid lines in the source and the candidate... the inequation represents the scope in which a match may be found... if it's further away than sp/2 it's not the peak you are looking for – DarkSquirrel42 Aug 03 '22 at 17:58