Mitchy
今日もキラキラしていこう♪

梯度:

之前前言里的边界检测能检测到很多边界,不仅是道路线的还包括了各种景物,车,路标等干扰因素。

但是我们知道我们要找的道路线应该是相对比较垂直于路面的,所以我们可以把找到的线和图片的x轴和y轴再计算梯度。

索贝尔算子(Sobel Operator):

  两个大于等于3并且大小为奇数的方形矩阵,用和图像的乘积来判断在矩阵范围内,图像的颜色在x轴和y轴方向上的变化大小。

  如果结果矩阵各数值之和为0说明图像颜色在该轴上没有变化。

  默认的算子矩阵大小(kernel size)是3,如果加大的话可以平滑一些无用的强烈梯度。

有用的函数:

  gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

  注:如果是用mpimg.imread()读的图片那么用cv2.COLOR_RGB2GRAY,如果用cv2.imread()读的图片那么用cv2.COLOR_BGR2GRAY。

  在x和y方向上的梯度:

    sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)

    sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)

  abs_sobelx = np.absolute(sobelx)

  scaled_sobel = np.uint8(255*abs_sobelx/np.max(abs_sobelx)) (注:这虽然不是必须的但是统一规格有助于以后统一阈值)

  thresh_min = 20

  thresh_max = 100

  sbinary = np.zeros_like(scaled_sobel)

  sbinary[(scaled_sobel >= thresh_min) & (scaled_sobel <= thresh_max)] = 1

  plt.imshow(sxbinary, cmap='gray')

由实验可知,道路线会在x轴梯度上更明显,但是y轴梯度上也能看到。

梯度的大小(绝对值)可通过梯度的平方开根号得到。如果是计算两轴的梯度大小,那么就是梯度平方和开根号。

梯度的方向就是arctan(sobely/sobelx),理论上计算结果的范围在+/π之间,但是由于sobelx会被取绝对值所以结果会在+/π/2之间。

代码中用np.arctan2().

将梯度大小,两轴梯度大小和方向的阈值结合,调整参数至可以检测出道路线

 

颜色空间:

前面我们将图片转化为灰度图之后损失了颜色信息,有时候这可能会让我们更难分辨出道路线(如黄色的线变成灰度之后颜色会和灰色的道路很接近),所以我们需要颜色空间为我们提供更多的信息。

除了RGB之外,还有HSV (hue色相, saturation饱和度, value明度) 和HLS (hue色相, lightness亮度, saturation饱和度) 颜色空间。

色相指的是和亮度无关的颜色,也就是说往该颜色上加黑色或者白色,将颜色变得更深或者更浅,对色相是没有影响的。

明度和亮度都是用来表示颜色的明暗或者深浅。

饱和度指的是颜色的鲜艳程度,比如和白色更接近的颜色饱和度更低,和亮红,亮黄,亮蓝接近的颜色饱和度高。

这些颜色的表达方法是通过人类视觉感知或者是为了电视视频/电脑图像的显示而被开发出来的。

有用的函数:

  hls = cv2.cvtColor(im, cv2.COLOR_RGB2HLS) (这里顺便会把RGB值转化为0-1之间的值)

也可以使用纯数学的方法完成转换,要知道的是RGB值,算出其中最大的值(Vmax = max(R,G,B))和最小的值(Vmin = min(R,G,B))之后进行一系列运算。

 

通过比较用颜色值的阈值(分0,1)提取R,G,B,灰度图,H,L,S图中的道路线,会发现S图出的效果最好,而且稳定性也好(不会因为光线影响结果)。

但是R图在白线的处理上可能比S图的结果还好,所以可以考虑结合各种图像的阈值得到一个稳定的结果。

 

posted on 2020-12-17 21:59  Mitchy  阅读(380)  评论(0编辑  收藏  举报