I am trying to detect lines in parking as shown below
What I hope to get is the clear lines and (x,y) position in the crossed line, however the result is not very promising
I guess it is due to two main reasons
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)
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)
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)
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)
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:
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:
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.
0 comments:
Post a Comment