亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

OpenCV怎么實現車道線識別

發布時間:2022-10-17 10:30:14 來源:億速云 閱讀:143 作者:iii 欄目:開發技術

這篇文章主要介紹“OpenCV怎么實現車道線識別”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“OpenCV怎么實現車道線識別”文章能幫助大家解決問題。

一、首先進行canny邊緣檢測,為獲取車道線邊緣做準備

import cv2
 
gray_img = cv2.imread('img.jpg',cv2.IMREAD_GRAYSCALE)
canny_img = cv2.Canny(gray_img,50,100)
cv2.imwrite('canny_img.jpg',canny_img)
cv2.imshow('canny',canny_img)
 
cv2.waitKey(0)

OpenCV怎么實現車道線識別

二、進行ROI提取獲取確切的車道線邊緣(紅色線內部)

方法:在圖像中,黑色表示0,白色為1,那么要保留矩形內的白色線,就使用邏輯與,當然前提是圖像矩形外也是0,那么就采用創建一個全0圖像,然后在矩形內全1,之后與之前的canny圖像進行與操作,即可得到需要的車道線邊緣。

OpenCV怎么實現車道線識別

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

OpenCV怎么實現車道線識別

三、利用概率霍夫變換獲取直線,并將斜率正數和復數的線段給分割開來

TIPs:使用霍夫變換需要將圖像先二值化

概率霍夫變換函數:

  • lines=cv2.HoughLinesP(image, rho,theta,threshold,minLineLength, maxLineGap)

  • image:圖像,必須是8位單通道二值圖像

  • rho:以像素為單位的距離r的精度,一般情況下是使用1

  • theta:表示搜索可能的角度,使用的精度是np.pi/180

  • threshold:閾值,該值越小,判定的直線越多,相反則直線越少

  • minLineLength:默認為0,控制接受直線的最小長度

  • maxLineGap:控制接受共線線段的最小間隔,如果兩點間隔超過了參數,就認為兩點不在同一直線上,默認為0

  • lines:返回值由numpy.ndarray構成,每一對都是一對浮點數,表示線段的兩個端點

import cv2
import numpy as np
 
#計算斜率
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 = cv2.imread('masked_edge_img.jpg', cv2.IMREAD_GRAYSCALE)
#霍夫變換獲取所有線段
lines = cv2.HoughLinesP(edge_img, 1, np.pi / 180, 15, minLineLength=40,
                        maxLineGap=20)
 
#利用斜率劃分線段
left_lines = [line for line in lines if calculate_slope(line) < 0]
right_lines = [line for line in lines if calculate_slope(line) > 0]

四、離群值過濾,剔除斜率相差過大的線段

流程:

  • 獲取所有的線段的斜率,然后計算斜率的平均值

  • 遍歷所有斜率,計算和平均斜率的差值,尋找最大的那個斜率對應的直線,如果差值大于閾值,那么就從列表中剔除對應的線段和斜率

  • 循環執行操作,直到剩下的全部都是小于閾值的線段

def reject_abnormal_lines(lines, threshold):
    slopes = [calculate_slope(line) for line in lines]
    while len(lines) > 0:
        mean = np.mean(slopes)
        diff = [abs(s - mean) for s in slopes]
        idx = np.argmax(diff)
        if diff[idx] > threshold:
            slopes.pop(idx)
            lines.pop(idx)
        else:
            break
    return lines
 
reject_abnormal_lines(left_lines, threshold=0.2)
reject_abnormal_lines(right_lines, threshold=0.2)

五、最小二乘擬合,實現將左邊和右邊的線段互相擬合成一條直線,形成車道線

流程:

  • 取出所有的直線的x和y坐標,組成列表,利用np.ravel進行將高維轉一維數組

  • 利用np.polyfit進行直線的擬合,最終得到擬合后的直線的斜率和截距,類似y=kx+b的(k,b)

  • 最終要返回(x_min,y_min,x_max,y_max)的一個np.array的數據,那么就是用np.polyval求多項式的值,舉個example,np.polyval([3,0,1], 5) # 3 * 5**2 + 0 * 5**1 + 1,即可以獲得對應x坐標的y坐標。

def least_squares_fit(lines):
    # 1. 取出所有坐標點
    x_coords = np.ravel([[line[0][0], line[0][2]] for line in lines])
    y_coords = np.ravel([[line[0][1], line[0][3]] for line in lines])
 
    # 2. 進行直線擬合.得到多項式系數
    poly = np.polyfit(x_coords, y_coords, deg=1)
    print(poly)
    # 3. 根據多項式系數,計算兩個直線上的點,用于唯一確定這條直線
    point_min = (np.min(x_coords), np.polyval(poly, np.min(x_coords)))
    point_max = (np.max(x_coords), np.polyval(poly, np.max(x_coords)))
    return np.array([point_min, point_max], dtype=np.int)
 
print("left lane")
print(least_squares_fit(left_lines))
print("right lane")
print(least_squares_fit(right_lines))

六、繪制線段

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

全部代碼

import cv2
import numpy as np
 
def get_edge_img(color_img, gaussian_ksize=5, gaussian_sigmax=1,
                 canny_threshold1=50, canny_threshold2=100):
    """
    灰度化,模糊,canny變換,提取邊緣
    :param color_img: 彩色圖,channels=3
    """
    gaussian = cv2.GaussianBlur(color_img, (gaussian_ksize, gaussian_ksize),
                                gaussian_sigmax)
    gray_img = cv2.cvtColor(gaussian, cv2.COLOR_BGR2GRAY)
    edges_img = cv2.Canny(gray_img, canny_threshold1, canny_threshold2)
    return edges_img
 
def roi_mask(gray_img):
    """
    對gray_img進行掩膜
    :param gray_img: 灰度圖,channels=1
    """
    poly_pts = np.array([[[0, 368], [300, 210], [340, 210], [640, 368]]])
    mask = np.zeros_like(gray_img)
    mask = cv2.fillPoly(mask, pts=poly_pts, color=255)
    img_mask = cv2.bitwise_and(gray_img, mask)
    return img_mask
 
 
def get_lines(edge_img):
    """
    獲取edge_img中的所有線段
    :param edge_img: 標記邊緣的灰度圖
    """
 
    def calculate_slope(line):
        """
        計算線段line的斜率
        :param line: np.array([[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):
        """
        剔除斜率不一致的線段
        :param lines: 線段集合, [np.array([[x_1, y_1, x_2, y_2]]),np.array([[x_1, y_1, x_2, y_2]]),...,np.array([[x_1, y_1, x_2, y_2]])]
        """
        slopes = [calculate_slope(line) for line in lines]
        while len(lines) > 0:
            mean = np.mean(slopes)
            diff = [abs(s - mean) for s in slopes]
            idx = np.argmax(diff)
            if diff[idx] > threshold:
                slopes.pop(idx)
                lines.pop(idx)
            else:
                break
        return lines
 
    def least_squares_fit(lines):
        """
        將lines中的線段擬合成一條線段
        :param lines: 線段集合, [np.array([[x_1, y_1, x_2, y_2]]),np.array([[x_1, y_1, x_2, y_2]]),...,np.array([[x_1, y_1, x_2, y_2]])]
        :return: 線段上的兩點,np.array([[xmin, ymin], [xmax, ymax]])
        """
        x_coords = np.ravel([[line[0][0], line[0][2]] for line in lines])
        y_coords = np.ravel([[line[0][1], line[0][3]] for line in lines])
        poly = np.polyfit(x_coords, y_coords, deg=1)
        point_min = (np.min(x_coords), np.polyval(poly, np.min(x_coords)))
        point_max = (np.max(x_coords), np.polyval(poly, np.max(x_coords)))
        return np.array([point_min, point_max], dtype=np.int)
 
    # 獲取所有線段
    lines = cv2.HoughLinesP(edge_img, 1, np.pi / 180, 15, minLineLength=40,
                            maxLineGap=20)
    # 按照斜率分成車道線
    left_lines = [line for line in lines if calculate_slope(line) > 0]
    right_lines = [line for line in lines if calculate_slope(line) < 0]
    # 剔除離群線段
    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
    cv2.line(img, tuple(left_line[0]), tuple(left_line[1]), color=(0, 255, 255),
             thickness=5)
    cv2.line(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 = cv2.VideoCapture('video.mp4')
while True:
    ret, frame = capture.read()
    if not ret:
        break
    frame = show_lane(frame)
    cv2.imshow('frame', frame)
    cv2.waitKey(10)

關于“OpenCV怎么實現車道線識別”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

兴文县| 乌什县| 阳高县| 扶余县| 江源县| 荥阳市| 新郑市| 射洪县| 即墨市| 双鸭山市| 新津县| 镇平县| 海宁市| 调兵山市| 泸定县| 湘阴县| 同心县| 长丰县| 丽江市| 垦利县| 得荣县| 富蕴县| 广丰县| 新野县| 秭归县| 开阳县| 澄迈县| 囊谦县| 九寨沟县| 建平县| 尚志市| 乌拉特中旗| 长沙县| 青田县| 常宁市| 钦州市| 玛多县| 乐亭县| 银川市| 修武县| 巴楚县|