How to detect lines in OpenCV?

前端 未结 4 1286
一整个雨季
一整个雨季 2020-11-28 03:46

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 no

相关标签:
4条回答
  • 2020-11-28 04:26

    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.

    0 讨论(0)
  • 2020-11-28 04:28

    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:

    0 讨论(0)
  • 2020-11-28 04:39

    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.

    Edit: Using VeraPoseidon's Houghlines implementation and the second library linked here, I've managed to get the following result for intersection detection. Credit to Vera and the library author for their good work. The green squares represent a detected intersection. There are a few errors, but this seems like a really good starting place to me. It seems as though most of the locations you actually want to detect an intersection have multiple intersections detected, so you could probably run an appropriately sized window over the image that looked for multiple intersections and deemed a true intersection as one where that window activated.

    Here is the code I used to produce that result:

    import cv2
    import numpy as np
    import isect_segments_bentley_ottmann.poly_point_isect as bot
    
    
    img = cv2.imread('parking.png')
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    
    kernel_size = 5
    blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0)
    
    low_threshold = 50
    high_threshold = 150
    edges = cv2.Canny(blur_gray, low_threshold, high_threshold)
    
    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)
    print(lines)
    points = []
    for line in lines:
        for x1, y1, x2, y2 in line:
            points.append(((x1 + 0.0, y1 + 0.0), (x2 + 0.0, y2 + 0.0)))
            cv2.line(line_image, (x1, y1), (x2, y2), (255, 0, 0), 5)
    
    lines_edges = cv2.addWeighted(img, 0.8, line_image, 1, 0)
    print(lines_edges.shape)
    #cv2.imwrite('line_parking.png', lines_edges)
    
    print points
    intersections = bot.isect_segments(points)
    print intersections
    
    for inter in intersections:
        a, b = inter
        for i in range(3):
            for j in range(3):
                lines_edges[int(b) + i, int(a) + j] = [0, 255, 0]
    
    cv2.imwrite('line_parking.png', lines_edges)
    

    You can use something like this block of code for a strategy to remove multiple intersections in a small area:

    for idx, inter in enumerate(intersections):
        a, b = inter
        match = 0
        for other_inter in intersections[idx:]:
            c, d = other_inter
            if abs(c-a) < 15 and abs(d-b) < 15:
                match = 1
                intersections[idx] = ((c+a)/2, (d+b)/2)
                intersections.remove(other_inter)
    
        if match == 0:
            intersections.remove(inter)
    

    Output image:

    You'll have to play with the windowing function though.

    0 讨论(0)
  • 2020-11-28 04:41

    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.)

    0 讨论(0)
提交回复
热议问题