Wednesday, August 9, 2017

How to detect lines in opencv?

Leave a Comment

I am trying to detect lines in parking as shown below

Empty parking lot

What I hope to get is the clear lines and (x,y) position in the crossed line, however the result is not very promising

Parking lot with Hough Lines drawn

I guess it is due to two main reasons

  1. some lines are very broken or missing even human eyes can clearly identify them. (Even HoughLine can help to connect some missing lines since HoughLine sometimes would connect unnecessary lines together, so I 'd rather to do it manually)

  2. there are some repeated lines

The general pipeline for the work is shown as below

1. select the some specific colors (white or yellow)

import cv2 import numpy as np import matplotlib from matplotlib.pyplot import imshow from matplotlib import pyplot as plt  # white color mask img = cv2.imread(filein) #converted = convert_hls(img) image = cv2.cvtColor(img,cv2.COLOR_BGR2HLS) lower = np.uint8([0, 200, 0]) upper = np.uint8([255, 255, 255]) white_mask = cv2.inRange(image, lower, upper) # yellow color mask lower = np.uint8([10, 0,   100]) upper = np.uint8([40, 255, 255]) yellow_mask = cv2.inRange(image, lower, upper) # combine the mask mask = cv2.bitwise_or(white_mask, yellow_mask) result = img.copy() cv2.imshow("mask",mask)  

Binary image

2. repeat the dilation and erosion until the image can not be changed (reference )

height,width = mask.shape skel = np.zeros([height,width],dtype=np.uint8)      #[height,width,3] kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3,3)) temp_nonzero = np.count_nonzero(mask) while(np.count_nonzero(mask) != 0 ):     eroded = cv2.erode(mask,kernel)     cv2.imshow("eroded",eroded)        temp = cv2.dilate(eroded,kernel)     cv2.imshow("dilate",temp)     temp = cv2.subtract(mask,temp)     skel = cv2.bitwise_or(skel,temp)     mask = eroded.copy()  cv2.imshow("skel",skel) #cv2.waitKey(0) 

 After the erosion and dialation

3. apply the canny to filter the lines and use HoughLinesP to get the lines

edges = cv2.Canny(skel, 50, 150) cv2.imshow("edges",edges) lines = cv2.HoughLinesP(edges,1,np.pi/180,40,minLineLength=30,maxLineGap=30) i = 0 for x1,y1,x2,y2 in lines[0]:     i+=1     cv2.line(result,(x1,y1),(x2,y2),(255,0,0),1) print i  cv2.imshow("res",result) cv2.waitKey(0) 

After Canny

I wonder after the first step of selecting certain color, the lines are with broken and noises , I would think in this step we should do something to make the broken line a complete, less noisy line, and then try to apply something to do the Canny and Hough lines, any ideas ?

5 Answers

Answers 1

I'm not sure what exactly you are asking, since there is no question in your posting.

One nice and robust technique to detect line segments is LSD (line segment detector), available in openCV since openCV 3.

Here's some simple basic C++ code, which can probably converted to python easily:

int main(int argc, char* argv[]) {     cv::Mat input = cv::imread("C:/StackOverflow/Input/parking.png");     cv::Mat gray;     cv::cvtColor(input, gray, CV_BGR2GRAY);       cv::Ptr<cv::LineSegmentDetector> det;     det = cv::createLineSegmentDetector();        cv::Mat lines;     det->detect(gray, lines);      det->drawSegments(input, lines);      cv::imshow("input", input);     cv::waitKey(0);     return 0; } 

Giving this result:

enter image description here

Which looks better for further processing than your image (no line duplicates etc.)

Answers 2

Here is my pipeline, maybe it can give you some help.

First, get the gray image and process GaussianBlur.

img = cv2.imread('src.png') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  kernel_size = 5 blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0) 

Second, process edge detection use Canny.

low_threshold = 50 high_threshold = 150 edges = cv2.Canny(blur_gray, low_threshold, high_threshold) 

Then, use HoughLinesP to get the lines. You can adjust the parameters for better performance.

rho = 1  # distance resolution in pixels of the Hough grid theta = np.pi / 180  # angular resolution in radians of the Hough grid threshold = 15  # minimum number of votes (intersections in Hough grid cell) min_line_length = 50  # minimum number of pixels making up a line max_line_gap = 20  # maximum gap in pixels between connectable line segments line_image = np.copy(img) * 0  # creating a blank to draw lines on  # Run Hough on edge detected image # Output "lines" is an array containing endpoints of detected line segments lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]),                     min_line_length, max_line_gap)  for line in lines:     for x1,y1,x2,y2 in line:     cv2.line(line_image,(x1,y1),(x2,y2),(255,0,0),5) 

Finally, draw the lines on your srcImage.

# Draw the lines on the  image lines_edges = cv2.addWeighted(img, 0.8, line_image, 1, 0) 

Here is my final performance.

Final Image:

enter image description here

Answers 3

what happens if you adjust maxLineGap or size of your erosion kernel. Alternatively, you could find the distance between lines. You would have to go though pairs of lines say ax1,ay1 to ax2,ay2 c.f. bx1,by1 to bx2,by2 you can find the point where the gradient at right angles (-1 over gradient of line) to a crosses line b. Basic school geometry and simultaneous equations, something like:

x = (ay1 - by1) / ((by2 - by1) / (bx2 - bx1) + (ax2 - ax1) / (ay2 - ay1)) # then y = by1 + x * (by2 - by1) / (bx2 - bx1) 

and compare x,y with ax1,ay1

PS you might need to add a check for the distance between ax1,ay1 and bx1,by1 as some of your lines look to be continuations of other lines and these might be eliminated by the closest point technique.

Answers 4

There are some great answers here to the first part of your question, but as for the second part (finding the line intersections) I'm not seeing a whole lot.

I'd suggest you take a look at the Bentley-Ottmann algorithm.

There are some python implementations of the algorithm here and here.

Answers 5

You can also add some intelligence to algorithm to get rid of the candidates which are not suppose to be detected as lines.. this can be done with the knowledge of physical properties of line. this might add some constraints.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment