imutils基础(2)基于imutils的Canny边缘检测

在这里插入图片描述
基于Python和OpenCV的零参数的自动Canny边缘检测这个技巧真的很棒——而且在很多情况下,它完全减轻了调优Canny边缘检测器参数的需要。但在我们开始之前,让我们先讨论一下Canny边缘检测器。

1.Canny边缘检测器

Canny边缘检测器是在1986年由John F. Canny发明的。它至今仍被广泛使用,是图像处理中默认的边缘检测器之一。

Canny边缘检测算法可以分为5个步骤:

  • 1.使用高斯滤波器平滑图像以去除高频噪声。
  • 2.计算图像的梯度
  • 3.应用非最大抑制来消除对边缘检测的“假”响应。
  • 4.使用梯度值的下限和上限应用阈值。
  • 5.通过抑制未连接到强边的弱边,使用滞后跟踪边。

如果你熟悉Canny边缘检测器的OpenCV实现,你会知道函数签名是这样的:cv2.canny(image, lower, upper)。其中image是我们想要检测边缘的图像;lower和upper分别是步骤4的整数阈值。

问题在于确定这些下限和上限。

阈值的最佳值是什么?

当你处理在不同光照条件下拍摄的不同内容的多幅图像时,这个问题特别重要。

在剩余部分,我将向您展示一个基于基本统计数据的小技巧,您可以应用它来摒弃Canny边缘检测阈值的手动调优。

这个技巧将节省你的参数调整时间-应用该功能后你仍然会得到一个不错的Canny边缘结果。

2.基于Python和OpenCV的零参数自动Canny边缘检测

在你最喜欢的代码编辑器中打开一个新文件,命名为auto_canny.py,让我们开始吧:

# 导入相关库
import numpy as np
import argparse
import glob
import cv2
def auto_canny(image, sigma=0.33):
	# 计算单个通道像素强度的中值
	v = np.median(image)
	# 根据计算的中值,实现自动Canny边缘检测
	lower = int(max(0, (1.0 - sigma) * v))
	upper = int(min(255, (1.0 + sigma) * v))
	edged = cv2.Canny(image, lower, upper)
	# 返回结果
	return edged

我们要做的第一件事是导入我们需要的包。我们将使用NumPy来进行数值运算,argparse来解析命令行参数,glob来获取从磁盘得到图像的路径。
然后我们定义auto_canny,我们的自动Canny边缘检测函数。这个函数需要一个参数image,它是单通道图像。作为一个可选参数sigma,可以用来改变基于简单统计确定的百分比阈值。
auto_canny函数中,首先得到图像中像素强度的中值。然后我们取这个中值,构造两上、下两个阈值。这些阈值是建立在由sigma参数控制的+/-百分比的基础上的。
sigma值越低,临界值越紧,而sigma值越大,临界值越宽。一般来说,你不需要经常改变这个值。简单地选择一个单一的,默认的sigma,并将其应用到您的整个图像数据集。

注:在实践中,sigma=0.33往往在我使用的大多数数据集上给出好的结果,所以我选择提供33%作为默认的sigma值。

现在我们有了下限和上限,然后应用Canny边缘检测器,并将结果返回。

# 构造参数parse并解析参数
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--images", required=True,
	help="path to input dataset of images")
args = vars(ap.parse_args())
# 循环操作图像
for imagePath in glob.glob(args["images"] + "/*.jpg"):
	# 加载图像,将其转换为灰度,并稍微模糊它
	image = cv2.imread(imagePath)
	gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
	blurred = cv2.GaussianBlur(gray, (3, 3), 0)
	# 应用Canny边缘检测,采用宽阈值、紧阈值和自动确定阈值
	wide = cv2.Canny(blurred, 10, 200)
	tight = cv2.Canny(blurred, 225, 250)
	auto = auto_canny(blurred)
	# 显示图片
	cv2.imshow("Original", image)
	cv2.imshow("Edges", np.hstack([wide, tight, auto]))
	cv2.waitKey(0)

我们解析命令行参数。这里我们只需要一个参数——images,它是包含我们想要处理的图像的目录的路径。
然后我们循环查看目录中的图像,从磁盘加载图像,将图像转换为灰度,并应用带有3 x 3核的高斯模糊来去除高频噪声。
然后采用三种方法进行Canny边缘检测:
+宽阈值。

  • 紧阈值。
  • 使用auto_canny函数自动确定的阈值。

3.结果展示

在这里插入图片描述
如你所见,宽Canny边缘阈值不仅能检测到海豚,还能检测到图像中的许多云。紧的阈值没有探测到云,但错过了海豚的尾巴。最后,自动方法能够找到所有的海豚,同时去除许多云的边缘。

让我们试试另一个图像:
在这里插入图片描述左边的宽Canny阈值包括基于相机拉丝金属上的光线反射的高频噪声,而中间的窄阈值忽略了相机上的许多结构边缘。最后,右边的自动方法能够在不包括高频噪声的情况下找到许多结构边缘。

又一个例子:
在这里插入图片描述
这里的结果相当引人注目。虽然宽(左)和自动(右)Canny边缘检测方法的性能相似,但紧阈值(中)几乎遗漏了杯子的所有结构边缘。

通过上面的例子,很明显,自动的,零参数版本的Canny边缘检测以最少的努力获得最好的结果。

结论

在这篇博客文章中,我向你展示了一个简单的技巧,可以使用Canny边缘检测器(可靠地)自动检测图像中的边缘,而不需要为函数提供阈值。
这个技巧只是取图像的中值,然后根据中值的百分比构造上下限阈值。在实践中,sigma=0.33往往能获得较好的结果。
一般情况下,您会发现Canny边缘检测的自动、零参数版本能够获得相当不错的结果,而您几乎不需要付出任何努力。

参考文献

https://www.pyimagesearch.com/2015/04/06/zero-parameter-automatic-canny-edge-detection-with-python-and-opencv/

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值