本文介绍: 本次我们采用标准Hough线变换检测路沿,经过多次测试和调参,我们最后采用高斯模糊进行图像预处理然后使用canny进行边缘提取最后使用Hough线变换绘制直线。从视频中取出的每一帧是彩色图像,我们可以先将它变成灰度图像,即将图像中的每个像素的RGB值(红、绿、蓝)转换一个单一的灰度值。但是canny检测出来的边缘噪声比较多,我们再使用高斯滤波模糊下图像,在python使用5×5的高斯滤波器模糊图像最大次数3出现在(2,0°)和(3,90°),则对应图像空间的线为x=2和y=3。

实验内容针对给定视频利用图像处理基本方法实现道路路沿的检测

提示:可利用Hough变换进行线检测,融合路沿的结构信息实现路沿边界定位(图中红色的点位置)。

处理视频文件

处理视频文件的主要流程如下

读取视频逐帧提取路沿检测逐帧保存输出视频

python的OpenCV实现视频文件处理,用videoCapture打开视频文件读取每一帧进行处理然后videoWriter保存视频

路沿检测

路沿检测流程如下

图像预处理边缘检测Hough变换

图像预处理

灰度化

视频中取出的每一帧是彩色图像,我们可以先将它变成灰度图像,即将图像中的每个像素的RGB值(红、绿、蓝)转换一个单一的灰度值。

image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

灰度图像只包含亮度信息如图1所示,而不包含颜色信息。这样可以简化图像,提高处理速度,突出图像的结构,减少噪声干扰。

图1

均衡化

我们再将图像均衡化python代码如下

image = cv2.equalizeHist(image)

图像均衡化可以提高图像的对比度,如图2所示,突出图像的细节轮廓边缘

 

图2

二值化

将灰度图转换为只有黑白两种颜色的图像,python代码如下

image = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)

图像二值化可以简化图像信息,突出物体的轮廓,如图3所示

图3

边缘检测

Canny边缘检测

Canny 边缘检测算法是John F.Canny于1986年开发出来的一个多级边缘检测算法,也被很多人认为是边缘检测的最优算法, 最优边缘检测的三个主要评价标准是:

错误: 标识出尽可能多的实际边缘,同时尽可能的减少噪声产生的误报。

高定位性: 标识出的边缘要与图像中的实际边缘尽可能接近。

最小响应: 图像中的边缘只能标识一次

Canny边缘检测算法步骤如下

高斯滤波去噪计算梯度幅值和方向非极大值抑制阈值处理

高斯滤波器去除噪声

使用高斯滤波器对图像进行平滑处理,以减少噪声影响

计算梯度幅值和方向

按照Sobel算子,运用一对卷积阵列 (分别作用于 xy 方向):

使用下列公式计算梯度幅值和方向:

梯度方向近似到四个可能角度之一(一般 0, 45, 90, 135)。

非极大值抑制

沿边缘垂直方向寻找梯度最大值,排除非边缘像素, 仅仅保留了一些细线条(候选边缘)。

阈值处理

如果某一像素位置的幅值超过高阈值, 该像素被保留为边缘像素。

如果某一像素位置的幅值小于低阈值, 该像素被排除。

如果某一像素位置的幅值在两个阈值之间,该像素仅仅在连接到一个高于高阈值的像素时被保留。

python使用canny对图像进行边缘检测,高阈值为175,低阈值为75。

image = cv2.Canny(image, 75, 175)

效果如图4所示,可见canny算法可以有效的提取图像的边缘信息

图4

但是canny检测出来的边缘中噪声比较多,我们再使用高斯滤波器模糊一下图像,在python使用5×5的高斯滤波器模糊图像。

image = cv2.GaussianBlur(image, (5, 5), 0)

效果如图5所示,可见高斯滤波器模糊成功地去掉了一些噪声。

图5

Hough变换

Hough变换是一种用于检测图像中几何形状技术,将图像由图像空间变换为参数空间。它最初是由保罗·霍夫(Paul Hough)在1962年提出的,用于在图像中检测直线。后来,这个方法扩展到检测其他几何形状,如圆和椭圆

一条直线在图像二维空间可由两个变量表示,在笛卡尔坐标系中直线可由参数斜率k和截距b表示y=kx+b,在极坐标系中可由参数极径r和极角θ表示

对于霍夫变换, 我们将用极坐标系来表示直线,因此直线的表达式可为:

图像空间中的一条线对应Hough空间中的一个点

图像空间中的一个点对应Hough空间中的一条线。

Hough变换的基本思想是将图像中的像素点映射参数空间中,并通过参数空间中寻找峰值来检测几何形状。对于直线检测,参数空间通常是极坐标空间,其中每个像素点在参数空间中对应一条直线。通过遍历图像中的像素点,可以累加参数空间中相应的位置,从而构建一个累加器数组。然后,在累加器数组中找到峰值,这些峰值对应于图像中存在的直线。

Hough变换步骤

离散化θ,θ=-45,0,45,90度。

按照点的坐标x,y)和每个角度θ求极半径r

统计(r,θ)出现的次数

最大次数3出现在(2,0°)和(3,90°),则对应的图像空间的线为x=2和y=3。

Hough变换的优点是它对于噪声和图像变形具有一定的鲁棒性。它可以检测到不完整的、部分可见的或被噪声干扰的几何形状。因此,Hough变换在计算机视觉领域中广泛应用于图像分析目标检测和特征提取任务

标准霍夫线变换

提供一组参数对 (θ, rθ) 的集合表示检测到的直线,在OpenCV 中通过函数 HoughLines实现

lines = cv2.HoughLines(edge, 1, np.pi / 180, 220)

统计概率霍夫线变换

这是执行起来效率更高的霍夫线变换. 它输出检测到的直线的端点 (x0, y0, x1, y1)。在OpenCV 中它通过函数 HoughLinesP来实现。

lines = cv2.HoughLinesP(edge, 1, np.pi / 180, 100, minLineLength=50, maxLineGap=1)

Hough线变换应用路沿检测

本次我们采用标准Hough线变换来检测路沿,经过多次测试和调参,我们最后采用高斯模糊进行图像预处理,然后使用canny进行边缘提取最后使用Hough线变换绘制直线。

def detect(image):

    gauss = cv2.GaussianBlur(image, (5, 5), 0)

    edge = cv2.Canny(gauss, 75, 175)

    # 进行Hough直线变换

    lines = cv2.HoughLines(edge, 1, np.pi / 180, 220)

视频检测效果

第一个视频是一个静止不动的路沿,检测效果如图6所示。

图6

第二个视频中,路沿开始变化起来,检测效果如图7所示。

第三个视频中出现了转弯,检测效果如图8所示,因为我们只做了线变化,因此对于路沿弯曲的部分只能画出直线部分

图8

代码

import cv2
import numpy as np


def detect(image):
    gauss = cv2.GaussianBlur(image, (5, 5), 0)
    edge = cv2.Canny(gauss, 75, 175)
    # 进行Hough直线变换
    lines = cv2.HoughLines(edge, 1, np.pi / 180, 220)
    # 绘制检测到的直线
    if lines is not None:
        for rho, theta in lines[:, 0, :]:
            if theta < 2:
                continue
            a = np.cos(theta)
            b = np.sin(theta)
            x0 = a * rho
            y0 = b * rho
            x1 = int(x0 - 350 * (-b))
            y1 = int(y0 - 350 * a)
            x2 = int(x0 - 700 * (-b))
            y2 = int(y0 - 700 * a)
            cv2.line(image, (x1, y1), (x2, y2), (0, 255, 0), 4)
    return image


video = cv2.VideoCapture('Task2/03.avi')  # 打开视频文件
# 获取视频的宽度高度以及帧率信息
width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = video.get(cv2.CAP_PROP_FPS)
# 创建VideoWriter对象,用于保存处理后的视频
videoWriter = cv2.VideoWriter('Task2/video3.mp4', cv2.VideoWriter_fourcc(*'mp4v'), fps, (width, height))
while True:
    have, frame = video.read()  # 读取当前帧
    if have:
        frame = detect(frame)  # 在这里对每一帧进行处理
        videoWriter.write(frame)  # 将处理后的帧写入输出视频文件
    else:
        break
video.release()  # 释放资源
videoWriter.release()

原文地址:https://blog.csdn.net/weixin_62264287/article/details/134520175

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_25604.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注