本文为合集收录,欢迎查看合集/专栏链接进行全部合集的系统学习。
合集完整版请参考这里。
本节来看一个利用传统计算机视觉方法来实现图片边缘检测的方法。
什么是边缘检测?
边缘检测是通过一些算法来识别图像中物体之间或者物体与背景之间的边界,也就是边缘。
图像边缘通常是图像中灰度变化显著的地方,标志着不同区域的分界线。
在一张图像中,边缘可以是物体的实际边界,也可以是纹理、颜色或亮度等特征变化比较明显的位置。
边缘检测有助于提取图像的结构信息,是许多计算机视觉和图像处理任务的基础,例如物体识别、图像分割和目标跟踪。
比如下面这张图片,我用红笔粗略的画出了一些物体的边缘,猫耳朵和背景很明显的边缘,椅子和背景以及椅子和猫咪的边缘等。
常见的边缘检测算法
实现图片的边缘检测的算法有很多,常见的边缘检测算法包括:
-
Sobel算子: 通过卷积图像和Sobel核,检测图像中的垂直和水平边缘。
-
Prewitt算子: 类似于Sobel,也是一种常用的边缘检测方法。
-
Canny边缘检测: 结合了多个步骤,包括高斯平滑、梯度计算和非极大值抑制,是一种广泛使用的边缘检测算法。
-
Laplacian算子: 通过对图像进行拉普拉斯运算,突出图像中的边缘。
-
基于机器学习的方法: 利用深度学习中的卷积神经网络(CNN)等技术,可以学习图像中的特征,进而进行边缘检测。
以上几种算法是常见的边缘检测算法,感兴趣的话可以深入研究,这里不详细说明每个算法的原理,但大致都是类似的过程:通过一个类似于前文讲述的高斯滤波的滤波器窗口,来对图像像素值进行运算,得到像素突变的地方,以此作为边缘。
只不过这些窗口中的数值是经过精心计算和设计的,使得这些专业的算法(比如Canny算法)对边缘检测更为有效。
利用 Canny 算子对图像进行边缘检测
下面使用 opencv 库中的 Canny 函数,也就是Canny 算子来完成边缘检测。
import cv2
import matplotlib.pyplot as plt
# 读取图像
image = cv2.imread('cat.png', cv2.IMREAD_GRAYSCALE)
# 使用 Canny 算子进行边缘检测
edges = cv2.Canny(image, 50, 150) # 调整阈值以获得最佳效果
# 显示结果
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.subplot(1, 2, 2)
plt.imshow(edges, cmap='gray')
plt.title('Canny Edges')
plt.show()
在上面的例子中,使用 cv2.Canny 函数中的 Canny 边缘检测算法,然后使用 matplotlib 库显示原始图像和检测到的边缘的图像。在实际使用时,你可以通过调整 cv2.Canny 函数的阈值来获得最佳的检测效果。
阈值是做什么的?
cv2.Canny 函数中的两个阈值参数指的是低阈值(threshold1)和高阈值(threshold2)。这两个阈值用于确定图像中的边缘。
-
低阈值 (threshold1): 用于标识边缘像素的梯度值低于这个阈值的情况。这些像素将被认为不是边缘。如果某个像素的梯度值超过了低阈值,它将被标记为可能的边缘。
-
高阈值 (threshold2): 用于边缘像素的梯度值高于这个阈值的情况。这些像素将被视为强边缘。如果某个像素的梯度值介于低阈值和高阈值之间,它将被标记为弱边缘。
在实践中,选择一个适当的高低阈值可以确保正确检测出图像中的边缘,这两个阈值的选择可能会因图像的特性而异,需要进行一些试验和调整。
下面是对一张图片进行边缘检测的效果,可以看到大量的边缘已经被检测出来了。
为什么要将图像转换为灰度图来做边缘检测
将图像转换为灰度图的一个主要原因是降低计算的复杂性,同时保留关键的信息。RGB图像包含了红、绿、蓝三个通道的信息,而灰度图只包含强度信息。
-
计算效率:灰度图像只有一个通道,相比于RGB图像的三个通道,处理灰度图像所需的计算量更小,这在图像处理和计算机视觉任务中很重要。
-
降低复杂性:对于很多应用来说,颜色信息并不是关键。将图像转换为灰度图简化了图像的处理和分析过程。
-
去除冗余信息:在某些情况下,颜色并不是任务关注的重点。例如,边缘检测和物体识别通常更关注于亮度变化而非颜色变化。
除此之外,还可以减少图片的内存占用,尽管如此,如果在一些任务中我们确实需要颜色信息,可以在边缘检测的基础上进一步处理,使得在RGB的彩色图片上完成边缘检测。