# Identify the best angle to orient a map

This is the image I am working with:

My goal is to rotate this (within a hundredth of a degree) so that the longest-lines/most-lines are completely horizontal.

## First Attempts

The first thing I did was look into using Houghlines for this, but it doesn't help me find the "best" lines in my image. It just produces a set of lines and angles; this is a problem because there may be a lot of lines in my map and I need to know the length and angle of each of them to evaluate the best map orientation. After a lot of tinkering I wasn't able to get the function to properly detect precise location of my lines, even after giving rho and theta a precision of 0.01 and np.pi/18000 respectively.

My second attempt was to count the pixels individually and analyze them statistically. This was very computationally intensive and lead me down a rabbit hole trying to organise shared memory between multiple processors in Python. The original code is in the first version of my post (I've removed it to keep things clean).

## Using HoughLinesP

As suggested I have tried using HoughLinesP.

import cv2                                                  # used for image processing functions
import numpy as np                                          # used for matrix calculations with opencv
class align_map():

def __init__(self, map_name):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
th, bw_image = cv2.threshold(image, 150, 255, cv2.THRESH_BINARY)
# cv2.imshow("bw_image", bw_image)
edges = cv2.Canny(bw_image, 50, 150, apertureSize=7)

threshold = 60
min_line_length = 10
max_line_gap = 30
lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=threshold, maxLineGap=max_line_gap, minLineLength=min_line_length)

count = 50
for x in range(0, len(lines)):
for x1,y1,x2,y2 in lines[x]:
cv2.line(image,(x1,y1),(x2,y2),(0,count,255-count),2)
count = count + 20
if (count > 255):
count = 40

cv2.imshow("HoughLinesP_Result", image)
cv2.waitKey(0)

map_name = "example.png"
align_map(map_name)


I've managed to detect the lines reasonably well. The different colours are there just to identify individual lines

Now I need to sort these into respective bins according to their angle, but I have a slight problem because I am getting duplicates--you can see this by the red and green neighbouring lines. I believe this is because I'm using Canny() for my edge detection. It's a problem because it will skew my weightings for each line.

edit retag close merge delete

Well, some simple pre-processing should help quite a bit. Threshold so you only keep the pure white, then only keep a one pixel boundary. That should give you edges without the double lines.

( 2017-03-20 22:54:44 -0500 )edit

Sort by ยป oldest newest most voted

I think you had the right idea when you were looking at HoughLines. However, you would be better served with HoughLinesP. This is precisely the sort of thing that the Hough transform is for.

The reason to use the HoughLinesP is that it gives you a measure of length as well as angle. You can just add up the length of the lines in each rotation bin. You'll have to do a bit of math to figure out which bin it's in, but you shouldn't have any trouble with that.

To get a high resolution, go back with a second iteration (or more!) over the bin with the highest number of votes at a much narrower range and higher precision.

Here's the python tutorial for HoughLinesP.

more

I've went through the tutorial of HoughLinesP and I was not getting very good results... The results I were getting indicate that my lines were not being detected where I believe that they should have been detected (i.e. from the middle of the line instead of from end to end). And not all lines were detected. You make a very good point though about using a broad detection phase first. I will try again and update and I will also take some time to earn some more reputation so I can add pictures.

( 2017-03-20 11:05:54 -0500 )edit

The key parameters are the last three. Threshold, length, and gap. Remember to start coarse and work your way in, or it could cut lines apart because they have slightly different orientations.

Also, I gave you some extra karma. I think you can post links and pictures now.

( 2017-03-20 17:53:08 -0500 )edit

Thank you for the support. I've edited my question to reflect the new approach (I got rid of my old code to avoid clutter). I am getting results with HoughLinesP as you've suggested. The only part of your answer that I don't understand is how to set a range when I repeat the algorithm for a higher resolution. Are you suggesting just making a bounding box ROI over the lines I'm interested in an increasing the resolution? I don't see a HoughLinesP function that allows specifying a range.

( 2017-03-20 22:12:17 -0500 )edit

I've been successful! Some pre-processing on the image helped with the Canny() double line problem. I did use bins and some statistical analysis, however I didn't find that I could specify a range when processing. Is it possible to limit the computations required by specifying a range for HoughLinesP?

( 2017-03-22 19:25:04 -0500 )edit

Ahh... Hmm. You're right, for some reason the HoughLinesP doesn't have the limits that HoughLInes does. If you're willing to modify the code, it doesn't look very hard to add the arguments. Pretty straightforward, though you wouldn't be able to use the IPP library.

( 2017-03-22 21:18:24 -0500 )edit

Thanks for the answer. I will probably do just that and make custom function. Cheers!

( 2017-03-27 11:17:07 -0500 )edit

Official site

GitHub

Wiki

Documentation