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):
image = cv2.imread(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.
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.