最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

OpenCV實(shí)戰(zhàn)案例之車道線識(shí)別詳解

 更新時(shí)間:2022年10月16日 13:43:21   作者:獜洛橙  
計(jì)算機(jī)視覺在自動(dòng)化系統(tǒng)觀測環(huán)境、預(yù)測該系統(tǒng)控制器輸入值等方面起著至關(guān)重要的作用,下面這篇文章主要給大家介紹了關(guān)于OpenCV實(shí)戰(zhàn)案例之車道線識(shí)別的相關(guān)資料,需要的朋友可以參考下

一、首先進(jìn)行canny邊緣檢測,為獲取車道線邊緣做準(zhǔn)備

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)

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

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

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)

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

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

概率霍夫變換函數(shù):

  • lines=cv2.HoughLinesP(image, rho,theta,threshold,minLineLength, maxLineGap)
  • image:圖像,必須是8位單通道二值圖像
  • rho:以像素為單位的距離r的精度,一般情況下是使用1
  • theta:表示搜索可能的角度,使用的精度是np.pi/180
  • threshold:閾值,該值越小,判定的直線越多,相反則直線越少
  • minLineLength:默認(rèn)為0,控制接受直線的最小長度
  • maxLineGap:控制接受共線線段的最小間隔,如果兩點(diǎn)間隔超過了參數(shù),就認(rèn)為兩點(diǎn)不在同一直線上,默認(rèn)為0
  • lines:返回值由numpy.ndarray構(gòu)成,每一對(duì)都是一對(duì)浮點(diǎn)數(shù),表示線段的兩個(gè)端點(diǎn)
import cv2
import numpy as np
 
#計(jì)算斜率
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]

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

流程:

  • 獲取所有的線段的斜率,然后計(jì)算斜率的平均值
  • 遍歷所有斜率,計(jì)算和平均斜率的差值,尋找最大的那個(gè)斜率對(duì)應(yīng)的直線,如果差值大于閾值,那么就從列表中剔除對(duì)應(yīng)的線段和斜率
  • 循環(huán)執(zhí)行操作,直到剩下的全部都是小于閾值的線段
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)

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

流程:

  • 取出所有的直線的x和y坐標(biāo),組成列表,利用np.ravel進(jìn)行將高維轉(zhuǎn)一維數(shù)組
  • 利用np.polyfit進(jìn)行直線的擬合,最終得到擬合后的直線的斜率和截距,類似y=kx+b的(k,b)
  • 最終要返回(x_min,y_min,x_max,y_max)的一個(gè)np.array的數(shù)據(jù),那么就是用np.polyval求多項(xiàng)式的值,舉個(gè)example,np.polyval([3,0,1], 5) # 3 * 5**2 + 0 * 5**1 + 1,即可以獲得對(duì)應(yīng)x坐標(biāo)的y坐標(biāo)。
def least_squares_fit(lines):
    # 1. 取出所有坐標(biāo)點(diǎn)
    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. 進(jìn)行直線擬合.得到多項(xiàng)式系數(shù)
    poly = np.polyfit(x_coords, y_coords, deg=1)
    print(poly)
    # 3. 根據(jù)多項(xiàng)式系數(shù),計(jì)算兩個(gè)直線上的點(diǎn),用于唯一確定這條直線
    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):
    """
    對(duì)gray_img進(jìn)行掩膜
    :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: 標(biāo)記邊緣的灰度圖
    """
 
    def calculate_slope(line):
        """
        計(jì)算線段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: 線段上的兩點(diǎn),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)

總結(jié)

到此這篇關(guān)于OpenCV實(shí)戰(zhàn)案例之車道線識(shí)別詳解的文章就介紹到這了,更多相關(guān)OpenCV車道線識(shí)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決python gdal投影坐標(biāo)系轉(zhuǎn)換的問題

    解決python gdal投影坐標(biāo)系轉(zhuǎn)換的問題

    今天小編就為大家分享一篇解決python gdal投影坐標(biāo)系轉(zhuǎn)換的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-01-01
  • 基于PyQt5完成的PDF拆分功能

    基于PyQt5完成的PDF拆分功能

    這篇文章主要介紹了基于PyQt5完成的PDF拆分功能,本文介紹的pdf拆分功能還有一些待完善地方,例如可增加預(yù)覽功能,實(shí)現(xiàn)每頁預(yù)覽,以及如何實(shí)現(xiàn)多條件拆分,需要的朋友可以參考下
    2022-06-06
  • Python實(shí)現(xiàn)Excel自動(dòng)分組合并單元格

    Python實(shí)現(xiàn)Excel自動(dòng)分組合并單元格

    這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)Excel自動(dòng)分組合并單元格,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-02-02
  • Python+Turtle繪制航海王草帽路飛詳解

    Python+Turtle繪制航海王草帽路飛詳解

    turtle庫是一個(gè)點(diǎn)線面的簡單圖像庫,在Python2.6之后被引入進(jìn)來,能夠完成一些比較簡單的幾何圖像可視化。本文將利用turtle繪制一個(gè)可愛的草帽路飛,感興趣的可以試一試
    2022-03-03
  • python使用chardet判斷字符串編碼的方法

    python使用chardet判斷字符串編碼的方法

    這篇文章主要介紹了python使用chardet判斷字符串編碼的方法,涉及Python編碼的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-03-03
  • python格式化字符串實(shí)例總結(jié)

    python格式化字符串實(shí)例總結(jié)

    這篇文章主要介紹了python格式化字符串的方法,實(shí)例展示了常見的幾類Python針對(duì)字符串的格式方法,非常實(shí)用,需要的朋友可以參考下
    2014-09-09
  • python畫圖時(shí)給圖中的點(diǎn)加標(biāo)簽和plt.text的使用

    python畫圖時(shí)給圖中的點(diǎn)加標(biāo)簽和plt.text的使用

    這篇文章主要介紹了python畫圖時(shí)給圖中的點(diǎn)加標(biāo)簽和plt.text的使用,利用matplotlib模塊畫各城市2019-nCoV疫情確診人數(shù)和節(jié)前流入人口數(shù)的圖的時(shí)候遇到了要給圖中的點(diǎn)加上標(biāo)簽示意,需要的朋友可以參考一下
    2022-03-03
  • Python如何通過ARIMA模型進(jìn)行時(shí)間序列分析預(yù)測

    Python如何通過ARIMA模型進(jìn)行時(shí)間序列分析預(yù)測

    這篇文章主要介紹了Python如何通過ARIMA模型進(jìn)行時(shí)間序列分析預(yù)測問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • Python創(chuàng)建簡單的神經(jīng)網(wǎng)絡(luò)實(shí)例講解

    Python創(chuàng)建簡單的神經(jīng)網(wǎng)絡(luò)實(shí)例講解

    在本篇文章里小編給大家整理的是一篇關(guān)于如何在Python中創(chuàng)建一個(gè)簡單的神經(jīng)網(wǎng)絡(luò)的相關(guān)知識(shí)點(diǎn),有興趣的朋友們可以參考下。
    2021-01-01
  • Python實(shí)現(xiàn)批量生成,重命名和刪除word文件

    Python實(shí)現(xiàn)批量生成,重命名和刪除word文件

    這篇文章主要為大家詳細(xì)介紹了Python如何利用第三方庫實(shí)現(xiàn)批量生成、重命名和刪除word文件的功能,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2023-03-03

最新評(píng)論

安吉县| 稻城县| 九江县| 云阳县| 南部县| 邵阳县| 芒康县| 红安县| 田林县| 巫山县| 仙游县| 泰州市| 葵青区| 永川市| 龙岩市| 昌吉市| 元朗区| 湖南省| 芦溪县| 巧家县| 垫江县| 巨鹿县| 沅江市| 莱芜市| 剑河县| 怀来县| 上栗县| 达州市| 高清| 奉新县| 祁连县| 织金县| 汤原县| 忻城县| 镇巴县| 肃宁县| 呼玛县| 霞浦县| 墨脱县| 化德县| 泰宁县|