在OpenCV中实现的不同边缘检测技术

在视觉处理的早期阶段,图片中的特征被识别出来,这些特征对于确定场景中物体的结构和质量具有重要意义。边缘就是这样的一个特征。边缘是图片中实质性的局部改变,对图像分析很有用。边缘经常出现在图片的两个不同部分之间的边界上。从照片中检索信息的最初阶段通常是边缘检测。在这篇文章中,我们将重点了解OpenCV所提供的边缘检测的概念和技术。以下是将要涉及的主题。

内容列表

  1. 关于边缘检测
  2. 边缘检测的不同技术
  3. 边缘检测是如何工作的?
  4. 用OpenCV学习边缘检测

图像中的一个边缘点是图片中的一个点,其坐标位于局部强度大幅偏移的位置。让我们先来了解一下边缘的概念和由它们获得的信息。

关于边缘检测

边缘检测是图像处理中用来确定图像内物体或区域的边界(边缘)的一种方法。边缘是照片中最重要的方面之一。

图像边缘是图片强度的一个大的局部移动,它经常与图像强度或第一导数(梯度)的不连续有关。图像强度的不连续可以是由于阶梯不连续或线条不连续。

  • 当图像强度从不连续的一侧的一个值迅速转移到不连续的另一侧的不同值时,就会发生阶梯不连续。
  • 线状不连续发生在视觉强度迅速变化但在很短的距离后又回到其初始值。

然而,在现实世界的照片中,台阶和线条的边界并不常见。由于大多数传感设备引入的低频成分或平滑,实际信号中的尖锐不连续现象并不常见。如果强度变化发生在有限的距离内而不是瞬间,那么台阶边缘就会变成斜坡边缘,而线条边缘就会变成屋顶边缘。

印度分析杂志

为什么需要进行边缘检测?

边缘检测使用户能够检查图片特征在灰度上的实质性变化。这种纹理标志着图片的一个部分的结束和另一个部分的开始。它减少了图片中的数据量,同时保留了图片的结构特征。

例如,在检测指纹时,用边缘检测对图片进行预处理是有好处的。这个例子中的 "边缘 "是指指纹的轮廓,而不是产生指纹的背景。这可以减少噪音,让机器只关注指纹的轮廓。

你是否在寻找一个完整的数据科学中使用的Python库。请看这里.

边缘检测的不同技术

边缘检测可分为两部分:梯度和高斯。

梯度

识别图片中实质性的局部变化的操作被称为边缘检测。一个维度上的阶梯式边缘对应于第一导数的局部峰值。梯度是一个函数变化的度量,图像可以被认为是图像强度的连续函数的样本阵列。梯度的离散近似值可用于识别图片中灰度等级的实质性变化。梯度被定义为矢量,是一阶导数的二维等价物。梯度有两个关键属性。

  1. 矢量指向坐标函数的最高上升率的方向。
  2. 梯度的大小等于坐标函数在矢量方向上每单位距离的最高上升率。

然而,通常的做法是用绝对值来近似计算梯度的大小。梯度的方向通过矢量分析确定为相对于X轴的角度。梯度的大小与边缘的方向无关。这些被称为各向同性的算子。有三个算子用于推导第一导数,它们是索贝尔算子、普雷维特算子、罗伯特算子

  • Robert的交叉算子简单地逼近梯度大小。它是一个具有2×2矩阵的梯度算子。内插点被用来计算差值。罗伯茨算子近似于该点的连续梯度,而不是在点上。
  • 梯度的大小由Sobel算子表示。使用3 x 3的邻域来计算梯度,可以避免在像素之间的内插点上计算梯度。考虑到像素的周围是如何排列的。这个算子强调了最接近遮罩中心的像素。最常见的边缘检测器之一是Sobel算子。
  • Prewitt算子采用了与Sobel算子相同的方程,例外的是常数为1。与索贝尔算子不同的是,这个算子不会将任何焦点放在蒙版中心的像素上。

高斯

前面提到的边缘检测器计算第一导数,如果大于某个阈值,就认为存在一个边缘点。因此,检测到的边缘点数量过多。一个更好的策略是只发现和检查局部梯度值达到最大值的地方。

这意味着在边缘点,第一导数将有一个峰值,第二导数将有一个零交叉。因此,边缘点可以通过定位图片强度的二阶导数的零交叉点来识别。二次导数由两个二维运算符表示:高斯的拉普拉斯和康尼边缘检测器。

  • Canny边缘检测器是一个高斯一阶导数,近似于优化信噪比和定位的乘积的算子。采用可分离滤波将图片与高斯平滑滤波器进行卷积的结果是一个平滑的数据阵列。使用2 x 2第一差分近似,可以确定平滑阵列的梯度,产生两个偏导数的阵列。

有限差分在2 x 2的方阵中被平均化,以计算图像中同一位置的偏导数。梯度的大小和方向可以使用典型的矩形到极地的转换公式来计算,其中arctan函数需要两个输入并在整个可能的方向圆上创建一个角度。

  • Marr和Hildreth帽子与高斯滤波一起使用,以获得高斯的拉普拉斯系数。在边缘增强之前,它被用来去除噪音。通过定位图片强度的二阶导数的零交叉点发现的边缘点极易受到噪声的影响。在这种方法中,图像应首先使用高斯滤波器进行卷积。

这个阶段可以平滑并降低图片中的噪音。小的结构和孤立的噪声点将被过滤掉。因为平滑会导致边缘扩散,所以边缘检测器只考虑具有局部最大梯度的像素作为边缘。这是通过使用二阶导数的零交叉来完成的。因为它是一个各向同性的算子,拉普拉斯被用来近似二维的二阶导数。为了防止检测琐碎的边缘,只有相关的一阶导数大于一定阈值的零交叉点才被选为边缘位置。

边缘检测是如何工作的?

边缘是数学中连接两个角或表面的线。边缘检测的基本概念是,像素亮度差异大的区域表明有边缘。因此,边缘检测是对图片中强度不连续的一种测量。边缘检测算法有三个步骤。

筛选

因为基于两个位置的强度值的梯度计算会受到离散计算中的噪声和其他变化的影响,所以通常利用过滤来改善边缘检测器的噪声性能。然而,边缘强度和降噪是有代价的。更多的过滤来消除噪音会降低边缘强度。

增强功能

评估一个点附近的强度变化以实现边缘识别是至关重要的。增强可以突出局部强度值有较大变化的像素,通常通过确定梯度大小来实现。

检测

具有明显边缘的点是该算法的优先选择。然而,图像中的许多位置都有非零梯度值,对于某种应用来说,并非所有这些点都是边缘。因此,应该利用一种方法来确定哪些点是边缘点。阈值处理经常被用作检测标准。

一些算法使用第四步,即定位

本地化

如果亚像素分辨率对应用是必要的,那么可以推断出边缘的位置。边缘的方向也可以被近似计算。

关键是要记住,检测只是显示图片中某个像素附近有边缘存在,并不总是提供边缘位置或方向的精确估计。边缘检测的错误是分类错误;假边缘和缺失边缘。位置和方向估计的概率分布被用来描述边缘估计的错误。因为这两个过程是由不同的算法进行的,并且有不同的错误模型,所以我们区分了边缘检测和估计。

用OpenCV学习边缘检测

让我们从导入必要的库开始,这些库将在文章的每个章节中使用。

import cv2
import matplotlib.pyplot as plt
import numpy as np
复制代码

读取图像并进行预处理

original_img = cv2.imread('Taj_mahal_hotel.jpg',cv2.IMREAD_COLOR)
gray = cv2.cvtColor(original_img, cv2.COLOR_BGR2GRAY)
blur_img = cv2.GaussianBlur(gray,(3,3),0)
复制代码

将图像转换为灰度是必要的,因为边缘检测运算符在灰度下工作。高斯模糊法用于减少图像中的噪声,这是一个重要的预处理步骤。

绘制转换后的查询图像。

plt.figure(figsize=(10,10))
plt.imshow(blur_img)
plt.title("Converted to Grayscale")
plt.show()
复制代码

印度分析杂志

索贝尔边缘检测器

在此,我们将采取三种不同的方案来比较X轴、Y轴和XY轴的边缘检测。

sobelx = cv2.Sobel(src=blur_img, ddepth=cv2.CV_64F, dx=1, dy=0, ksize=5) 
filtered_image_x = cv2.convertScaleAbs(sobelx)
 
sobely = cv2.Sobel(src=blur_img, ddepth=cv2.CV_64F, dx=0, dy=1, ksize=5)
filtered_image_y = cv2.convertScaleAbs(sobely)
 
sobelxy = cv2.Sobel(src=blur_img, ddepth=cv2.CV_64F, dx=1, dy=1, ksize=5)
filtered_image_xy = cv2.convertScaleAbs(sobelxy)
 
plt.figure(figsize=(18,19))
plt.subplot(221)
plt.imshow(blur_img, cmap='gray')
plt.title('Original') 
plt.axis("off")
 
plt.subplot(222)
plt.imshow(filtered_image_x, cmap='gray')
plt.title('Sobel X') 
plt.axis("off")
 
plt.subplot(223)
plt.imshow(filtered_image_y, cmap='gray')
plt.title('Sobel Y') 
plt.axis("off")
 
plt.subplot(224)
plt.imshow(filtered_image_xy, cmap='gray')
plt.title('Sobel X Y')
plt.axis("off")
plt.show()
复制代码

印度分析杂志

单一方向的边缘检测都无法检测到边缘。但双向边缘检测在检测图像中物体的边缘方面做得相当好。

Canny边缘检测器

该方法使用三阶段程序从图像中提取边缘,当应用模糊处理时,该过程总共有四个阶段。

edges = cv2.Canny(image=blur_img, threshold1=100, threshold2=200)
 
plt.figure(figsize=(18,19))
plt.subplot(121)
plt.imshow(blur_img, cmap='gray')
plt.title('Original') 
plt.axis("off")
 
plt.subplot(122)
plt.imshow(edges, cmap='gray')
plt.title('Edge image')
plt.axis("off")
plt.show()
复制代码

印度分析杂志

拉普拉斯边缘检测器

拉普拉斯边缘检测器对图像的二阶导数进行比较。它计算第一次导数在单次过程中的变化次数。

laplacian = cv2.Laplacian(blur_img,5,cv2.CV_64F)
filtered_image = cv2.convertScaleAbs(laplacian)
plt.figure(figsize=(18,19))
plt.subplot(121)
plt.imshow(blur_img, cmap='gray')
plt.title('Original') 
plt.axis("off")
 
plt.subplot(122)
plt.imshow(filtered_image, cmap='gray')
plt.title('Edge image')
plt.axis("off")
plt.show()
复制代码

印度分析杂志

根据结果,比较所有三种方法,Canny边缘检测器在检测物体边缘方面做得相当好。

结论

在数字图像中,边缘是强度的大局部变化。边缘是一个链接的像素集合,它定义了两个不同区域之间的边界。通过这篇文章,我们已经了解了边缘检测的概念和操作,并使用OpenCV进行了实现。

猜你喜欢

转载自juejin.im/post/7107491346067226655