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

一、提取车道线

在道路检测中,提取车道线至关重要。我们采用两种主要方法进行车道线提取:梯度提取和颜色提取。梯度提取包括高斯滤波、灰度化、梯度处理、二值化和形态学变换(膨胀和腐蚀),能有效突出车道线的边缘特征;颜色提取则通过 HLS 颜色空间提取白色车道线和使用 Lab 颜色空间提取黄色车道线,可以进一步增强车道线的可区分性。这两种方法结合使用,有助于实现更准确的车道线检测。

1.1、梯度提取

高斯滤波

  • 使用高斯滤波器对输入图像进行平滑,减少噪声,帮助后续的梯度计算。

灰度化

  • 将彩色图像转换为灰度图像,以简化图像数据。

梯度处理

  • 使用Sobel算子计算图像的梯度,可以计算x和y方向的梯度。

二值化

  • 通过阈值处理将图像二值化,突出边缘。

形态学变换(膨胀,腐蚀)

  • 使用膨胀和腐蚀来去除噪声和填补空洞。

1.2、颜色提取

白色提取(HLS空间

  • 通过转换到HLS颜色空间来提取白色车道线。

黄色提取(Lab空间

  • 将图像转换到Lab颜色空间,以便提取黄色区域。

二、梯度提取

导入模块

python 复制代码
import cv2
import numpy as np

输入图像

python 复制代码
img_wrp=cv2.imread('img_wrp.png')

高斯滤波

python 复制代码
img_Gaussian=cv2.GaussianBlur(img_wrp,(7,7),sigmaX=1)

灰度化

python 复制代码
img_gray=cv2.cvtColor(img_Gaussian,cv2.COLOR_BGR2GRAY)

梯度处理

python 复制代码
img_Sobel=cv2.Sobel(img_gray,-1,dx=1,dy=0)

二值化

python 复制代码
ret,img_threshold=cv2.threshold(img_Sobel,127,255,cv2.THRESH_BINARY)

形态学变换(先膨胀后腐蚀)

python 复制代码
kernel=np.ones((11,11),np.uint8)
img_dilate=cv2.dilate(img_threshold,kernel,iterations=2)
img_erode=cv2.erode(img_dilate, kernel, iterations=1)

输出图像

python 复制代码
cv2.imshow('img_wrp', img_wrp)
cv2.imshow('img_Gaussian', img_Gaussian)
cv2.imshow('img_gray', img_gray)
cv2.imshow('img_Sobel', img_Sobel)
cv2.imshow('img_threshold', img_threshold)
cv2.imshow('img_erode', img_erode)
cv2.waitKey(0)

完整代码

python 复制代码
import cv2
import numpy as np

# 读取透视变换后的图像 'img_wrp.png'  
img_wrp = cv2.imread('img_wrp.png')  

# 对图像应用高斯模糊,减少噪声,使用的卷积核为 (7, 7),sigmaX 为 1  
img_Gaussian = cv2.GaussianBlur(img_wrp, (7, 7), sigmaX=1)  

# 将模糊后的图像转换为灰度图  
img_gray = cv2.cvtColor(img_Gaussian, cv2.COLOR_BGR2GRAY)  

# 对灰度图像应用 Sobel 边缘检测,使用水平梯度 (dx=1, dy=0)  
img_Sobel = cv2.Sobel(img_gray, -1, dx=1, dy=0)  

# 对 Sobel 输出的图像应用二值化处理,将图像转换为黑白图像  
# 当像素值 > 127 时,设为 255;否则设为 0  
ret, img_threshold = cv2.threshold(img_Sobel, 127, 255, cv2.THRESH_BINARY)  

# 创建一个 11x11 的全 1 核,进行形态学操作  
kernel = np.ones((11, 11), np.uint8)  

# 对二值化图像进行膨胀操作,增加白色区域  
img_dilate = cv2.dilate(img_threshold, kernel, iterations=2)  

# 对膨胀后的图像进行腐蚀操作,减少白色区域  
img_erode = cv2.erode(img_dilate, kernel, iterations=1)  

# 显示各步骤处理后的图像  
cv2.imshow('img_wrp', img_wrp)           # 显示原始透视变换图  
cv2.imshow('img_Gaussian', img_Gaussian) # 显示高斯模糊后的图像  
cv2.imshow('img_gray', img_gray)         # 显示灰度图像  
cv2.imshow('img_Sobel', img_Sobel)       # 显示 Sobel 边缘检测结果  
cv2.imshow('img_threshold', img_threshold) # 显示二值化后的图像  
cv2.imshow('img_erode', img_erode)       # 显示腐蚀后的图像  

# 等待按键后关闭窗口  
cv2.waitKey(0)  
  1. 读取透视变换后保存的图像。
  2. 对图像应用高斯模糊,减少噪声以平滑图像。
  3. 将模糊图像转换为灰度图,以便进行边缘检测。
  4. 使用 Sobel 算子检测图像的水平边缘。
  5. 将 Sobel 输出的图像进行二值化处理,以获取明显的边缘部分。
  6. 进行形态学的膨胀和腐蚀操作,增加和减少白色区域,进一步改善图像质量。
  7. 显示处理后各个步骤的图像,方便观察效果。

三、颜色提取

导入模块

python 复制代码
import cv2
import numpy as np

输入图像

python 复制代码
img_wrp=cv2.imread('img_wrp.png')

提取白色车道线

python 复制代码
img_hls=cv2.cvtColor(img_wrp,cv2.COLOR_BGR2HLS)
l_channel=img_hls[:,:,1]
l_channel=l_channel/np.max(l_channel)*255
binary_output1=np.zeros_like(l_channel)
binary_output1[(l_channel>220) & (l_channel<255)]=1

提取黄色车道线

python 复制代码
img_lab=cv2.cvtColor(img_wrp,cv2.COLOR_BGR2Lab)
img_lab[:,240:,:]=(0,0,0)
lab_b=img_lab[:,:,2]
if np.max(lab_b)>100:
    lab_b=lab_b/np.max(lab_b)*255
binary_output2=np.zeros_like(l_channel)
binary_output2[(lab_b > 212) & (lab_b < 220)] = 1

对车道线进行合并

python 复制代码
#直接进行相加
binary_output=binary_output1+binary_output2

python 复制代码
#创建新的模板
binary_output=np.zeros_like(binary_output1)
binary_output[(binary_output1 == 1) | (binary_output2 == 1)] = 1

形态学变换(先膨胀后腐蚀)

python 复制代码
kernel=np.ones((15,15),np.uint8)
img_dilate_binary_output=cv2.dilate(binary_output,kernel,iterations=1)
img_erode_binary_output=cv2.erode(img_dilate_binary_output, kernel, iterations=1)

输出图像

python 复制代码
cv2.imshow('binary_output1',binary_output1)
cv2.imshow('binary_output2', binary_output2)
cv2.imshow('binary_output', binary_output)
cv2.imshow('img_erode_binary_output', img_erode_binary_output)
cv2.waitKey(0)

完整代码

python 复制代码
import cv2  # 导入 OpenCV 库,用于图像处理  
import numpy as np  # 导入 NumPy 库,用于数值计算  

# 读取透视变换后的图像 'img_wrp.png'  
img_wrp = cv2.imread('img_wrp.png')  

# 将图像从 BGR 转换到 HLS 颜色空间  
img_hls = cv2.cvtColor(img_wrp, cv2.COLOR_BGR2HLS)  

# 提取 HLS 中的亮度通道 (L通道)  
l_channel = img_hls[:, :, 1]  

# 将亮度通道归一化到 0 到 255 的范围  
l_channel = l_channel / np.max(l_channel) * 255  

# 创建一个和亮度通道同样大小的零数组,用于存放二值化结果  
binary_output1 = np.zeros_like(l_channel)  

# 使用阈值条件筛选出亮度通道中处于 220 到 255 之间的像素点  
binary_output1[(l_channel > 220) & (l_channel < 255)] = 1  

# 提取黄色车道线  
# 转换原图像为 Lab 颜色空间  
img_lab = cv2.cvtColor(img_wrp, cv2.COLOR_BGR2Lab)  

# 将 Lab 图像的某些区域(240列及之后的所有区域)设为黑色  
img_lab[:, 240:, :] = (0, 0, 0)  

# 提取 Lab 图像中的 b 通道  
lab_b = img_lab[:, :, 2]  

# 对 b 通道进行归一化处理(如果最大值大于 100)  
if np.max(lab_b) > 100:  
    lab_b = lab_b / np.max(lab_b) * 255  

# 创建一个与亮度通道同样大小的零数组,用于存放二值化结果  
binary_output2 = np.zeros_like(l_channel)  

# 使用阈值条件筛选出 b 通道中处于 212 到 220 之间的像素点  
binary_output2[(lab_b > 212) & (lab_b < 220)] = 1  

# 创建一个新的二值图像 binary_output,结合两个二值图像  
binary_output = np.zeros_like(binary_output1)  
binary_output[(binary_output1 == 1) | (binary_output2 == 1)] = 1  

# 创建一个 15x15 的全 1 核,用于形态学操作  
kernel = np.ones((15, 15), np.uint8)  

# 对结合的二值图像进行膨胀操作,增加白色区域  
img_dilate_binary_output = cv2.dilate(binary_output, kernel, iterations=1)  

# 对膨胀后的图像进行腐蚀操作,以减少白色区域  
img_erode_binary_output = cv2.erode(img_dilate_binary_output, kernel, iterations=1)  

# 显示不同阶段的二值化输出图像  
cv2.imshow('binary_output1', binary_output1)              # 显示亮度通道的二值化结果  
cv2.imshow('binary_output2', binary_output2)              # 显示黄色车道线的二值化结果  
cv2.imshow('binary_output', binary_output)                # 显示结合后的二值图像  
cv2.imshow('img_erode_binary_output', img_erode_binary_output)  # 显示腐蚀处理后的图像  

# 等待按键后关闭窗口  
cv2.waitKey(0)  
  1. 读取透视变换后的图像,并将其转换为 HLS 颜色空间,以提取亮度通道。
  2. 将亮度通道归一化并进行二值化,提取亮度较高的区域。
  3. 转换图像为 Lab 颜色空间,提取 b 通道并进行归一化处理,选择黄色车道线。
  4. 创建一个结合两个输出的最终二值图像,该图像包含亮度和黄色车道线的信息。
  5. 使用膨胀和腐蚀操作改善二值图像的形态,去除噪声和空隙。
  6. 显示每个步骤的结果,以便进行视觉比较和分析。

四、库函数

4.1、cvtColor()

python 复制代码
cv.cvtColor(	src, code[, dst[, dstCn[, hint]]]	) ->	dst
方法 描述
src 输入图像:8 位无符号、16 位无符号 ( CV_16UC... ) 或单精度浮点。
dst 输出图像的大小和深度与 src 相同。
code 色彩空间转换代码(请参阅 ColorConversionCodes)。
dstCn 目标图像中的通道数;如果参数为 0,则 Channels 的数量会自动从 src 和 code 中得出。
hint 实现修改标志。请参阅 AlgorithmHint

4.2、GaussianBlur()

python 复制代码
cv.GaussianBlur(	src, ksize, sigmaX[, dst[, sigmaY[, borderType[, hint]]]]	) ->	DST

| 方法 | 描述 |
| src | 输入图像;图像可以有任意数量的通道,这些通道是独立处理的,但深度应为 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F。 |
| dst | 输出图像的大小和类型与 src 相同。 |
| ksize | Gaussian kernel 大小。ksize.width 和 ksize.height 可以不同,但它们都必须是正数和奇数。或者,它们可以是零,然后根据 sigma 计算。 |
| sigmaX | X 方向上的高斯核标准差 |
| sigmaY | Y 方向的高斯核标准差;如果 sigmaY 为零,则设置为等于 sigmaX,如果两个 sigma 都为零,则分别从 ksize.width 和 ksize.height 计算出来(详见 getGaussianKernel);为了完全控制结果,而不管所有这些语义将来可能如何修改,建议指定所有 ksize、sigmaX 和 sigmaY。 |
| borderType | 像素外插方法,请参阅 BorderTypes。不支持BORDER_WRAP。 |

hint 实现修改标志。请参阅 AlgorithmHint

4.3、threshold()

将固定级别的阈值应用于每个数组元素。

该函数将固定级别的阈值应用于多通道数组。该函数通常用于从灰度图像中获取双层(二进制)图像( compare 也可用于此目的)或用于去除噪声,即过滤掉值太小或太大的像素。该函数支持多种类型的阈值。它们由 type parameter 确定。

此外,特殊值 THRESH_OTSUTHRESH_TRIANGLE 可以与上述值之一结合使用。在这些情况下,该函数使用 Otsu 或 Triangle 算法确定最佳阈值,并使用它而不是指定的阈值。

注意

目前,Otsu 和 Triangle 方法仅针对 8 位单通道图像实现。

python 复制代码
cv.threshold(src, thresh, maxval, type[, dst]) ->retval, dst
方法 描述
src 输入数组 (多通道、8 位或 32 位浮点)
thresh 阈值
maxval Maximum 值,用于 THRESH_BINARYTHRESH_BINARY_INV 阈值类型。
type 阈值类型

注意:

该方法有两个返回值retval、dst
阈值作的类型

|------------------------------------------------------------|-----------------------------------------------------------------------------|
| THRESH_BINARY Python: cv.THRESH_BINARY 阈值法 | ​ |
| THRESH_BINARY_INV Python: cv.THRESH_BINARY_INV 反阈值法 | ​ |
| THRESH_TRUNC Python: cv.THRESH_TRUNC 截断阈值法 | ​ |
| THRESH_TOZERO Python: cv.THRESH_TOZERO 低阈值零处理 | ​ |
| THRESH_TOZERO_INV Python: cv.THRESH_TOZERO_INV 超阈值零处理 | ​ |
| THRESH_MASK Python: cv.THRESH_MASK | |
| THRESH_OTSU Python: cv.THRESH_OTSU OTSU阈值法 | flag 中,使用 Otsu 算法选择最佳阈值 |
| THRESH_TRIANGLE Python: cv.THRESH_TRIANGLE Triangle阈值法 | 标志,使用 Triangle 算法选择最佳阈值 |

4.4、Sobel()

python 复制代码
cv.Sobel(	src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]	) ->	dst

| 方法 | 描述 |
| src | 输入图像 |
| dst | 输出图像 |
| ddepth | 目标图像的所需深度,请参阅组合 |
| dx | 导数 X 的阶数 |
| dy | 导数 y 的阶数 |
| ksize | 扩展 Sobel 核的大小;它必须是 1、3、5 或 7。 |
| scale | 计算的导数值的可选比例因子;默认情况下,不应用缩放(有关详细信息,请参阅 getDerivKernels)。 |
| delta | 在将过滤的像素存储到 DST 之前添加到过滤像素的可选值。 |

borderType 素外插方法,请参阅 BorderTypes。不支持BORDER_WRAP

4.5、dilate()

python 复制代码
cv.dilate(	src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]	) ->	dst

| 方法 | 描述 |
| src | 输入图像;通道数可以是任意的,但深度应该是 CV_8U、 CV_16U、 CV_16S、 CV_32F 或 CV_64F 之一。 |
| dst | 输出图像的大小和类型与 src 相同。 |
| kernel | 用于扩张的结构元件;如果 element=Mat(),则使用 3 x 3 矩形结构元素。可以使用 getStructuringElement 创建 Kernel |
| anchor | 锚点在元素中的位置;默认值 (-1, -1) 表示锚点位于元素中心。 |
| iterations | 应用扩张的次数。 |
| borderType | 像素外插方法,请参阅 BorderTypes。不支持BORDER_WRAP。 |

borderValue border 值(如果边界为常量)
BorderTypes
BORDER_CONSTANT Python:cv.BORDER_CONSTANT `iiiiii
BORDER_REPLICATE Python:cv.BORDER_REPLICATE `aaaaaa
BORDER_REFLECT Python:cv.BORDER_REFLECT `fedcba
BORDER_REFLECT_101 Python:cv.BORDER_REFLECT_101 `gfedcb
BORDER_TRANSPARENT Python:cv.BORDER_TRANSPARENT `uvwxyz
BORDER_REFLECT101 Python:cv.BORDER_REFLECT101 与 BORDER_REFLECT_101 相同
BORDER_DEFAULT Python:cv.BORDER_DEFAULT 与 BORDER_REFLECT_101 相同
BORDER_ISOLATED Python:cv.BORDER_ISOLATED 插值限制在 ROI 边界内。

4.6、erode()

python 复制代码
cv.erode(	src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]	) ->	dst

| 方法 | 描述 |
| src | 输入图像;通道数可以是任意的,但深度应该是 CV_8U、 CV_16U、 CV_16S、 CV_32F 或 CV_64F 之一。 |
| dst | 输出图像的大小和类型与 src 相同。 |
| kernel | 用于侵蚀的结构元件;如果 ,则使用矩形结构元素。可以使用 getStructuringElement 创建 Kernel。element=Mat()``3 x 3 |
| anchor | 锚点在元素中的位置;默认值 (-1, -1) 表示锚点位于元素中心。 |
| iterations | 应用 腐蚀的次数。 |
| borderType | 像素外插方法,请参阅 BorderTypes。不支持BORDER_WRAP。 |

borderValue border 值(如果边界为常量)
BorderTypes
BORDER_CONSTANT Python:cv.BORDER_CONSTANT `iiiiii
BORDER_REPLICATE Python:cv.BORDER_REPLICATE `aaaaaa
BORDER_REFLECT Python:cv.BORDER_REFLECT `fedcba
BORDER_REFLECT_101 Python:cv.BORDER_REFLECT_101 `gfedcb
BORDER_TRANSPARENT Python:cv.BORDER_TRANSPARENT `uvwxyz
BORDER_REFLECT101 Python:cv.BORDER_REFLECT101 与 BORDER_REFLECT_101 相同
BORDER_DEFAULT Python:cv.BORDER_DEFAULT 与 BORDER_REFLECT_101 相同
BORDER_ISOLATED Python:cv.BORDER_ISOLATED 插值限制在 ROI 边界内。
相关推荐
用户27784491049934 小时前
借助DeepSeek智能生成测试用例:从提示词到Excel表格的全流程实践
人工智能·python
JavaEdge在掘金6 小时前
ssl.SSLCertVerificationError报错解决方案
python
我不会编程5557 小时前
Python Cookbook-5.1 对字典排序
开发语言·数据结构·python
老歌老听老掉牙7 小时前
平面旋转与交线投影夹角计算
python·线性代数·平面·sympy
满怀10157 小时前
Python入门(7):模块
python
无名之逆7 小时前
Rust 开发提效神器:lombok-macros 宏库
服务器·开发语言·前端·数据库·后端·python·rust
你觉得2057 小时前
哈尔滨工业大学DeepSeek公开课:探索大模型原理、技术与应用从GPT到DeepSeek|附视频与讲义下载方法
大数据·人工智能·python·gpt·学习·机器学习·aigc
啊喜拔牙7 小时前
1. hadoop 集群的常用命令
java·大数据·开发语言·python·scala
hyshhhh8 小时前
【算法岗面试题】深度学习中如何防止过拟合?
网络·人工智能·深度学习·神经网络·算法·计算机视觉
__lost8 小时前
Pysides6 Python3.10 Qt 画一个时钟
python·qt