@Author:Runsen

霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,该过程在一个參数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换结果。

这张图里面有一条看起来挺直的线,就是车道,这张图是百度随便找的。

灰度缩放

将图像转换为灰度的原因是易于处理。与具有三个以上值的彩色图像相比,灰度图像只有一个像素强度值(0 或 1)。这将使灰度图像在单个通道中工作,这将比三个通道的彩色图片更容易和更快地处理。

在代码中创建的图像数组。

import cv2
import numpy as npimage = cv2.imread('lane.jpg')
lane_image = np.copy(image)
# 借助cvtColor openCV 库中的函数将图像转换为灰度。
gray = cv2.cvtColor(lane_image, cv2.COLOR_RGB2GRAY) cv2.imshow('result', gray) #to output gray-scale image
cv2.waitKey(0)

运行这个程序,得到的图像应该如下所示。

减少噪音和平滑

在识别图像中,减少噪音和平滑很重要。这种降噪和图像平滑化将通过称为高斯模糊的过滤器来完成。

图像存储为离散像素的集合。灰度图像中的每个像素都由一个描述像素亮度的数字表示。为了平滑图像,我们需要使用周围像素强度的平均值来修改像素的值。

在cv2.GaussianBlur()在灰度图像上应用函数。

在这里,我们在图像上应用 5 * 5 内核窗口。内核的大小取决于情况,但 5*5 窗口对于大多数情况是理想的。我们将blur变量传递给以imshow()获取输出。因此,获得高斯模糊图像的最终代码如下所示:

#coding=gbk
import cv2
import numpy as npimage = cv2.imread('lane.jpg')
lane_image = np.copy(image)
# 借助cvtColor openCV 库中的函数将图像转换为灰度。
gray = cv2.cvtColor(lane_image, cv2.COLOR_RGB2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
cv2.imshow('result', blur)
cv2.waitKey(0)

Canny 边缘检测

在图像中,X 对应于图像中的宽度(列数),Y 对应于图像的高度(行数)。宽度和高度的乘积为我们提供了图像中的像素总数。因此可以表示为 X 和 Y 的连续函数,即;f(x, y)。

由于f(x, y)是一个数学函数,我们可以执行运算来确定图像中像素亮度的快速变化。Canny 方法将在 x 和 y 方向上为我们提供函数的导数。我们可以使用这个导数来测量与相邻像素有关的强度变化。

通过计算各个方向的导数,调用cv2.Canny(),我们得到图像的梯度。

cv2.Canny(image, low_threshold, high_threshold)

两个参数low_threshold并high_threshold 允许我们遵循最强gradience相邻像素隔离。如果梯度大于阈值上限,则将其识别为边缘像素。如果低于下限,则会被拒绝。

我们将采用 1:3 的低高阈值比率。这次我们输出的是canny图像

canny = cv2.Canny(blur, 50, 150)
cv2.imshow('result', canny)
cv2.waitKey(0)

ROI

模型检测之前,我们必须指定我们有兴趣检测车道线的区域(ROI)。

在这种情况下,我们将感兴趣的区域作为道路的中间,如图所示。

为找到我们感兴趣区域的位置,使用matplotlib库来定位坐标并隔离该区域。

import cv2
import numpy as np
import matplotlib.pyplot as pltdef canny(image):gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)blur = cv2.GaussianBlur(gray, (5, 5), 0)canny = cv2.Canny(blur, 50, 150)return cannyimage = cv2.imread('lane.jpg')
lane_image = np.copy(image)
canny = canny(lane_image)
plt.imshow(canny)
plt.show()


现在我们已经获得了 ROI 所需的测量值,我们将生成一个图像来掩盖其他所有内容。我们得到的图像是原始图像中具有指定顶点的多边形的蒙版。

下面的代码的像素坐标是随便找的。

import cv2
import numpy as np
import matplotlib.pyplot as pltdef canny(image):gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)blur = cv2.GaussianBlur(gray,(5, 5), 0)canny = cv2.Canny(blur, 50, 150)return cannydef region_of_interest(image):polygons = np.array([[(0, 380), (300, 100),(400, 100), (620, 430)]])mask = np.zeros_like(image)cv2.fillPoly(mask, polygons, 255)masked_image = cv2.bitwise_and(image, mask)return masked_imageimage = cv2.imread('lane.jpg')
lane_image = np.copy(image)canny_image = canny(lane_image)
cropped_image = region_of_interest(canny_image)
cv2.imshow('result',cropped_image)
cv2.waitKey(0)


通过利用cv2.bitwise_and() 的函数来实现这一点,该函数计算两个图像的按位 &以仅显示由掩码的多边形轮廓跟踪的 ROI。

虽然说图片上还有一些车,但是影响不大,最后一步是使用霍夫变换来检测我们感兴趣的孤立区域中的直线。

霍夫变换

现在拥有的图片只是一系列像素,我们无法直接找到几何表示来了解斜率和截距。

由于算法时间复杂度的关系,我们不能暴力遍历像素来找到斜率和截距,因此可以使用霍夫变换的地方。它帮助我们找出突出的线条并连接图像中不相交的边缘点。

霍夫变换就是一个斜率和截距转换成为x和y的过程。


XY 平面中的一个点可以有任意数量的线穿过它。为了识别图片中的线条,我们必须将每个边缘像素想象为坐标空间中的一个点,然后将该点转换为霍夫空间中的一条线。

只要所有线都经过一个点,那么这些线的斜率和截距,在霍夫变换必然呈现一条线。


我们需要在 XY 平面上找到两条或更多条线,来表示它们在霍夫空间中相交的对应点,就可以检测线。

这是因为两个点可以确定同一条直线。

在openCV 已经有一个被调用的函数cv2.HoughLinesP(),

lines = cv2.HoughLinesP(cropped_image, 2, np.pi/180, 100, np.array([]), minLineLength=40, maxLineGap=5)
  • 第一个参数是之前生成的裁剪图像,它是孤立车道线的梯度图像。

  • 第二个和第三个参数指定霍夫累加器数组(为识别大多数交叉点而创建的网格)的分辨率。

  • 第四个参数是确定检测线路所需的最小投票数所需的阈值。

我们将定义 3 个函数来优化和显示车道线。

display_lines:这个函数来用与原始图像相似的测量值标记黑色图像上的线条,然后将其混合到我们的彩色图像中。

def display_lines(image, lines):line_image = np.zeros_like(image)if lines is not None:for x1, y1, x2, y2 in lines:cv2.line(line_image, (x1, y1), (x2, y2), (255, 0, 0), 10)return line_image

make_coordinates:这将为我们指定坐标,能够标记斜率和 y 轴截距。

def make_coordinates(image, line_parameters):slope, intercept = line_parametersy1 = image.shape[0]y2 = int(y1*(3/5))x1 = int((y1 - intercept)/slope)x2 = int((y2 - intercept)/slope)return np.array([x1, y1, x2, y2])

average_slope_intercept:声明了两个空的名单-left_fit和right_fit这将右分别包含左侧的平均线和线的坐标上的坐标。

def average_slope_intercept(image, lines):left_fit = []right_fit = []for line in lines:x1, y1, x2, y2 = line.reshape(4)parameters = np.polyfit((x1, x2), (y1, y2), 1)slope = parameters[0]intercept = parameters[1]if slope < 0:left_fit.append((slope, intercept))else:right_fit.append((slope, intercept))left_fit_average = np.average(left_fit, axis=0)right_fit_average = np.average(right_fit, axis=0)left_line = make_coordinates(image, left_fit_average)right_line = make_coordinates(image, right_fit_average)return np.array([left_line, right_line])

霍夫变换技术实现直线检测的完整代码:

import cv2
import numpy as npdef make_coordinates(image, line_parameters):slope, intercept = line_parametersy1 = image.shape[0]y2 = int(y1*(3/5))x1 = int((y1 - intercept)/slope)x2 = int((y2 - intercept)/slope)return np.array([x1, y1, x2, y2])def average_slope_intercept(image, lines):left_fit = []right_fit = []for line in lines:x1, y1, x2, y2 = line.reshape(4)parameters = np.polyfit((x1, x2), (y1, y2), 1)slope = parameters[0]intercept = parameters[1]if slope < 0:left_fit.append((slope, intercept))else:right_fit.append((slope, intercept))left_fit_average = np.average(left_fit, axis=0)right_fit_average = np.average(right_fit, axis=0)left_line = make_coordinates(image, left_fit_average)right_line = make_coordinates(image, right_fit_average)return np.array([left_line, right_line])def canny(image):gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)blur = cv2.GaussianBlur(gray,(5, 5), 0)canny = cv2.Canny(blur, 50, 150)return cannydef display_lines(image, lines):line_image = np.zeros_like(image)if lines is not None:for x1, y1, x2, y2 in lines:cv2.line(line_image, (x1, y1), (x2, y2), (255, 255, 255), 10)return line_imagedef region_of_interest(image):polygons = np.array([[(0, 380), (300, 100),(400, 100), (620, 430)]])mask = np.zeros_like(image)cv2.fillPoly(mask, polygons, 255)masked_image = cv2.bitwise_and(image, mask)return masked_imageimage = cv2.imread('lane.png')
lane_image = np.copy(image)canny_image = canny(lane_image)
cropped_image = region_of_interest(canny_image)
lines = cv2.HoughLinesP(cropped_image, 2, np.pi/180, 100, np.array([]), minLineLength=40, maxLineGap=5)
averaged_lines = average_slope_intercept(lane_image, lines)
line_image = display_lines(lane_image, averaged_lines)combo_image = cv2.addWeighted(lane_image, 0.8, line_image, 1, 1)cv2.imshow('result',combo_image)
cv2.waitKey(0)

检测视频中的车道

#coding=gbk
'''
@Author:Runsen
'''
import cv2
import numpy as npdef make_coordinates(image, line_parameters):slope, intercept = line_parametersy1 = image.shape[0]y2 = int(y1*(3/5))x1 = int((y1 - intercept)/slope)x2 = int((y2 - intercept)/slope)return np.array([x1, y1, x2, y2])def average_slope_intercept(image, lines):left_fit = []right_fit = []for line in lines:x1, y1, x2, y2 = line.reshape(4)parameters = np.polyfit((x1, x2), (y1, y2), 1)slope = parameters[0]intercept = parameters[1]if slope < 0:left_fit.append((slope, intercept))else:right_fit.append((slope, intercept))left_fit_average = np.average(left_fit, axis=0)right_fit_average = np.average(right_fit, axis=0)left_line = make_coordinates(image, left_fit_average)right_line = make_coordinates(image, right_fit_average)return np.array([left_line, right_line])def canny(image):gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)blur = cv2.GaussianBlur(gray,(5, 5), 0)canny = cv2.Canny(blur, 50, 150)return cannydef display_lines(image, lines):line_image = np.zeros_like(image)if lines is not None:for x1, y1, x2, y2 in lines:cv2.line(line_image, (x1, y1), (x2, y2), (255, 255, 255), 10)return line_imagedef region_of_interest(image):height = image.shape[0]polygons = np.array([[(200, height), (1100, height), (550, 250)]])mask = np.zeros_like(image)cv2.fillPoly(mask, polygons, 255)masked_image = cv2.bitwise_and(image, mask)return masked_imagecap = cv2.VideoCapture('test2.mp4')
while(cap.isOpened()):_, frame = cap.read()canny_image = canny(frame)cropped_image = region_of_interest(canny_image)lines = cv2.HoughLinesP(cropped_image, 2, np.pi/180, 100, np.array([]), minLineLength=40, maxLineGap=5)averaged_lines = average_slope_intercept(frame, lines)line_image = display_lines(frame, averaged_lines)combo_image = cv2.addWeighted(frame, 0.8, line_image, 1, 1)cv2.imshow('result',combo_image)if cv2.waitKey(1) == ord('q'):break
cap.release()
cv2.destroyAllWindows()

深度学习和目标检测系列教程 20-300:OpenCV与图像处理:霍夫变换技术实现直线检测相关推荐

  1. 综述 | 基于深度学习的目标检测算法

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:计算机视觉life 导读:目标检测(Object Det ...

  2. 基于深度学习的目标检测的研究进展2

    普通的深度学习监督算法主要是用来做分类,如图1(1)所示,分类的目标是要识别出图中所示是一只猫.而在ILSVRC(ImageNet Large Scale Visual Recognition Cha ...

  3. 基于深度学习的目标检测研究进展

    前言 开始本文内容之前,我们先来看一下上边左侧的这张图,从图中你看到了什么物体?他们在什么位置?这还不简单,图中有一个猫和一个人,具体的位置就是上图右侧图像两个边框(bounding-box)所在的位 ...

  4. 基于深度学习的目标检测算法综述(从R-CNN到Mask R-CNN)

    深度学习目标检测模型全面综述:Faster R-CNN.R-FCN和SSD 从RCNN到SSD,这应该是最全的一份目标检测算法盘点 基于深度学习的目标检测算法综述(一) 基于深度学习的目标检测算法综述 ...

  5. 【深度学习】基于深度学习的目标检测研究进展

    原文出处:http://chuansong.me/n/353443351445 开始本文内容之前,我们先来看一下上边左侧的这张图,从图中你看到了什么物体?他们在什么位置?这还不简单,图中有一个猫和一个 ...

  6. 基于深度学习的目标检测方法综述

    引言 现有的深度学习的目标检测方法,可以大致分为两类:一.基于候选区域的目标检测方法:二.基于回归的目标检测方法.依据方法的提出时间,可以构建出如下时间线: 2014 CVPR R-CNN[1] 20 ...

  7. 深度学习之目标检测:R-CNN、Fast R-CNN、Faster R-CNN

    object detection 就是在给定的图片中精确找到物体所在位置,并标注出物体的类别.object detection 要解决的问题就是物体在哪里,是什么这整个流程的问题.然而,这个问题不是容 ...

  8. 基于深度学习的目标检测技术演进:从目标检测到人脸检测

    本篇博客主要转载两篇写得好的分别介绍基于深度学习的目标检测和人脸检测的文章,最近在调研基于深度学习的人脸检测相关的文章,在网上查相关资料时,有幸看到.文末附带基于深度学习的目标检测和人脸检测相关经典文 ...

  9. 独家总结| 基于深度学习的目标检测详解

    欢迎关注微信公众号[计算机视觉联盟] 获取更多前沿AI.CV资讯                                                基于深度学习的目标检测 基于深度学习的目 ...

最新文章

  1. java测试时间的类,java 测试五种单例模式需要的时间
  2. python下载文件到指定目录-python – 如何将文件下载到特定目录?
  3. 安卓工控主板双网口有什么用途?
  4. 17.explain_api
  5. 数据结构 平衡二叉树avl c++
  6. 测试开发:聊一聊自动化测试框架,值得收藏!
  7. jquery开发手册(详细全面)
  8. 计算机游戏设计专业世界大学排名,看过来,世界五大顶尖游戏设计大学在这里...
  9. django + mysql8修改数据库密码
  10. 忘记了已保存自动登录的密码,怎么办?
  11. 蛋白质语言建模?伯克利RoshanRao157页博士论文《训练,评估和理解蛋白质序列的进化模型》...
  12. 《 指数基金投资指南 》by 银行螺丝钉 - 笔记 - 1、2章
  13. PID闭环底盘调试记录
  14. 【MySQL】创建高性能的索引
  15. VR和AR已从概念转为真正走进人们生活的实际应用
  16. 双鱼林 android 服务器,双鱼林安卓Android代码生成器下载_双鱼林安卓Android代码生成器官方下载-太平洋下载中心...
  17. IDEA 安装快捷键提示工具:Key promoter X
  18. C语言笔记-26-网络-UDP网络编程
  19. HDLBits第十四章练习及答案3
  20. 函数式编程-Stream流(来源三更草堂)

热门文章

  1. Unity3D——学习分享(一) 游戏开发
  2. java象棋实验报告_中国象棋java程序设计实验报告
  3. Windows10 会不会成为微软的新起点?
  4. 【JAVA】逻辑控制
  5. samba服务器搭建详细配置
  6. 响应式(自适应屏幕)
  7. ZZULIOJ:1015 计算时间间隔
  8. JAVA技术及其应用实验三(抽象类和匿名类)
  9. Oracle 常见错误总结及问题解决方法
  10. 数据脱敏为何如此重要?