Python+OpenCV:Canny边缘检测
Python+OpenCV:Canny边缘检测
理论
Canny边缘检测是目前比较流行的边缘检测算法,它由John F. Canny发明。
这是一个多阶段的算法。
降噪:由于边缘检测容易受到图像中噪声的影响,第一步使用5x5高斯滤波器去除图像中的噪声。
找到图像的强度梯度:对平滑后的图像进行水平方向和垂直方向的Sobel核滤波,得到水平方向(Gx)和垂直方向(Gy)的一阶导数。从这两幅图像中,我们可以找到每个像素的边缘梯度和方向如下:
梯度方向总是垂直于边缘。它是圆形的四个角之一,代表垂直,水平和两个对角线方向。
- Non-maximum抑制:在获得梯度大小和方向后,对图像进行全面扫描,以便删除任何不需要的像素(可能不构成边缘)。
为此,在每个像素处,检查像素是否在梯度方向上的邻域内存在局部极大值。查看下图:
点A在边缘上(垂直方向)。梯度方向垂直于边缘。点B和点C是梯度方向的。因此,对点A和点B、C进行检验,看它是否形成局部极大值。如果是,则考虑进入下一阶段,否则,它将被抑制(设为零)。
简而言之,你得到的结果是一个“薄边缘”的二值图像。
- 滞后阈值(Hysteresis Thresholding):这个阶段决定哪些是真正的边,哪些不是边。为此,我们需要两个阈值,minVal和maxVal。
任何强度梯度大于maxVal的边肯定是边,而低于minVal的边肯定是非边,因此被丢弃。
那些位于这两个阈值之间的边是根据它们的连接性而分类为边缘或非边缘。如果它们连接到“确定边缘”像素,它们被认为是边缘的一部分。否则,它们也会被丢弃。请看下图:
边A在maxVal的上方,因此被认为是“确定的边”。尽管C边在maxVal下方,但它与A边相连,所以这条边也被认为是有效边,我们得到了那条完整的曲线。但边B虽然在minVal之上,且与边C处于同一区域,但它没有连接到任何“sure-edge”,因此被丢弃。因此,我们必须相应地选择minVal和maxVal以获得正确的结果,这是非常重要的。
这个阶段也可以假设边缘是长线,而去除小像素噪声。
最终,我们得到的是图像中的强边。
示例
####################################################################################################
# Canny边缘检测(Canny Edge Detection)
def lmc_cv_canny_edge_detection():
"""
函数功能: Canny边缘检测(Canny Edge Detection).
"""
# 读取图像
image = lmc_cv.imread('D:/99-Research/Python/Image/Lena.jpg')
image = lmc_cv.cvtColor(image, lmc_cv.COLOR_BGR2GRAY)
# Canny边缘检测(Canny Edge Detection)
edges_image = lmc_cv.Canny(image, 100, 250, L2gradient=False)
# 显示图像
pyplot.figure('Image Display')
titles = ['Original Image', 'Canny Edge Image']
images = [image, edges_image]
for i in range(2):
pyplot.subplot(1, 2, i + 1)
pyplot.imshow(images[i], 'gray')
pyplot.title(titles[i])
pyplot.xticks([])
pyplot.yticks([])
pyplot.show()
# 根据用户输入保存图像
if ord("q") == (lmc_cv.waitKey(0) & 0xFF):
# 销毁窗口
pyplot.close()
return
还没有评论,来说两句吧...