转载请注明出处 https://blog.youkuaiyun.com/gloria_iris/article/details/91625656
本博文主要使用canny变换和hough变换实现车道线检测。简单识别程序可参考车道线识别(一) 简单识别
1. canny边缘检测
边缘检测的目标是识别图像中物体的边界。边缘检测前需要将图像转换为灰度图像,然后计算图像的梯度值,图像像素的亮度值对应着该点的梯度值,通过寻找最大的梯度值,可以找到边缘。识别边缘后,可以根据物体形状检测对象。
边缘强度:图像相邻像素间值得差异程度,实际上就是该点的梯度值。图1将以动图的方式解释canny边缘检测的具体原理:

具体代码
# doing all the relevant imports
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import cv2
# Read in the image and convert to grayscale
image = mpimg.imread('exit-ramp.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
# Define a kernel size for Gaussian smoothing / blurring
# Note: this step is optional as cv2.Canny() applies a 5x5 Gaussian internally
kernel_size = 3
blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size), 0)
# Define parameters for Canny and run it
# NOTE: if you try running this code you might want to change these!
low_threshold = 50
high_threshold = 150
edges = cv2.Canny(blur_gray, low_threshold, high_threshold)
# Display the image
plt.imshow(edges, cmap='Greys_r')
plt.show()
2. Hough变换
霍夫变换是一种从图像空间到霍夫空间的转换,在图像空间的一条直线,在霍夫空间就是位于m-b坐标上的一个点。如何查找图像空间中的直线呢?首先需要运行Canny边缘检测算法,找到图像中所有位于边缘的点。边缘检测图像中的每个点在hough空间是一条直线,如果在霍夫空间找到一个有多条直线交叉的位置,就可以认为在图像空间中找到了一组直线的点集。

由于垂直线的斜率为无穷大,无法用参数m-b表示,因而在极坐标中重新定义直线,变量表示直线与原点之间的垂直距离,
是直线与水平方向之间的夹角。图像空间中的每一个点对应霍夫空间中的一条正弦曲线,图像空间中一条直线上所有的点,等价于霍夫空间中的多个正弦曲线。同样地,在
-
空间中,正弦曲线交点的位置就是这条直线在霍夫空间中的参数。


若图像空间是一个矩形框构成的点集,则在霍夫空间的曲线上有四个主要交叉点,具体如下图C。

在霍夫空间进行直线查找时,需设置一些参数,如线段长短、虚实等。在OpenCV中使用HoughLinesP设置参数,具体形式为:
lines = cv2.HoughLinesP(masked_edges, rho, theta, threshold, np.array([]),
min_line_length, max_line_gap)
具体实现代码:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import cv2
# Read in and grayscale the image
image = mpimg.imread('exit-ramp.jpg')
gray = cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
# Define a kernel size and apply Gaussian smoothing
kernel_size = 5
blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0)
# Define our parameters for Canny and apply
low_threshold = 50
high_threshold = 150
edges = cv2.Canny(blur_gray, low_threshold, high_threshold)
# Next we'll create a masked edges image using cv2.fillPoly()
mask = np.zeros_like(edges)
ignore_mask_color = 255
# This time we are defining a four sided polygon to mask
imshape = image.shape
vertices = np.array([[(0,imshape[0]),(450, 290), (490, 290), (imshape[1],imshape[0])]], dtype=np.int32)
cv2.fillPoly(mask, vertices, ignore_mask_color)
masked_edges = cv2.bitwise_and(edges, mask)
# Define the Hough transform parameters
# Make a blank the same size as our image to draw on
rho = 2 # distance resolution in pixels of the Hough grid
theta = np.pi/180 # angular resolution in radians of the Hough grid
threshold = 15 # minimum number of votes (intersections in Hough grid cell)
min_line_length = 40 #minimum number of pixels making up a line
max_line_gap = 20 # maximum gap in pixels between connectable line segments
line_image = np.copy(image)*0 # creating a blank to draw lines on
# Run Hough on edge detected image
# Output "lines" is an array containing endpoints of detected line segments
lines = cv2.HoughLinesP(masked_edges, rho, theta, threshold, np.array([]),
min_line_length, max_line_gap)
# Iterate over the output "lines" and draw lines on a blank image
for line in lines:
for x1,y1,x2,y2 in line:
cv2.line(line_image,(x1,y1),(x2,y2),(255,0,0),10)
# Create a "color" binary image to combine with line image
color_edges = np.dstack((edges, edges, edges))
# Draw the lines on the edge image
lines_edges = cv2.addWeighted(color_edges, 0.8, line_image, 1, 0)
plt.imshow(lines_edges)
plt.show()
