欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

(四)Canny边缘检测及ROI区域选择

程序员文章站 2024-01-28 09:56:52
...

Canny边缘检测

边缘检测是车道线识别中一个非常重要的项目。Canny边缘检测是基于求梯度变化最大值的方法来实现边缘检测,其基本原理就是对图像中各个点求梯度,梯度最大的地方就是边缘。

图像中的边界和边缘

边界和边缘不同,边界是与区域有关的全局概念,而边缘表示图像函数的局部性质;边界与边缘也相互关联,一种寻找边界的方法是连接显著的边缘。
边界(border)
区域R的边界是自身的像素集合,其中的每个点具有一个或者多个的R的外接领域点。检测图像中的对象边界,更偏向于关注上层语义对象
边缘(edge)
边缘是图像上灰度不连续的点,或者灰度变化剧烈的地方,他是一个由大小和方向的矢量。
物体边界检测如下图:
(四)Canny边缘检测及ROI区域选择
物体边缘检测如下:
(四)Canny边缘检测及ROI区域选择

边缘检测原理

在边缘点附近信号具有频域的高频分量,所有边缘检测方法在本质上都是检测信号的高频。边缘检测的难点在于区分信号的高频和噪声,因此需要对其进行提前的噪声消除处理如高斯平滑滤波进行图像的预处理。吐过检测图像上灰度不连续的点,或者是灰度剧烈变化处来达到边缘检测的目的。
(四)Canny边缘检测及ROI区域选择
边缘的数学表达:信号一阶微分最大值或两阶微分过零点处。
(四)Canny边缘检测及ROI区域选择

一、Canny基本思想

1. 边缘检测
解析:边缘是对象和背景之间的边界,还能表示重叠对象之间的边界。边缘检测是图像分割的一部分,图像分割的目的是识别出图像中的区域。边缘检测是定位边缘像素的过程,而边缘增强是增加边缘和背景之间的对比度以便能够更清楚地看清边缘的过程。边缘跟踪是沿着边缘进行跟踪的过程,这个过程通常会把边缘像素采集到一个列表中,链码算法是边缘跟踪算法的一个特例。
2. 最优边缘准则 [1]
Canny边缘检测算子是John F. Canny于1986年开发出来的一个多级边缘检测算法。Canny的目标是找到一个最优的边缘检测算法,最优边缘检测的含义,如下所示:
(1)最优检测:算法能够尽可能多地标识出图像中的实际边缘,漏检真实边缘的概率和误检非边缘的概率都尽可能小;
(2)最优定位准则:检测到的边缘点的位置距离实际边缘点的位置最近,或者是由于噪声影响引起检测出的边缘偏离物体的真实边缘的程度最小;
(3)检测点与边缘点一一对应:算子检测的边缘点与实际边缘点应该是一一对应。

二、Canny算法实现

1. 高斯滤波图像去噪
垃圾进,垃圾出,数据预处理工作是非常重要的,图像处理也不例外。这里使用高斯滤波进行图像去噪,比如blur = cv2.GaussianBlur(img, (5,5), 0),处理后的图像与原始图像相比稍微有些模糊。这样单独的一个像素噪声在经过高斯滤波的图像上变得几乎没有影响。

2. 计算图像梯度
Canny算法的基本思想是找寻一幅图相中灰度强度变化最强的位置。所谓变化最强,即指梯度方向。对平滑后的图像使用Sobel算子计算水平方向和竖直方向的一阶导数(图像梯度)(Gx和Gy)。根据得到的这两幅梯度图(Gx和Gy)找到边界的梯度和方向。如下所示:
(四)Canny边缘检测及ROI区域选择
(四)Canny边缘检测及ROI区域选择
梯度的方向一般总是与边界垂直。梯度方向被归为四类:垂直,水平,和两个对角线。

3. 非极大值抑制
在获得梯度的方向和大小之后,应该对整幅图像做一个扫描,去除那些非边界上的点。对每一个像素进行检查,看这个点的梯度是不是周围具有相同梯度方向的点中最大的。如下所示:
(四)Canny边缘检测及ROI区域选择

上图中的数字代表了像素点的梯度强度,箭头方向代表了梯度方向。以第二排第三个像素点为例,由于梯度方向向上,则将这一点的强度(7)与其上下两个像素点的强度(5和4)比较,由于这一点强度最大,则保留。

4. 滞后阈值
现在要确定那些边界才是真正的边界。这时我们需要设置两个阈值:minVal和maxVal。当图像的灰度梯度高于maxVal时被认为是真的边界,那些低于minVal的边界会被抛弃。如果介于两者之间的话,就要看这个点是否与某个被确定为真正的边界点相连,如果是就认为它也是边界点,如果不是就抛弃。如下所示:
(四)Canny边缘检测及ROI区域选择
A高于阈值maxVal所以是真正的边界点,C虽然低于maxVal但高于minVal并且与A相连,所以也被认为是真正的边界点。而B就会被抛弃,因为它不仅低于maxVal而且不与真正的边界点相连。所以选择合适的maxVal和minVal对于能否得到好的结果非常重要。在这一步一些小的噪声点也会被除去,因为我们假设边界都是一些长的线段。
(四)Canny边缘检测及ROI区域选择
(四)Canny边缘检测及ROI区域选择
4. 算法框架
(四)Canny边缘检测及ROI区域选择
(四)Canny边缘检测及ROI区域选择
使用Opencv自带的函数进行设置:
cv2.Canny(image,threshold1,threshold2)
其中threshold2用于检测图像中明显的边缘,但一遍情况下检测效果不会那么完美,呈现断断续续的状态,因此使用threshold1用于将间断的边缘连接起来。

# Canny edge detection high threshold
# Canny 边缘检测高阈值
canny_lthreshold = 50  
canny_hthreshold = 150  
#blur_gray为高斯平滑处理后的图片
edges = cv2.Canny(blur_gray, canny_lthreshold, canny_hthreshold)

可得到如图所示的效果
(四)Canny边缘检测及ROI区域选择

三、基于ROI的去除其他不感兴趣区域边缘线

在进行边缘检测时,图像中存在很多对于我们不感兴趣的区域,去除掉这些区域可以有效的提高检测效率与速度。在车道线检测实例中,我们只关心车道线,由于camera相对车是固定的,而无人车相对车道的左右也是基本固定的,所以车道在camera视频中基本保持在一个固定的区域内,据此我们可以绘制出一个大搞的Region of interest(ROI),过滤掉ROI之外的edges。最终效果
(四)Canny边缘检测及ROI区域选择

#**********************选取关键兴趣区域,减少计算量***********************
def roi_mask(img, vertices):
  #定义mask全为黑
  mask = np.zeros_like(img)
  #defining a 3 channel or 1 channel color to fill the mask with depending on the input image
  if len(img.shape) > 2:
    channel_count = img.shape[2]  # i.e. 3 or 4 depending on your image
    mask_color = (255,) * channel_count
  else:
    mask_color = 255
  #将区域和图片进行填充fillPoly和叠加and
  cv2.fillPoly(mask, vertices, mask_color)
  masked_img = cv2.bitwise_and(img, mask)
  return masked_img
# edges为进过边缘处理的图像,可以修改提前处理
# roi_vtx 为设置的感兴趣的roi区域
# roi_edges 裁剪过的车道线图像
roi_vtx = np.array([[(0, img.shape[0]), (460, 325), (520, 325), (img.shape[1], img.shape[0])]])
roi_edges = roi_mask(edges, roi_vtx)