Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python openCV detect parallel lines

I have an image and it has some shapes in it. I detected lines with using hough lines. How can I detect which lines are parallel?

like image 368
vtokmak Avatar asked Apr 03 '13 06:04

vtokmak


People also ask

How do you find parallel lines in Python?

Two lines y = k1 * x + b1, y = k2 * x + b2 are parallel, if k1 = k2. So you need to calculate coefficient k for each detected line. In order to uniquely identify the equation of a line you need to know the coordinates of two points that belong to line.

What algorithm is used to detect lines in OpenCV?

The Hough Transform is a method that is used in image processing to detect any shape, if that shape can be represented in mathematical form. It can detect the shape even if it is broken or distorted a little bit.

How do I find the lines of an image in Python?

Use the HoughLinesP() Function of OpenCV to Detect Lines in an Image in Python. The HoughLinesP() function uses probabilistic Hough line transform to detect lines. We have to read the given image using the imread() function, convert it into grayscale, and then find its edges using Canny() .

What is cv2 HoughLines?

Everything explained above is encapsulated in the OpenCV function, cv2.HoughLines(). It simply returns an array of. values. is measured in pixels and is measured in radians. First parameter, Input image should be a binary image, so apply threshold or use canny edge detection before finding applying hough transform.


3 Answers

As John proposed, the easiest way is to detect similar angles. OpenCVs HoughLines function represents a line by means of its distance to the origin and an angle.

enter image description here

So what you could basically do is to cluster the different angles with a hierarchical clustering algorithm:

from scipy.spatial.distance import pdist
from scipy.cluster.hierarchy import ward, fcluster    

img = cv2.imread('images/img01.bmp')
img_canny = cv2.Canny(img, 50, 200, 3)

lines = cv2.HoughLines(img_canny, 1, 5* np.pi / 180, 150)

def find_parallel_lines(lines):

    lines_ = lines[:, 0, :]
    angle = lines_[:, 1]

    # Perform hierarchical clustering

    angle_ = angle[..., np.newaxis]
    y = pdist(angle_)
    Z = ward(y)
    cluster = fcluster(Z, 0.5, criterion='distance')

    parallel_lines = []
    for i in range(cluster.min(), cluster.max() + 1):
        temp = lines[np.where(cluster == i)]
        parallel_lines.append(temp.copy())

    return parallel_lines
like image 125
Franzi Avatar answered Oct 28 '22 21:10

Franzi


Equation of a line in Cartesian coordinates:

y = k * x + b

Two lines y = k1 * x + b1, y = k2 * x + b2 are parallel, if k1 = k2.

So you need to calculate coefficient k for each detected line.

In order to uniquely identify the equation of a line you need to know the coordinates of two points that belong to line.

After having found lines with HoughLines (С++):

vector<Vec2f> lines;
HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 );

you have the vector lines, which stores the parameters (r,theta) of the detected lines in polar coordinates. You need to transfer them in Cartesian coordinates:

Here example in C++:

for( size_t i = 0; i < lines.size(); i++ )
{
  float rho = lines[i][0], theta = lines[i][1];
  Point pt1, pt2;
  double a = cos(theta), b = sin(theta);
  double x0 = a*rho, y0 = b*rho;
  pt1.x = cvRound(x0 + 1000*(-b)); //the first point
  pt1.y = cvRound(y0 + 1000*(a)); //the first point
  pt2.x = cvRound(x0 - 1000*(-b)); //the second point
  pt2.y = cvRound(y0 - 1000*(a)); //the second point
}

After having got these two points of a line you can calculate its equation.

like image 29
Ann Orlova Avatar answered Oct 28 '22 20:10

Ann Orlova


HoughLines returns its results in Polar coordinates. So just check the 2nd value for the angle. No need to convert to x,y

def findparallel(lines):

lines1 = []
for i in range(len(lines)):
    for j in range(len(lines)):
        if (i == j):continue
        if (abs(lines[i][1] - lines[j][1]) == 0):          
             #You've found a parallel line!
             lines1.append((i,j))


return lines1
like image 36
john ktejik Avatar answered Oct 28 '22 21:10

john ktejik