采用组合梯度阈值和色彩信息来检测车道,组合梯度阈值组合x灰度梯度、yx灰度梯度、xy灰度梯度和方向梯度信息。
基于梯度:Sobel算子
X方向的Sobel算子检测X方向的梯度;
Y方向的Sobel算子检测Y方向的梯度。
Sobel算子对灰度图进行操作,故需要进行灰度转换:
灰度转换的公式:Gray=R0.299+G0.587+B*0.114
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)#mpimg.imread()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#cv2.imread()
计算x和y方向:
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize = n)#sobelx
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, ksize = n)#sobely
绝对值和8位化:
abs_sobelx = np.absolute(sobelx)
scaled_sobel = np.uint8(255*abs_sobelx/np.max(abs_sobelx)
二值化:
thresh_min = 20
thresh_max = 100
sxbinary = np.zeros_like(scaled_sobel)
sxbinary[(scaled_sobel >= thresh_min) & (scaled_sobel <= thresh_max)] = 1
plt.imshow(sxbinary, cmap='gray')
sobelxy的梯度
sobelxy的计算方式如下:
方向梯度
计算公式:
计算结果在[-pi/2, pi/2]内。
组合梯度信息
def abs_sobel_thresh(img, orient='x', sobel_kernel=3, thresh=(0, 255)):
# Calculate directional gradient
# Apply threshold
return grad_binary
def mag_thresh(image, sobel_kernel=3, mag_thresh=(0, 255)):
# Calculate gradient magnitude
# Apply threshold
return mag_binary
def dir_threshold(image, sobel_kernel=3, thresh=(0, np.pi/2)):
# Calculate gradient direction
# Apply threshold
return dir_binary
# Choose a Sobel kernel size
ksize = 3 # Choose a larger odd number to smooth gradient measurements
# Apply each of the thresholding functions
gradx = abs_sobel_thresh(image, orient='x', sobel_kernel=ksize, thresh=(0, 255))
grady = abs_sobel_thresh(image, orient='y', sobel_kernel=ksize, thresh=(0, 255))
mag_binary = mag_thresh(image, sobel_kernel=ksize, mag_thresh=(0, 255))
dir_binary = dir_threshold(image, sobel_kernel=ksize, thresh=(0, np.pi/2))
######组合
combined = np.zeros_like(dir_binary)
combined[((gradx == 1) & (grady == 1)) | ((mag_binary == 1) & (dir_binary == 1))] = 1
色彩信息
色彩空间
最常见的是RGB色彩空间,由下图的实验可知,B通道对黄色车道线检测不利,选用R通道分析。
RGB色彩空间受阴影的影响大,但是HSV (hue, saturation, and value)和HLS (hue, lightness, and saturation)这两种常用色彩空间则只有V和L通道与阴影相关,完全可以采用HS信息来规避阴影问题。
如图实验可知,S通道可以有效分离黄色车道线。
使用**hls = cv2.cvtColor(im, cv2.COLOR_RGB2HLS)**来获得HLS图片。
import numpy as np
import cv2
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
image = mpimg.imread(r'D:\Study\udacity self-driving\12\straight_lines1.jpg')
# Edit this function to create your own pipeline.
def pipeline(img, s_thresh=(170, 255), sx_thresh=(20, 100), gsx_thresh = (50, 255)):
img = np.copy(img)
# Convert to HSV color space and separate the V channel
hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HLS).astype(np.float)
l_channel = hsv[:,:,1]
s_channel = hsv[:,:,2]
# Sobel x
sobelx = cv2.Sobel(l_channel, cv2.CV_64F, 1, 0) # Take the derivative in x
abs_sobelx = np.absolute(sobelx) # Absolute x derivative to accentuate lines away from horizontal
scaled_sobel = np.uint8(255*abs_sobelx/np.max(abs_sobelx))
# Threshold x gradient
sxbinary = np.zeros_like(scaled_sobel)
sxbinary[(scaled_sobel >= sx_thresh[0]) & (scaled_sobel <= sx_thresh[1])] = 1
# Threshold color channel
s_binary = np.zeros_like(s_channel)
s_binary[(s_channel >= s_thresh[0]) & (s_channel <= s_thresh[1])] = 1
# Note color_binary[:, :, 0] is all 0s, effectively an all black image. It might
# be beneficial to replace this channel with something else.
#Threshold gray sobelx channel
gsobelx = cv2.Sobel(cv2.cvtColor(img, cv2.COLOR_RGB2GRAY).astype(np.float), cv2.CV_64F, 1, 0)
abs_gsobelx = np.absolute(gsobelx)
scaled_gsobelx = np.uint8(255*abs_gsobelx/np.max(abs_gsobelx))
gsxbinary = np.zeros_like(scaled_gsobelx)
gsxbinary[(scaled_gsobelx >= gsx_thresh[0]) & (scaled_gsobelx <= gsx_thresh[1])] = 1
# Stack each channel
color_binary = np.dstack(( gsxbinary, sxbinary, s_binary))
return gsxbinary, color_binary
g, result = pipeline(image)
# Plot the result
f, (ax1, ax2) = plt.subplots(1, 2, figsize=(24, 9))
f.tight_layout()
ax1.imshow(image)
ax1.set_title('Original Image', fontsize=40)
# ax2.imshow(result)
# ax2.set_title('Pipeline Result', fontsize=40)
# plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
# plt.show()
gray = np.zeros_like(result[:,:,0])
gray[(result[:,:,0]==1)|(result[:,:,1]==1)|(result[:,:,2]==1)]=1
ax2.imshow(gray)
ax2.set_title('Pipeline Result', fontsize=40)
plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
plt.show()