user1803115
user1803115

Reputation: 39

Detecting square size on a grid

I need to detect the size of a square on a grid like this one (all squares are supposed to be equal): http://imgur.com/VZAimWS

I could think of many different strategies to find out what is the length of a side of a square, but I would expect there might be a particular technique that is more robust or considered better in terms of providing a more accurate answer. Any tips? One of the things I was exploring is to identify each parallel line and find the average (or maybe median) distance between the lines.

In case it's relevant, I am planning to use MatLab or OpenCV for this.

Thank you

Upvotes: 1

Views: 311

Answers (2)

Mark Setchell
Mark Setchell

Reputation: 207395

I see you want to do this in Matlab, but you might get some inspiration from my attacking it with ImageMagick, which is installed on most Linux distros, and available for OS X and Windows for free from here.

Here is the bones of how I proceed - it's just one command in the Terminal - no compilers, no OpenCV, no Matlab:

convert grid.jpg                                   \
   -threshold 80% -negate                          \
   -morphology Thinning:-1 Skeleton                \
   \( +clone                                       \
         -background none                          \
         -fill red -stroke red -strokewidth 2      \
         -hough-lines 9x9+150 -write lines.mvg     \
   \)                                              \
   -composite hough.png

That lovely command, does these steps:

  • thresholds the image to black and white at 80%
  • inverts it
  • thins it to a skeleton

  • copies the whole lot and on the copy performs a Hough Line detection colouring the lines in red

  • overlays the detected lines back onto the original image

The output image is like this:

enter image description here

And the file lines.mvg contains the line coordinates on which the maths is needed...

# Hough line transform: 9x9+150
viewbox 0 0 1777 1449
line 177.944,0 102.005,1449  # 191   <-- shown in yellow below
line 171.848,0 121.248,1449  # 332
line 0,118.401 1777,149.419  # 453
line 0,143 1777,143  # 181
line 0,283.426 1777,314.444  # 431
line 504.586,0 479.293,1449  # 252
line 0,454.452 1777,485.47  # 403
line 0,481 1777,481  # 164
line 0,627.479 1777,658.496  # 309
line 0,649 1777,649  # 233
line 842.637,0 817.345,1449  # 299
line 0,801.505 1777,832.523  # 558
line 0,844.525 1777,813.507  # 167
line 0,973.531 1777,1004.55  # 291
line 0,1013.55 1777,982.533  # 158
line 1180.69,0 1155.4,1449  # 495
line 0,1146.56 1777,1177.58  # 396
line 0,1182.58 1777,1151.56  # 350
line 0,1331 1777,1331  # 320
line 1510.74,0 1485.45,1449  # 539
line 0,1352.6 1777,1321.58  # 277
line 1504,0 1504,1449  # 201

I'll draw the first line from the list above in on the image in yellow so you can see how the coordinates work.

convert hough.png -stroke yellow -draw "line 177.944,0 102.005,1449" out.jpg

enter image description here

Now, about that maths... it is going to be hard to measure correctly on a distorted image, because it's... well, distorted. I would think about 2 strategies. Either take the top line and solve for its intersection with the leftmost line, and the same in the other 3 corners, You can then calculate the two diagonals of the image and estimate the distortion and amortize it across lots of squares which may be good. Or you could solve for the intersections of all the lines and apply some type of clustering to eradicate multiply-defined corners... or something simpler altogether.

Let's look at just the vertical lines...

grep -v "line 0" lines.mvg

line 177.944,0 102.005,1449  # 191
line 171.848,0 121.248,1449  # 332
line 504.586,0 479.293,1449  # 252
line 842.637,0 817.345,1449  # 299
line 1180.69,0 1155.4,1449  # 495
line 1510.74,0 1485.45,1449  # 539
line 1504,0 1504,1449  # 201

The first two are the same line, so let's average 177 and 171 to give 174. The last two are also the same line, so if we average 1510 and 1504 we get 1507. So, now the grid spacings are

330px = 504-174
338px = 842-504
338px = 1180-842
357px = 1507-1180

So, I'm going for 338px... ish :-)

Upvotes: 5

Rafael Ruiz Mu&#241;oz
Rafael Ruiz Mu&#241;oz

Reputation: 5473

Well what I would try is:

  1. Pass a threshold and you will get a better edge of the squares.
  2. Then pass the HoughLines algorithm
  3. You will get lines, please adapt the configuration to the best performance in order to see all the lines.
  4. Calculate the points where every line cross with another line and you will have the vertexes of each one.
  5. Use a little math! :)

Upvotes: 1

Related Questions