Python----计算机视觉处理(Opencv:道路检测之车道线拟合)

news2025/4/7 19:22:55

完整版: Python----计算机视觉处理(Opencv:道路检测完整版:透视变换,提取车道线,车道线拟合,车道线显示)

一、获取左右车道线的原始位置 

导入模块

import cv2
import numpy as np
from matplotlib import pyplot as plt

输入图像 

img = cv2.imread('img_road.png')

获取图像的高和宽 

height, width, _ = img.shape

对图像的高进行求和 

num_ax0 = np.sum(img, axis=0)

显示图像求和图 

plt.plot(num_ax0)
plt.show()

得到直方图左右两侧最高点的位置 

    img_left_argmax=np.argmax(num_ax0[:width//2])
    img_right_argmax=np.argmax(num_ax0[width//2:])+width//2

二、绘制小窗口

获取图像中所有非零像素的x和y的位置

nonzeroy,nonzerox=np.array(img.nonzero())

定义一些小窗口的概念参数

# 定义小窗口的个数
windows_num=10

#小窗口的宽度和高度
windows_height=height//windows_num
windows_width=30

#小窗口白色个数阈值
min_pix=40

#初始化当前窗口的位置
left_current=img_left_argmax
right_current=img_right_argmax

创建空列表接收左侧和右侧车道线像素的索引

left_lane_inds=[]
right_lane_inds=[]

绘制小窗口一

for window in range(windows_num):
    # 计算当前窗口的上边界的y坐标
    win_y_high=height-windows_height*(window+1)
    # 计算当前窗口的下边界的y坐标
    win_y_low = height - windows_height * window
    # 计算左边窗口左右边界的x坐标
    win_x_left_left=left_current - windows_width
    win_x_left_right=left_current + windows_width

    # 计算右边窗口左右边界的x坐标
    win_x_right_left=right_current - windows_width
    win_x_right_right=right_current + windows_width

    cv2.rectangle(out_img, (win_x_left_left, win_y_high), (win_x_left_right, win_y_low), (0, 255, 0), 2)
    cv2.rectangle(out_img, (win_x_right_left, win_y_high), (win_x_right_right, win_y_low), (0, 255, 0), 2)

 

        通过上述代码绘画出的小窗口没有随路线的弯曲程度而弯曲,需要该进 

改进小窗口,让窗口随路线的走势而走势

    for window in range(windows_num):
        # 计算当前窗口的上边界的y坐标
        win_y_high=height-windows_height*(window+1)
        # 计算当前窗口的下边界的y坐标
        win_y_low = height - windows_height * window
        # 计算左边窗口左右边界的x坐标
        win_x_left_left=left_current - windows_width
        win_x_left_right=left_current + windows_width

        # 计算右边窗口左右边界的x坐标
        win_x_right_left=right_current - windows_width
        win_x_right_right=right_current + windows_width

        cv2.rectangle(out_img, (win_x_left_left, win_y_high), (win_x_left_right, win_y_low), (0, 255, 0), 2)
        cv2.rectangle(out_img, (win_x_right_left, win_y_high), (win_x_right_right, win_y_low), (0, 255, 0), 2)

        good_left_index=((nonzeroy >= win_y_high) & (nonzeroy < win_y_low)
                         & (nonzerox >= win_x_left_left) & (nonzerox < win_x_left_right)).nonzero()[0]
        good_right_index=((nonzeroy >= win_y_high) & (nonzeroy < win_y_low)
                          & (nonzerox >= win_x_right_left) & (nonzerox < win_x_right_right)).nonzero()[0]

        left_lane_inds.append(good_left_index)
        right_lane_inds.append(good_right_index)

        if len(good_left_index)>min_pix:
            left_current = int(np.mean(nonzerox[good_left_index]))
        else:
            if len(good_right_index)>min_pix:
                offset=int(np.mean(nonzerox[good_right_index]))-right_pre
                left_current=left_current+offset
        if len(good_right_index)>min_pix:
            right_current = int(np.mean(nonzerox[good_right_index]))
        else:
            if len(good_left_index)>min_pix:
                offset=int(np.mean(nonzerox[good_left_index]))-left_pre
                right_current=right_current+offset

        left_pre=left_current
        right_pre=right_current

三、拟合车道线

#连接索引的列表,为了后续更方便的提取出这些像素点的和y的坐标,以便进行车道线的拟合
    left_lane_inds=np.concatenate(left_lane_inds)
    right_lane_inds=np.concatenate(right_lane_inds)

    # 提取左侧和右侧车道线像素的位置
    # left_lane_inds 是一个一维数组,它包含了左侧车道线在滑动窗口中找到的白色像素点的x坐标的索引
    # 通过将这些索引作为索引器应用到 nonzerox数组上,就可以得到相应的左侧车道线的x坐标
    # leftx 包含了左侧车道线自色像素点的华标
    leftx=nonzerox[left_lane_inds]
    lefty=nonzeroy[left_lane_inds]

    rightx=nonzerox[right_lane_inds]
    righty=nonzeroy[right_lane_inds]

    # 有了坐标之后,就要去对左侧和右侧车道线进行多项式拟合,从而得到拟合的车道线# np.polyfit()是numpy中用于进行多项式拟合的函数
    # 他接受三个参数:xy 和deg
    # x:自变量数组,y:因变量数组
    # deg:多项式的次数,如果是y=ax^2+b^x+C
    # left_fit里存放的就是 a、b、c的参数,
    left_fit=np.polyfit(lefty,leftx,2)
    right_fit=np.polyfit(righty, rightx, 2)
    # 使用np.linspace 生成一组均匀分布的数值,用于表示竖直方向上的像素坐标,方便后续的车道线的绘制
    # 使用多项式拟合来估计左侧和右侧车道线的x坐标
    # left_fitx 就是左侧拟合出来的车道线
    ploty=np.linspace(0,height-1,height)
    left_fitx=left_fit[0]*ploty**2+left_fit[1]*ploty+left_fit[2]
    right_fitx = right_fit[0] * ploty ** 2 + right_fit[1] * ploty +  right_fit[2]

    # 计算中间车道线的位置
    middle_fitx=(left_fitx+right_fitx)//2
    # 使用不同颜色将车道线标出来
    out_img[lefty,leftx]=[255,0,0]
    out_img[righty,rightx]=[0,0,255]

四、完整代码

 

import cv2  
import numpy as np  
import matplotlib.pyplot as plt  

# 读取图像  
img = cv2.imread('img_road.png')  

# 将图像复制到三个通道,以便于处理  
out_img = np.dstack((img, img, img))  

# 计算每列像素的总和,以便找到车道线的最高点  
num_ax0 = np.sum(img, axis=0)  

# 获取左右两侧最高点的位置  
img_left_argmax = np.argmax(num_ax0[:width // 2])  # 左侧最高点  
img_right_argmax = np.argmax(num_ax0[width // 2:]) + width // 2  # 右侧最高点  

# 获取图像中所有非零像素的x和y的位置  
nonzeroy, nonzerox = np.array(img.nonzero())  

# 定义小窗口的个数  
windows_num = 10  

# 小窗口的高度和宽度  
windows_height = height // windows_num  
windows_width = 30  

# 小窗口白色像素的个数阈值  
min_pix = 400  

# 初始化当前窗口的位置  
left_current = img_left_argmax  
right_current = img_right_argmax  

# 记录上一个窗口的位置  
left_pre = left_current  
right_pre = right_current  

# 创建空列表以接收左侧和右侧车道线像素的索引  
left_lane_inds = []  
right_lane_inds = []  

# 遍历每个窗口  
for window in range(windows_num):  
    # 计算当前窗口的上边界y坐标  
    win_y_high = height - windows_height * (window + 1)  
    # 计算当前窗口的下边界y坐标  
    win_y_low = height - windows_height * window  
    # 计算左侧窗口的左右边界x坐标  
    win_x_left_left = left_current - windows_width  
    win_x_left_right = left_current + windows_width  
    # 计算右侧窗口的左右边界x坐标  
    win_x_right_left = right_current - windows_width  
    win_x_right_right = right_current + windows_width  

    # 在图像上绘制窗口  
    cv2.rectangle(out_img, (win_x_left_left, win_y_high), (win_x_left_right, win_y_low), (0, 255, 0), 2)  
    cv2.rectangle(out_img, (win_x_right_left, win_y_high), (win_x_right_right, win_y_low), (0, 255, 0), 2)  

    # 找到在当前窗口内的好像素索引  
    good_left_index = ((nonzeroy >= win_y_high) & (nonzeroy < win_y_low)  
                       & (nonzerox >= win_x_left_left) & (nonzerox < win_x_left_right)).nonzero()[0]  
    good_right_index = ((nonzeroy >= win_y_high) & (nonzeroy < win_y_low)  
                        & (nonzerox >= win_x_right_left) & (nonzerox < win_x_right_right)).nonzero()[0]  
    
    # 将找到的索引添加到列表中  
    left_lane_inds.append(good_left_index)  
    right_lane_inds.append(good_right_index)  
    

    # 更新当前窗口位置  
    if len(good_left_index) > min_pix:  
        left_current = int(np.mean(nonzerox[good_left_index]))  # 更新左侧窗口位置  
    else:  
        if len(good_right_index) > min_pix:  
            offset = int(np.mean(nonzerox[good_right_index])) - right_pre  # 计算偏移量  
            left_current = left_current + offset  # 更新左侧窗口位置  

    if len(good_right_index) > min_pix:  
        right_current = int(np.mean(nonzerox[good_right_index]))  # 更新右侧窗口位置  
    else:  
        if len(good_left_index) > min_pix:  
            offset = int(np.mean(nonzerox[good_left_index])) - left_pre  # 计算偏移量  
            right_current = right_current + offset  # 更新右侧窗口位置  

    # 更新上一个窗口位置  
    left_pre = left_current  
    right_pre = right_current  

# 将找到的索引合并为一个数组  
left_lane_inds = np.concatenate(left_lane_inds)  
right_lane_inds = np.concatenate(right_lane_inds)  

# 获取左右车道线的x和y坐标  
leftx = nonzerox[left_lane_inds]  
lefty = nonzeroy[left_lane_inds]  

rightx = nonzerox[right_lane_inds]  
righty = nonzeroy[right_lane_inds]  

# 使用多项式拟合左侧和右侧车道线  
# 有了坐标之后,就要去对左侧和右侧车道线进行多项式拟合,从而得到拟合的车道线# np.polyfit()是numpy中用于进行多项式拟合的函数
# 他接受三个参数:xy 和deg
# x:自变量数组,y:因变量数组
# deg:多项式的次数,如果是2y=ax^2+b^x+C
# left_fit里存放的就是 a、b、c的参数,
left_fit = np.polyfit(lefty, leftx, 2)  # 左侧拟合  
right_fit = np.polyfit(righty, rightx, 2)  # 右侧拟合  

# 创建y坐标的线性空间  
ploty = np.linspace(0, height - 1, height)  

# 根据拟合的多项式计算x坐标  
left_fitx = left_fit[0] * ploty ** 2 + left_fit[1] * ploty + left_fit[2]  
right_fitx = right_fit[0] * ploty ** 2 + right_fit[1] * ploty + right_fit[2]  

# 计算中间车道线的x坐标  
middle_fitx = (left_fitx + right_fitx) // 2  

# 在输出图像上标记左侧和右侧车道线像素  
out_img[lefty, leftx] = [255, 0, 0]  # 左侧车道线为红色  
out_img[righty, rightx] = [0, 0, 255]  # 右侧车道线为蓝色  

# 显示结果图像  
cv2.imshow('out_img', out_img)  
cv2.waitKey(0)  
  1. 图像读取和准备:读取图像并为处理做好准备。
  2. 直方图计算:计算像素值的总和,以找到车道的位置。
  3. 滑动窗口:使用滑动窗口技术识别车道像素。
  4. 车道像素索引:收集左侧和右侧车道的好像素索引。
  5. 多项式拟合:对识别出的车道点进行多项式拟合,以生成平滑的车道线。
  6. 可视化:在输出图像上绘制检测到的车道线并展示。

五、库函数

5.1、nonzero()

        返回数组中非零元素的索引

numpy.nonzero(a)

用途:它通常用来查找非零元素的位置,常用于图像处理中筛选出特定的像素。

返回值:函数返回一个元组,每个元素是一个数组,表示非零元素在每个维度上的索引。例如,对于二维数组 AA.nonzero() 返回两个数组,第一个数组表示行索引,第二个数组表示列索引。

import numpy as np

arr=np.array(
    [
        [0,1,2,3,4,5,6],
        [1,2,3,4,5,6,7],
        [0,0,0,0,0,0,0]
    ]
)
print(arr.nonzero())
#(array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1]), array([1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6]))

5.2、polyfit()

        用于计算数据点的多项式拟合

numpy.polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False)
方法描述
xM 个采样点的 x 坐标。(x[i], y[i])
y采样点的 y 坐标。样本的多个数据集 共享相同 x 坐标的点可以通过以下方式一次拟合 传入一个 2D 数组,该数组每列包含一个数据集。
deg拟合多项式的次数
rcond拟合的相对条件编号。小于 this 相对于最大奇异值将被忽略。这 默认值为 len(x)*eps,其中 eps 是 float 类型,大多数情况下约为 2E-16。
fullSwitch 确定返回值的性质。当为 False 时( default) 仅返回系数,当 True diagnostic 还会返回来自奇异值分解的信息。
w权重。如果不是 None,则权重适用于未平方的 残差 。理想情况下,权重为 选中,这样产品的误差都具有 相同的方差。使用逆方差加权时,请使用 。默认值为 None。w[i]y[i] - y_hat[i]x[i]w[i]*y[i]w[i] = 1/sigma(y[i])
cov如果给定且非 False,则不仅返回估计值,还返回其 协方差矩阵。默认情况下,协方差的缩放比例为 chi2/dof,其中 dof = M - (度 + 1),即假定权重 不可靠,除非在相对意义上,并且一切都是缩放的 使得还原的 Chi2 是 Unity。如果 ,则省略此缩放,因为与权重 w = 1/sigma,其中已知 sigma 是 不确定性。cov='unscaled'
import numpy as np
x = np.array([1, 2, 3, 4])
y = np.array([2, 3, 5, 7])
# ax**2+bx+c
a,b,c = np.polyfit(x, y, 2)  # 进行二次多项式拟合
print(a,b,c)
#[0.25 0.45 1.25]

5.3、linspace()

        用于生成指定范围内的等间距数字

numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0, *, device=None)
方法描述
start序列的起始值。
stop序列的结束值,除非 endpoint 设置为 False。 在这种情况下,序列由除最后一个均匀分布的样本之外的所有样本组成,因此不包括 stop。请注意,步骤 当 endpoint 为 False 时,size 会发生变化。num + 1
num要生成的样本数。默认值为 50。必须为非负数。
endpoint如果为 True,则 stop 是最后一个样本。否则,不包括在内。 默认值为 True。
retstep如果为 True,则返回 (samples, step),其中 step 是间距 样本之间。
dtype输出数组的类型。如果未给出,则数据类型 是从 start 和 stop 推断出来的。推断的 dtype 永远不会是 整数;float 的 整数数组。
axis结果中用于存储样本的轴。仅在启动时相关 或 stop 是类似数组的。默认情况下 (0),样本将沿着 在开头插入新轴。使用 -1 在末尾获取一个轴。
device要放置创建的阵列的设备。默认值:None。 仅对于 Array-API 互作性,如果通过,则必须这样做。
import numpy as np
samples = np.linspace(0, 1, 5)  # 生成 0 到 1 之间的 5 个等间距点
print(samples)
# [0.   0.25 0.5  0.75 1.  ]

5.4、dstack()

        用于沿着深度(第三个轴)拼接数组。

numpy.dstack(tup)
方法描述
tup数组沿除第三个轴之外的所有轴必须具有相同的形状。 一维或二维数组必须具有相同的形状。
import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
c = np.dstack((a, b))  # 沿着深度轴拼接,结果形状为 (2, 2, 2)
print(c)
'''
[[[1 5]
  [2 6]]

 [[3 7]
  [4 8]]]
'''

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何理解神经网络中的“分段线性单元”,优雅解析前向和反向传播

什么是非线性 非线性本质上指的是一个系统或函数中输入与输出之间的关系不呈现简单的比例关系&#xff0c;也就是说&#xff0c;输出不只是输入的线性组合 ( 比如 y k 1 x 1 k 2 x 2 b ) (比如yk1x1k2x2b) (比如yk1x1k2x2b)。下面详细解释这个概念&#xff1a; 缺乏叠加性…

WVP-GB28181摄像头管理平台存在弱口令

免责声明&#xff1a;本号提供的网络安全信息仅供参考&#xff0c;不构成专业建议。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权&#xff0c;请及时与我联系&#xff0c;我将尽快处理并删除相关内容。 漏洞描述 攻击者可利用漏洞获取当前系统管…

开源身份和访问管理方案之keycloak(三)keycloak健康检查(k8s)

文章目录 开源身份和访问管理方案之keycloak&#xff08;三&#xff09;keycloak健康检查启用运行状况检查 健康检查使用Kubernetes下健康检查Dockerfile 中 HEALTHCHECK 指令 健康检查Docker HEALTHCHECK 和 Kubernetes 探针 开源身份和访问管理方案之keycloak&#xff08;三&…

Android学习总结之service篇

引言 在 Android 开发里&#xff0c;Service 与 IntentService 是非常关键的组件&#xff0c;它们能够让应用在后台开展长时间运行的操作。不过&#xff0c;很多开发者仅仅停留在使用这两个组件的层面&#xff0c;对其内部的源码实现了解甚少。本文将深入剖析 Service 和 Inte…

spring mvc异步请求 sse 大文件下载 断点续传下载Range

学习连接 异步Servlet3.0 Spring Boot 处理异步请求&#xff08;DeferredResult 基础案例、DeferredResult 超时案例、DeferredResult 扩展案例、DeferredResult 方法汇总&#xff09; spring.io mvc Asynchronous Requests 官网文档 spring.io webflux&webclient官网文…

Opencv计算机视觉编程攻略-第十节 估算图像之间的投影关系

目录 1. 计算图像对的基础矩阵 2. 用RANSAC 算法匹配图像 3. 计算两幅图像之间的单应矩阵 4. 检测图像中的平面目标 图像通常是由数码相机拍摄的&#xff0c;它通过透镜投射光线成像&#xff0c;是三维场景在二维平面上的投影&#xff0c;这表明场景和它的图像之间以及同一…

14.流程自动化工具:n8n和家庭自动化工具:node-red

n8n 安装 docker方式 https://docs.n8n.io/hosting/installation/docker/ #https://hub.docker.com/r/n8nio/n8n docker pull n8nio/n8n:latest docker rm -f n8n; docker run -it \ --network macvlan --hostname n8n \ -e TZ"Asia/Shanghai" \ -e GENERIC_TIME…

图形渲染: tinyrenderer 实现笔记(Lesson 1 - 4)

目录 项目介绍环境搭建Lesson 1: Bresenham’s Line Drawing Algorithm&#xff08;画线算法&#xff09;Lesson 2: Triangle rasterization 三角形光栅化Scanline rendering 线性扫描Modern rasterization approach 现代栅格化方法back-face culling 背面剔除 Lesson 3: Hidde…

大规模硬件仿真系统的编译挑战

引言&#xff1a; 随着集成电路设计复杂度的不断提升&#xff0c;硬件仿真系统在现代芯片设计流程中扮演着越来越重要的角色。基于FPGA&#xff08;现场可编程门阵列&#xff09;的商用硬件仿真系统因其灵活性、全自动化、高性能和可重构性&#xff0c;成为验证大规模集成电路设…

记一次常规的网络安全渗透测试

目录&#xff1a; 前言 互联网突破 第一层内网 第二层内网 总结 前言 上个月根据领导安排&#xff0c;需要到本市一家电视台进行网络安全评估测试。通过对内外网进行渗透测试&#xff0c;网络和安全设备的使用和部署情况&#xff0c;以及网络安全规章流程出具安全评估报告。本…

【8】搭建k8s集群系列(二进制部署)之安装work-node节点组件(kubelet)

一、下载k8s二进制文件 下载地址&#xff1a; https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG -1.20.md 注&#xff1a;打开链接你会发现里面有很多包&#xff0c;下载一个 server 包就够了&#xff0c;包含了 Master 和 Worker Node 二进制文件。…

使用 VIM 编辑器对文件进行编辑

一、VIM 的两种状态 VIM&#xff08;vimsual&#xff09;是 Linux/UNIX 系列 OS 中通用的全屏编辑器。vim 分为两种状态&#xff0c;即命令状态和编辑状态&#xff0c;在命令状态下&#xff0c;所键入的字符系统均作命令来处理&#xff1b;而编辑状态则是用来编辑文本资料&…

visual studio 2022的windows驱动开发

在visual studio2022中&#xff0c;若在单个组件中找不到Windows Driver Kit (WDK)选项&#xff0c;可通过提升vs版本解决&#xff0c;在首次选择时选择WDM 创建好项目在Source Files文件夹中创建一个test.c文件&#xff0c;并输入以下测试代码&#xff1a; #include <ntdd…

基于大数据的美团外卖数据可视化分析系统

【大数据】基于大数据的美团外卖数据可视化分析系统 &#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统通过对海量外卖数据的深度挖掘与分析&#xff0c;能够为美团外卖平台提供运营决策支…

vue2打包部署到nginx,解决路由history模式下页面空白问题

项目使用的是vue2&#xff0c;脚手架vue-cli 4。 需求&#xff1a;之前项目路由使用的是hash&#xff0c;现在要求调整为history模式&#xff0c;但是整个过程非常坎坷&#xff0c;遇到了页面空白问题。现在就具体讲一下这个问题。 首先&#xff0c;直接讲路由模式由hash改为…

【数据结构】排序算法(中篇)·处理大数据的精妙

前引&#xff1a;在进入本篇文章之前&#xff0c;我们经常在使用某个应用时&#xff0c;会出现【商品名称、最受欢迎、购买量】等等这些榜单&#xff0c;这里面就运用了我们的排序算法&#xff0c;作为刚学习数据结构的初学者&#xff0c;小编为各位完善了以下几种排序算法&…

AI随身翻译设备:从翻译工具到智能生活伴侣

文章目录 AI随身翻译设备的核心功能1. 实时翻译2. 翻译策略3. 翻译流程4. 输出格式 二、AI随身翻译设备的扩展功能1. 语言学习助手2. 旅行助手3. 商务助手4. 教育助手5. 健康助手6. 社交助手7. 技术助手8. 生活助手9. 娱乐助手10. 应急助手 三、总结四、未来发展趋势&#xff0…

chromadb 安装和使用

简介 Chromadb 是一个开源的嵌入式向量数据库&#xff0c;专为现代人工智能和机器学习应用设计&#xff0c;旨在高效存储、检索和管理向量数据。以下是关于它的详细介绍&#xff1a; 核心特性 易于使用&#xff1a;提供了简洁直观的 API&#xff0c;即使是新手也能快速上手…

LabVIEW 在故障诊断中的算法

在故障诊断领域&#xff0c;LabVIEW 凭借其强大的图形化编程能力、丰富多样的工具包以及卓越的功能性能&#xff0c;成为工程师们进行故障诊断系统开发的得力助手。通过运用各种算法&#xff0c;能够对采集到的信号进行全面、深入的分析处理&#xff0c;从而准确地诊断出系统中…

springboot 启动方式 装配流程 自定义starter 文件加载顺序 常见设计模式

目录 springboot介绍 核心特性 快速搭建 Spring Boot 项目 方式一&#xff1a;使用 Spring Initializr 方式二&#xff1a;使用 IDE 插件 示例代码 1. 创建项目并添加依赖 2. 创建主应用类 3. 创建控制器类 4. 运行应用程序 配置文件 部署和监控 部署 监控 与其…