SoFunction
Updated on 2024-10-30

OpenCV practical cases of lane line recognition details

I. First canny edge detection is performed to prepare for obtaining lane line edges

import cv2
 
gray_img = ('',cv2.IMREAD_GRAYSCALE)
canny_img = (gray_img,50,100)
('canny_img.jpg',canny_img)
('canny',canny_img)
 
(0)

II. perform ROI extraction to obtain the exact lane line edges (inside the red line)

Method: In the image, black means 0, white is 1, then to keep the white line inside the rectangle, use logical and, of course, provided that the image outside the rectangle is also 0, then use to create an all 0 image, and then in the rectangle of all 1, and after that with the previous canny image with the operation, you can get the desired edge of the lane line.

import cv2
import numpy as np
 
canny_img = ('canny_img.jpg',cv2.IMREAD_GRAYSCALE)
roi = np.zeros_like(canny_img)
roi = (roi,([[[0, 368],[300, 210], [340, 210], [640, 368]]]),color=255)
roi_img = cv2.bitwise_and(canny_img, roi)
('roi_img.jpg',roi_img)
('roi_img',roi_img)
(0)

III. use probabilistic Hough transformations to obtain straight lines and give splits to lines with positive and complex slopes

TIPs: using the Hough transform requires binarizing the image first

Probabilistic Hough transform function:

  • lines=(image, rho,theta,threshold,minLineLength, maxLineGap)
  • image: image, must be an 8-bit single-channel binary image
  • rho: the precision of the distance r in pixels, typically 1 is used
  • theta: indicates the possible angles to search for, the precision used is /180
  • threshold: the smaller the value, the more straight lines will be determined, on the contrary, the less straight lines will be determined.
  • minLineLength: defaults to 0, controls the minimum length of a line to be accepted.
  • maxLineGap: control to accept the minimum interval of the common line segment, if the interval between two points exceeds the parameter, it is considered that the two points are not in the same straight line, the default is 0
  • lines: the return value consists of a pair of floating-point numbers, each of which represents the two endpoints of the line.
import cv2
import numpy as np
 
# Calculate the slope
def calculate_slope(line):
    x_1, y_1, x_2, y_2 = line[0]
    return (y_2 - y_1) / (x_2 - x_1)
 
edge_img = ('masked_edge_img.jpg', cv2.IMREAD_GRAYSCALE)
# Hough transform to get all line segments
lines = (edge_img, 1,  / 180, 15, minLineLength=40,
                        maxLineGap=20)
 
#Dividing line segments using slope
left_lines = [line for line in lines if calculate_slope(line) < 0]
right_lines = [line for line in lines if calculate_slope(line) > 0]

IV. Outlier filtering, eliminating line segments with too large a difference in slope

Process:

  • Get the slopes of all the line segments, then calculate the average of the slopes
  • Iterate through all the slopes, calculate the difference with the average slope, find the line corresponding to the largest one, if the difference is larger than the threshold, then eliminate the corresponding line segment and slope from the list
  • Loop through the operation until all that remain are line segments smaller than the threshold
def reject_abnormal_lines(lines, threshold):
    slopes = [calculate_slope(line) for line in lines]
    while len(lines) > 0:
        mean = (slopes)
        diff = [abs(s - mean) for s in slopes]
        idx = (diff)
        if diff[idx] > threshold:
            (idx)
            (idx)
        else:
            break
    return lines
 
reject_abnormal_lines(left_lines, threshold=0.2)
reject_abnormal_lines(right_lines, threshold=0.2)

V. Least squares fitting, realizing that the left and right line segments are fitted to each other to form a straight line, forming a lane line

Process:

  • Take the x and y coordinates of all the straight lines, form a list, and use it to convert the high-dimensional to one-dimensional arrays
  • Use to perform a fit to a straight line and end up with the slope and intercept of the fitted line, similar to (k,b) for y=kx+b
  • Ultimately to return (x_min,y_min,x_max,y_max) one of the data, then it is used to find the value of the polynomial, to give an example, ([3,0,1], 5) # 3 * 5 * * 2 + 0 * 5 * * 1 + 1, that is, you can get the corresponding x coordinate of the y coordinate.
def least_squares_fit(lines):
    # 1. Take out all coordinate points
    x_coords = ([[line[0][0], line[0][2]] for line in lines])
    y_coords = ([[line[0][1], line[0][3]] for line in lines])
 
    # 2. Perform straight line fitting. Obtain polynomial coefficients
    poly = (x_coords, y_coords, deg=1)
    print(poly)
    # 3. Calculation of two points on a line, based on polynomial coefficients, used to uniquely determine the line
    point_min = ((x_coords), (poly, (x_coords)))
    point_max = ((x_coords), (poly, (x_coords)))
    return ([point_min, point_max], dtype=)
 
print("left lane")
print(least_squares_fit(left_lines))
print("right lane")
print(least_squares_fit(right_lines))

VI. Drawing line segments

(img, tuple(left_line[0]), tuple(left_line[1]), color=(0, 255, 255), thickness=5)
(img, tuple(right_line[0]), tuple(right_line[1]), color=(0, 255, 255), thickness=5)

All codes (video display)

import cv2
import numpy as np
 
def get_edge_img(color_img, gaussian_ksize=5, gaussian_sigmax=1,
                 canny_threshold1=50, canny_threshold2=100):
    """
    grayscale,blurred,cannya transformation,Extraction Edge
    :param color_img: color chart,channels=3
    """
    gaussian = (color_img, (gaussian_ksize, gaussian_ksize),
                                gaussian_sigmax)
    gray_img = (gaussian, cv2.COLOR_BGR2GRAY)
    edges_img = (gray_img, canny_threshold1, canny_threshold2)
    return edges_img
 
def roi_mask(gray_img):
    """
    treat (sb a certain way)gray_imgmask
    :param gray_img: grayscale image,channels=1
    """
    poly_pts = ([[[0, 368], [300, 210], [340, 210], [640, 368]]])
    mask = np.zeros_like(gray_img)
    mask = (mask, pts=poly_pts, color=255)
    img_mask = cv2.bitwise_and(gray_img, mask)
    return img_mask
 
 
def get_lines(edge_img):
    """
    Get all line segments in edge_img
    :param edge_img: grayscale map of marker edges
    """
 
    def calculate_slope(line):
        """
        Calculate the line segmentlineslope
        :param line: ([[x_1, y_1, x_2, y_2]])
        :return:
        """
        x_1, y_1, x_2, y_2 = line[0]
        return (y_2 - y_1) / (x_2 - x_1)
 
    def reject_abnormal_lines(lines, threshold=0.2):
        """
        Excluding line segments with inconsistent slopes
        :param lines: set of line segments, [([[x_1, y_1, x_2, y_2]]),([[x_1, y_1, x_2, y_2]]),...,([[x_1, y_1, x_2, y_2]])]
        """
        slopes = [calculate_slope(line) for line in lines]
        while len(lines) > 0:
            mean = (slopes)
            diff = [abs(s - mean) for s in slopes]
            idx = (diff)
            if diff[idx] > threshold:
                (idx)
                (idx)
            else:
                break
        return lines
 
    def least_squares_fit(lines):
        """
        commander-in-chief (military)linesThe line segments in are fitted to a line segment
        :param lines: set of line segments, [([[x_1, y_1, x_2, y_2]]),([[x_1, y_1, x_2, y_2]]),...,([[x_1, y_1, x_2, y_2]])]
        :return: Two points on a line segment,([[xmin, ymin], [xmax, ymax]])
        """
        x_coords = ([[line[0][0], line[0][2]] for line in lines])
        y_coords = ([[line[0][1], line[0][3]] for line in lines])
        poly = (x_coords, y_coords, deg=1)
        point_min = ((x_coords), (poly, (x_coords)))
        point_max = ((x_coords), (poly, (x_coords)))
        return ([point_min, point_max], dtype=)
 
    # Get all line segments
    lines = (edge_img, 1,  / 180, 15, minLineLength=40,
                            maxLineGap=20)
    # Split into lane lines according to slope
    left_lines = [line for line in lines if calculate_slope(line) > 0]
    right_lines = [line for line in lines if calculate_slope(line) < 0]
    # Culling outliers
    left_lines = reject_abnormal_lines(left_lines)
    right_lines = reject_abnormal_lines(right_lines)
 
    return least_squares_fit(left_lines), least_squares_fit(right_lines)
 
def draw_lines(img, lines):
    left_line, right_line = lines
    (img, tuple(left_line[0]), tuple(left_line[1]), color=(0, 255, 255),
             thickness=5)
    (img, tuple(right_line[0]), tuple(right_line[1]),
             color=(0, 255, 255), thickness=5)
 
def show_lane(color_img):
    edge_img = get_edge_img(color_img)
    mask_gray_img = roi_mask(edge_img)
    lines = get_lines(mask_gray_img)
    draw_lines(color_img, lines)
    return color_img
 
capture = ('video.mp4')
while True:
    ret, frame = ()
    if not ret:
        break
    frame = show_lane(frame)
    ('frame', frame)
    (10)

summarize

To this OpenCV practical cases of lane line recognition detailed article is introduced to this, more related OpenCV lane line recognition content, please search for my previous articles or continue to browse the following related articles I hope that you will support me more in the future!