(一)Canny边缘检查算法步骤:
1.彩色图转化为灰度图
2.由于边缘检测容易受到图像中噪声的影响,应用高斯滤波来平滑图像–>去除噪声。
3.找寻图像的强度梯度。 Canny的基本思想是找寻一幅图像中强度变化最强的位置。所谓的变化最强,即指梯度方向。平滑后的图像中每个像素点的梯度可以由Sobel算子来获得:
(1)首先,利用Sobel算子得到沿x轴和y轴方向的梯度G_x和G_y。
(2)由G_X和G_Y便可计算每一个像素点的梯度幅值G。
(3)接着,每一个像素点用G代替。对于变化剧烈的边界处,G值越大,对应的颜色为白色。
(4)然后,这些边界通常非常粗,难以标定边界的真正位置,还必须存储梯度的方向θ。
4.应用非极大抑制技术来消除边误检(本来不是边缘但检测出来是),沿着梯度θ方向上比较该像素点,若该像素点与两侧相比最大则保留,否则抑制(置为0)。这一步的目的是将模糊的边界变得清晰,剔除一大部分不是边缘的点。
5.双阈值边缘连接处理
规则:设定两个阈值,minVal和maxVal。
大于maxVal的边缘肯定是边缘(保留),低于minVal的边缘是非边缘(舍去)。
对于介于两者之间的值,判断是否与真正的边界(强边界)相连,相连就保留,否则丢弃。
6.二值化图像输出结果。
(二)OpenCV+Python实现
1.函数说明:
OpenCV-Python中Canny函数的原型为:
edge = cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]])
参数:
image:需要处理的原图像,该图像必须为单通道的灰度图;
threshold1:阈值1。
threshold2:阈值2。
apertureSize:Sobel算子的直径。
其中较大的阈值2用于检测图像中明显的边缘,但一般情况下检测的效果不会那么完美,边缘检测出来是断断续续的。所以这时候用较小的第一个阈值用将这些间断的边缘连接起来。可选参数中apertureSize就是Sobel算子的大小。而L2gradient参数是一个布尔值,如果为真,则使用更精确的L2范数进行计算(即两个方向的倒数的平方和再开放),否则使用L1范数(直接将两个方向导数的绝对值相加)。
函数返回一副二值图,其中包含检测出的边缘。
2.程序代码:
import cv2
import numpy as np
#载入图片, 由于Canny只能处理灰度图,所以将读取的图像转成灰度图
img_original=cv2.imread('img.jpg')
cv2.namedWindow('Canny')
# 用高斯平滑处理原图像降噪。若效果不好可调节高斯核大小
img = cv2.GaussianBlur(img_original,(3,3),0)
img1 = cv2.GaussianBlur(img_original,(1,1),0)
#定义回调函数
def nothing(x):
pass
#创建两个滑动条,分别控制threshold1,threshold2
cv2.createTrackbar('threshold1','Canny',50,400,nothing)
cv2.createTrackbar('threshold2','Canny',100,400,nothing)
while(1):
#返回滑动条所在位置的值
threshold1=cv2.getTrackbarPos('threshold1','Canny')
threshold2=cv2.getTrackbarPos('threshold2','Canny')
#用Canny函数进行边缘检测,指定最大和最小阈值,其中apertureSize默认为3
img_edges=cv2.Canny(img,threshold1,threshold2)
#显示图片
cv2.imshow('original',img_original)
cv2.imshow('GaussianBlur_3,3',img)
cv2.imshow('GaussianBlur_1,1',img1)
cv2.imshow('Canny',img_edges)
if cv2.waitKey(1)==ord('q'):
break
cv2.destroyAllWindows()
3.运行结果:
原图像:
高斯核为(3,3)进行平滑后的图像,如图1所示:
高斯核为(1,1)进行平滑后的图像,如图2所示:
设低阈值为50,高阈值为100不变;
高斯核为(3,3),输出结果如图3所示:
高斯核为(1,1),输出结果如图4所示:
上阈值定为100,下阈值从50开始增大的过程中,细节逐渐减少,如下图所示:
下阈值定为50,上阈值从100开始增大的过程中,细节逐步减少,如下图所示:
4.结果分析
高斯核越小,边缘信息越多,越大边缘信息越少。高阈值设置的太高,就会导致高于高阈值的点很少,边界就会不清楚时断时续;如果设置的太低就会导致大于高阈值的点很多,噪声也就太多,不利于我们的后续操作。低阈值越小,边界信息越多,越大边缘信息越少。所以在实际操作中多试几次,才能找到最合适的参数值。