Python基于YOLOv8和OpenCV實(shí)現(xiàn)車道線和車輛檢測(cè)功能
使用YOLOv8(You Only Look Once)和OpenCV實(shí)現(xiàn)車道線和車輛檢測(cè),目標(biāo)是創(chuàng)建一個(gè)可以檢測(cè)道路上的車道并識(shí)別車輛的系統(tǒng),并估計(jì)它們與攝像頭的距離。該項(xiàng)目結(jié)合了計(jì)算機(jī)視覺技術(shù)和深度學(xué)習(xí)物體檢測(cè)。
1、系統(tǒng)主要功能
- 車道檢測(cè):使用邊緣檢測(cè)和霍夫線變換檢測(cè)道路車道。
- 汽車檢測(cè):使用 YOLOv8 模型識(shí)別汽車并在汽車周圍繪制邊界框。
- 距離估計(jì):使用邊界框大小計(jì)算檢測(cè)到的汽車與攝像頭的距離。
2、環(huán)境要求
- OpenCV:用于圖像處理和車道檢測(cè)。
- Ultralytics YOLOv8:用于車輛檢測(cè)。
- NumPy:用于數(shù)組操作。
pip install opencv-python-headless numpy ultralytics
opencv-python 和 opencv-python-headless 區(qū)別是 OpenCV 的 Python 包,主要區(qū)別在于是否包含 GUI 相關(guān)的功能。
opencv-python
- 包含 GUI 功能:支持窗口顯示、鼠標(biāo)事件等圖形界面操作。
- 依賴:需要 GUI 庫(如 GTK、Qt)支持。
- 適用場(chǎng)景:適用于需要顯示圖像或與用戶交互的環(huán)境,如桌面應(yīng)用。
opencv-python-headless
- 不包含 GUI 功能:去除了窗口顯示和用戶交互功能。
- 依賴:無需 GUI 庫,適合無圖形界面的環(huán)境。
- 適用場(chǎng)景:適用于服務(wù)器或無圖形界面的環(huán)境,如遠(yuǎn)程服務(wù)器、Docker 容器。
3、代碼
import cv2
import numpy as np
import math
import time
from ultralytics import YOLO # YOLOv8 module
# Function to mask out the region of interest
def region_of_interest(img, vertices):
mask = np.zeros_like(img)
match_mask_color = 255
cv2.fillPoly(mask, vertices, match_mask_color)
masked_image = cv2.bitwise_and(img, mask)
return masked_image
# Function to draw the filled polygon between the lane lines
def draw_lane_lines(img, left_line, right_line, color=[0, 255, 0], thickness=10):
line_img = np.zeros_like(img)
poly_pts = np.array([[
(left_line[0], left_line[1]),
(left_line[2], left_line[3]),
(right_line[2], right_line[3]),
(right_line[0], right_line[1])
]], dtype=np.int32)
# Fill the polygon between the lines
cv2.fillPoly(line_img, poly_pts, color)
# Overlay the polygon onto the original image
img = cv2.addWeighted(img, 0.8, line_img, 0.5, 0.0)
return img
# The lane detection pipeline
def pipeline(image):
height = image.shape[0]
width = image.shape[1]
region_of_interest_vertices = [
(0, height),
(width / 2, height / 2),
(width, height),
]
# Convert to grayscale and apply Canny edge detection
gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
cannyed_image = cv2.Canny(gray_image, 100, 200)
# Mask out the region of interest
cropped_image = region_of_interest(
cannyed_image,
np.array([region_of_interest_vertices], np.int32)
)
# Perform Hough Line Transformation to detect lines
lines = cv2.HoughLinesP(
cropped_image,
rho=6,
theta=np.pi / 60,
threshold=160,
lines=np.array([]),
minLineLength=40,
maxLineGap=25
)
# Separating left and right lines based on slope
left_line_x = []
left_line_y = []
right_line_x = []
right_line_y = []
if lines is None:
return image
for line in lines:
for x1, y1, x2, y2 in line:
slope = (y2 - y1) / (x2 - x1) if (x2 - x1) != 0 else 0
if math.fabs(slope) < 0.5: # Ignore nearly horizontal lines
continue
if slope <= 0: # Left lane
left_line_x.extend([x1, x2])
left_line_y.extend([y1, y2])
else: # Right lane
right_line_x.extend([x1, x2])
right_line_y.extend([y1, y2])
# Fit a linear polynomial to the left and right lines
min_y = int(image.shape[0] * (3 / 5)) # Slightly below the middle of the image
max_y = image.shape[0] # Bottom of the image
if left_line_x and left_line_y:
poly_left = np.poly1d(np.polyfit(left_line_y, left_line_x, deg=1))
left_x_start = int(poly_left(max_y))
left_x_end = int(poly_left(min_y))
else:
left_x_start, left_x_end = 0, 0 # Defaults if no lines detected
if right_line_x and right_line_y:
poly_right = np.poly1d(np.polyfit(right_line_y, right_line_x, deg=1))
right_x_start = int(poly_right(max_y))
right_x_end = int(poly_right(min_y))
else:
right_x_start, right_x_end = 0, 0 # Defaults if no lines detected
# Create the filled polygon between the left and right lane lines
lane_image = draw_lane_lines(
image,
[left_x_start, max_y, left_x_end, min_y],
[right_x_start, max_y, right_x_end, min_y]
)
return lane_image
# Function to estimate distance based on bounding box size
def estimate_distance(bbox_width, bbox_height):
# For simplicity, assume the distance is inversely proportional to the box size
# This is a basic estimation, you may use camera calibration for more accuracy
focal_length = 1000 # Example focal length, modify based on camera setup
known_width = 2.0 # Approximate width of the car (in meters)
distance = (known_width * focal_length) / bbox_width # Basic distance estimation
return distance
# Main function to read and process video with YOLOv8
def process_video():
# Load the YOLOv8 model
model = YOLO('weights/yolov8n.pt')
# 或者加載官方模型
# model = YOLO("yolov8n.pt") # load an official model
# Open the video file
cap = cv2.VideoCapture('video/video.mp4')
# Check if video opened successfully
if not cap.isOpened():
print("Error: Unable to open video file.")
return
# Set the desired frame rate
target_fps = 30
frame_time = 1.0 / target_fps # Time per frame to maintain 30fps
# Resize to 720p (1280x720)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
# Loop through each frame
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# Resize frame to 720p
resized_frame = cv2.resize(frame, (1280, 720))
# Run the lane detection pipeline
lane_frame = pipeline(resized_frame)
# Run YOLOv8 to detect cars in the current frame
results = model(resized_frame)
# Process the detections from YOLOv8
for result in results:
boxes = result.boxes
for box in boxes:
x1, y1, x2, y2 = map(int, box.xyxy[0]) # Bounding box coordinates
conf = box.conf[0] # Confidence score
cls = int(box.cls[0]) # Class ID
# Only draw bounding boxes for cars with confidence >= 0.5
if model.names[cls] == 'car' and conf >= 0.5:
label = f'{model.names[cls]} {conf:.2f}'
# Draw the bounding box
cv2.rectangle(lane_frame, (x1, y1), (x2, y2), (0, 255, 255), 2)
cv2.putText(lane_frame, label, (x1, y1 - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 2)
# Estimate the distance of the car
bbox_width = x2 - x1
bbox_height = y2 - y1
distance = estimate_distance(bbox_width, bbox_height)
# Display the estimated distance
distance_label = f'Distance: {distance:.2f}m'
cv2.putText(lane_frame, distance_label, (x1, y2 + 20),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
# Display the resulting frame with both lane detection and car detection
cv2.imshow('Lane and Car Detection', lane_frame)
# Limit the frame rate to 30fps
time.sleep(frame_time)
# Break the loop when 'q' is pressed
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Release video capture and close windows
cap.release()
cv2.destroyAllWindows()
# Run the video processing function
process_video()4、工作原理
4.1 車道線檢測(cè) Pipeline
車道線檢測(cè)包括一下幾個(gè)步驟:
Step 1: 屏蔽感興趣區(qū)域(ROI)
只處理圖像的下半部分(車道線通常是可見的)。
def region_of_interest(img, vertices):
mask = np.zeros_like(img)
match_mask_color = 255
cv2.fillPoly(mask, vertices, match_mask_color)
masked_image = cv2.bitwise_and(img, mask)
return masked_imageStep 2: 使用Canny進(jìn)行邊緣檢測(cè)
將圖像轉(zhuǎn)換為灰度,并應(yīng)用Canny邊緣檢測(cè)來突出顯示邊緣。
gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) cannyed_image = cv2.Canny(gray_image, 100, 200)
Step 3: 霍夫線變換
霍夫線變換用于檢測(cè)當(dāng)前車道的線段。
lines = cv2.HoughLinesP(
cropped_image,
rho=6,
theta=np.pi / 60,
threshold=160,
lines=np.array([]),
minLineLength=40,
maxLineGap=25
)4.2 使用YOLOv8進(jìn)行車輛檢測(cè)
Step 1: 加載YOLOv8模型
我們使用預(yù)訓(xùn)練的YOLOv8模型來檢測(cè)每一幀中的汽車(或者使用官方提供的模型)。
from ultralytics import YOLO
model = YOLO('weights/yolov8n.pt')
# model = YOLO('yolov8n.pt') #官方提供的模型Step 2: 繪制邊界框
對(duì)于每一輛檢測(cè)到的汽車,繪制邊界框,并顯示類名(汽車)和置信度分?jǐn)?shù)。
for box in boxes:
x1, y1, x2, y2 = map(int, box.xyxy[0])
conf = box.conf[0]
if model.names[cls] == 'car' and conf >= 0.5:
label = f'{model.names[cls]} {conf:.2f}'
cv2.rectangle(lane_frame, (x1, y1), (x2, y2), (0, 255, 255), 2)
cv2.putText(lane_frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 2)Step 3:. 距離估計(jì)
根據(jù)邊界框的大小估計(jì)到每輛檢測(cè)到的汽車的距離。
def estimate_distance(bbox_width, bbox_height):
focal_length = 1000 # Example focal length
known_width = 2.0 # Approximate width of a car (in meters)
distance = (known_width * focal_length) / bbox_width
return distanceStep 4:. 視頻處理 Pipeline
將車道檢測(cè)、車輛檢測(cè)和距離估計(jì)結(jié)合到一個(gè)實(shí)時(shí)視頻處理pipeline中。
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
lane_frame = pipeline(resized_frame)
results = model(resized_frame)
for result in results:
# Draw bounding boxes and estimate distance
cv2.imshow('Lane and Car Detection', lane_frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break5、結(jié)果

項(xiàng)目源碼地址: https://github.com/CityIsBetter/Lane_Detection
到此這篇關(guān)于Python基于YOLOv8和OpenCV實(shí)現(xiàn)車道線和車輛檢測(cè)的文章就介紹到這了,更多相關(guān)Python YOLOv8和OpenCV車道線檢測(cè)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python光學(xué)仿真實(shí)現(xiàn)光線追跡折射與反射的實(shí)現(xiàn)
這篇文章主要為大家介紹了python光學(xué)仿真實(shí)現(xiàn)光線追跡折射與反射的實(shí)現(xiàn)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-10-10
Python獲取中國節(jié)假日數(shù)據(jù)記錄入JSON文件
項(xiàng)目系統(tǒng)內(nèi)置的日歷應(yīng)用為了提升用戶體驗(yàn),特別設(shè)置了在調(diào)休日期顯示“休”的UI圖標(biāo)功能,那么問題是這些調(diào)休數(shù)據(jù)從哪里來呢?我嘗試一種更為智能的方法:Python獲取中國節(jié)假日數(shù)據(jù)記錄入JSON文件2025-04-04
Python的Pandas時(shí)序數(shù)據(jù)詳解
這篇文章主要為大家詳細(xì)介紹了Pandas時(shí)序數(shù)據(jù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03
Python多線程應(yīng)用中的卡死問題優(yōu)化方案指南
在利用Python語言開發(fā)某查詢軟件時(shí),遇到了點(diǎn)擊搜索按鈕后軟件卡死的問題,本文將簡單分析一下出現(xiàn)的原因以及對(duì)應(yīng)的優(yōu)化方案,希望對(duì)大家有所幫助2025-08-08
pyCharm 實(shí)現(xiàn)關(guān)閉代碼檢查
這篇文章主要介紹了pyCharm 實(shí)現(xiàn)關(guān)閉代碼檢查,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-06-06
使用Python實(shí)現(xiàn)多功能課堂點(diǎn)名器與抽簽工具
這篇文章主要為大家詳細(xì)介紹了如何使用Python實(shí)現(xiàn)多功能課堂點(diǎn)名器,也可以用作抽簽工具,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02
python獲取服務(wù)器響應(yīng)cookie的實(shí)例
今天小編就為大家分享一篇python獲取服務(wù)器響應(yīng)cookie的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-12-12
python開發(fā)實(shí)時(shí)可視化儀表盤的示例
這篇文章主要介紹了python開發(fā)實(shí)時(shí)可視化儀表盤的示例,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下2021-05-05

