Python基于YOLOv8和OpenCV实现车道线和车辆检测

使用YOLOv8(You Only Look Once)和OpenCV实现车道线和车辆检测,目标是创建一个可以检测道路上的车道并识别车辆的系统,并估计它们与摄像头的距离。该项目结合了计算机视觉技术和深度学习物体检测。

1、系统主要功能

  • 车道检测:使用边缘检测和霍夫线变换检测道路车道。
  • 汽车检测:使用 YOLOv8 模型识别汽车并在汽车周围绘制边界框。
  • 距离估计:使用边界框大小计算检测到的汽车与摄像头的距离。

2、环境要求

  • OpenCV:用于图像处理和车道检测。
  • Ultralytics YOLOv8:用于车辆检测。
  • NumPy:用于数组操作。
pip install opencv-python-headless numpy ultralytics

opencv-pythonopencv-python-headless 区别是 OpenCV 的 Python 包,主要区别在于是否包含 GUI 相关的功能。

opencv-python
  • 包含 GUI 功能:支持窗口显示、鼠标事件等图形界面操作。
  • 依赖:需要 GUI 库(如 GTK、Qt)支持。
  • 适用场景:适用于需要显示图像或与用户交互的环境,如桌面应用。
opencv-python-headless
  • 不包含 GUI 功能:去除了窗口显示和用户交互功能。
  • 依赖:无需 GUI 库,适合无图形界面的环境。
  • 适用场景:适用于服务器或无图形界面的环境,如远程服务器、Docker 容器。
选择建议
  • 如果需要显示图像或与用户交互,选择 opencv-python
  • 如果仅需图像处理且无图形界面需求,选择 opencv-python-headless

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 车道线检测 Pipeline

车道线检测包括一下几个步骤:

Step 1: 屏蔽感兴趣区域(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_image

Step 2: 使用Canny进行边缘检测
将图像转换为灰度,并应用Canny边缘检测来突出显示边缘。

gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
cannyed_image = cv2.Canny(gray_image, 100, 200)

Step 3: 霍夫线变换
霍夫线变换用于检测当前车道的线段。

lines = cv2.HoughLinesP(
    cropped_image,
    rho=6,
    theta=np.pi / 60,
    threshold=160,
    lines=np.array([]),
    minLineLength=40,
    maxLineGap=25
)

4.2 使用YOLOv8进行车辆检测

Step 1: 加载YOLOv8模型
我们使用预训练的YOLOv8模型来检测每一帧中的汽车(或者使用官方提供的模型)。

from ultralytics import YOLO
model = YOLO('weights/yolov8n.pt')
# model = YOLO('yolov8n.pt') #官方提供的模型

Step 2: 绘制边界框
对于每一辆检测到的汽车,绘制边界框,并显示类名(汽车)和置信度分数。

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:. 距离估计
根据边界框的大小估计到每辆检测到的汽车的距离。

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 distance

Step 4:. 视频处理 Pipeline
将车道检测、车辆检测和距离估计结合到一个实时视频处理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'):
        break

5、结果

在这里插入图片描述

  • 项目源码地址: https://github.com/CityIsBetter/Lane_Detection

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/951489.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【算法】查找与排序

因文章篇幅有限&#xff0c;查找和排序分开写&#xff08;附代码与详细过程 注释详解&#xff09;&#xff0c;这篇文章主讲算法中的数据查找。 查找是数据结构中最基本的操作之一&#xff0c;用于从给定的数据集合中找到特定的目标数据。查找的效率直接影响程序的性能&#…

Linux环境中对Postgrel数据库的安装与配置

一、环境准备 linux操作系统的环境是centos7; Postgrel数据库的版本是12.0&#xff0c;不同版本的下载渠道如下&#xff08;PostgreSQL: File Browser&#xff09;&#xff1a; 可以看到压缩包是比较小的&#xff1b;下载之后&#xff0c;上传到你的linux环境中即可。 二、安…

基于vue的商城小程序的毕业设计与实现(源码及报告)

环境搭建 ☞☞☞ ​​​Vue入手篇(一)&#xff0c;防踩雷(全网最详细教程)_vue force-CSDN博客 目录 一、功能介绍 二、登录注册功能 三、首页 四、项目截图 五、源码获取 一、功能介绍 用户信息展示&#xff1a;页面顶部设有用户头像和昵称展示区&#xff0c;方便用户识别…

单元测试概述入门

引入 什么是测试&#xff1f;测试的阶段划分&#xff1f; 测试方法有哪些&#xff1f; 1.什么是单元测试&#xff1f; 单元测试&#xff1a;就是针对最小的功能单元&#xff08;方法&#xff09;&#xff0c;编写测试代码对其正确性进行测试。 2.为什么要引入单元测试&#x…

Springboot3巧妙运用拦截器阻断xss攻击

Springboot3巧妙运用拦截器阻断xss攻击 什么是xss跨站脚本攻击类型简单示例解决方法拦截器代码使用demo 什么是xss 人们经常将跨站脚本攻击&#xff08;Cross Site Scripting&#xff09;缩写为CSS&#xff0c;但这会与层叠样式表&#xff08;Cascading Style Sheets&#xff…

DAY39|动态规划Part07|LeetCode:198.打家劫舍、213.打家劫舍II、337.打家劫舍III

目录 LeetCode:198.打家劫舍 基本思路 C代码 LeetCode:213.打家劫舍II 基本思路 C代码 LeetCode:337.打家劫舍III 基本思路 C代码 LeetCode:198.打家劫舍 力扣题目链接 文字讲解&#xff1a;LeetCode:198.打家劫舍 视频讲解&#xff1a;动态规划&#xff0c;偷不偷这个…

数据结构——栈的实现

今天&#xff0c;我们来写一下关于栈的博文。 1.首先我们先了解一下什么是栈&#xff1f; 一&#xff1a;概念&#xff1a; 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端称为栈顶&#xff0c;另…

uniapp 的uni.getRecorderManager() 录音功能小记

官网上明确说的是全局唯一并且只是获取对象&#xff0c;所以会导致一个问题就是&#xff0c;当你多个页面要用到这个对象的时候&#xff0c;会发现 onStop 方法会被覆盖&#xff0c;导致调用结果不是自己想要的 解决办法也简单粗暴&#xff0c;在需要用到的界面重新覆盖onStop…

Unity:删除注册表内的项目记录

然后WinR按键输入regedit 打开注册表 在注册表 HKEY CURRENT USER—>SOFTWARE—>Unity—>UnityEditor—>DefaultCompany —>language_Test 中&#xff0c;删除我们的之前存储的语言环境数据。在 “ 三、文本调用和替换 ” 测试时已经将语言环境存储到注册表中了…

标准应用 | 2025年网络安全服务成本度量实施参考

01 网络安全服务成本度量依据相关新变化 为了解决我国网络安全服务产业发展中面临的服务供需两方对于服务成本组成认知偏差较大、网络安全服务成本度量缺乏依据的问题&#xff0c;中国网络安全产业联盟&#xff08;CCIA&#xff09;组织北京赛西科技发展有限责任公司、北京安…

微信小程序map组件所有markers展示在视野范围内

注意&#xff1a;使用include-points属性不生效&#xff0c;要通过createMapContext实现 <template><view class"map-box"><map id"map" class"map" :markers"markers" :enable-traffic"true" :enable-poi&…

PLC实现HTTP协议JSON格式数据上报对接的参数配置说明

IGT-SER系列PLC通讯智能网关支持HTTP协议GET和POST、PUT请求模式。支持JSON格式的文件&#xff0c;也可以实现WebService的调用。 通常智能网关是HTTP协议的客户端&#xff0c;也可以同时作为HTTP的服务端。相关案例 作为客户端时支持触发、周期、混合等多种工…

微信小程序——创建滑动颜色条

在微信小程序中&#xff0c;你可以使用 slider 组件来创建一个颜色滑动条。以下是一个简单的示例&#xff0c;展示了如何实现一个颜色滑动条&#xff0c;该滑动条会根据滑动位置改变背景颜色。 步骤一&#xff1a;创建小程序项目 首先&#xff0c;使用微信开发者工具创建一个新…

Improving Language Understanding by Generative Pre-Training GPT-1详细讲解

Improving Language Understanding by Generative Pre-Training 2018.06 GPT-1 0.有监督、半监督、无监督 CV&#xff1a;ImageNet pre-trained model NLP&#xff1a;pre-trained model? 在计算机视觉中任务包含分类、检测、分割&#xff0c;任务类别数少&#xff0c;对应…

sql server cdc漏扫数据

SQL Server的CDC指的是“变更数据捕获”&#xff08;Change Data Capture&#xff09;。这是SQL Server数据库提供的一项功能&#xff0c;能够跟踪并记录对数据库表中数据所做的更改。这些更改包括插入、更新和删除操作。CDC可以捕获这些变更的详细信息&#xff0c;并使这些信息…

如何在 Ubuntu 22.04 上安装 Caddy Web 服务器教程

简介 Caddy 是一个开源的 Web 服务器&#xff0c;它支持静态和现代 Web 应用程序&#xff0c;使用预定义的配置规则&#xff0c;并为所有链接的域名自动启用 HTTPS。Caddy 使用 GO 语言编写&#xff0c;提供了用户友好的配置指令&#xff0c;使你既可以将其用作 Web 服务器&am…

《机器学习》——贝叶斯算法

贝叶斯简介 贝叶斯公式&#xff0c;又称贝叶斯定理、贝叶斯法则&#xff0c;最初是用来描述两个事件的条件概率间的关系的公式&#xff0c;后来被人们发现具有很深刻的实际意义和应用价值。该公式的实际内涵是&#xff0c;支持某项属性的事件发生得愈多&#xff0c;则该属性成…

边缘计算网关在机床设备数据采集中的应用

边缘计算网关是连接边缘设备和云端的一个中间节点&#xff0c;负责在边缘设备和云服务器之间进行数据传输和处理。它具备数据采集、数据处理、协议转换、数据存储、安全功能及远程管理等多种能力&#xff0c;是边缘计算系统中不可或缺的关键设备。 一、功能与优势 数据采集&a…

腾讯二面:MySQL的半同步是什么?不是MySQL的两阶段提交,那是什么?

前言 年后在进行腾讯二面的时候&#xff0c;写完算法的后问的第一个问题就是&#xff0c;MySQL的半同步是什么&#xff1f;我当时直接懵了&#xff0c;我以为是问的MySQL的两阶段提交的问题呢&#xff1f;结果确认了一下后不是两阶段提交&#xff0c;然后面试官看我连问的是啥都…

云计算基础,虚拟化原理

文章目录 一、虚拟化1.1 什么是虚拟化1.2 虚拟化类型 二 、存储虚拟化2.1 存储指标2.2 存储类型2.3 存储协议2.4 RAID 三、内存 i/O虚拟化3.1 内存虚拟化基本概念地址空间转换原理内存共享与隔离原理 3.2 I/O 虚拟化基本概念模拟&#xff08;Emulation&#xff09;方式半虚拟化…