1.分别在x和y两个方向求导。
2.在图像的每一点,结合以上两个结果求出近似梯度:
在图像的每一点,结合以上两个结果求出:
G = G x 2 + G y 2 G = \sqrt{G_x^2+ G_y^2} G=Gx2+Gy2 or ∣ G x ∣ + ∣ G y ∣ |G_x| + |G_y| ∣Gx∣+∣Gy∣
统计极大值所在的位置,就是图像的边缘。
Sobel_x_or_y = cv2.Sobel(src, ddepth, dx, dy, dst, ksize, scale, delta, borderType)
参数:
src:传入的图像
ddepth: 图像的深度
dx和dy: 指求导的阶数,0表示这个方向上没有求导,取值为0、1。
ksize: 是Sobel算子的大小,即卷积核的大小,必须为奇数1、3、5、7,默认为3。
注意:如果ksize=-1,就演变成为3x3的Scharr算子。
scale:缩放导数的比例常数,默认情况为没有伸缩系数。
borderType:图像边界的模式,默认值为cv2.BORDER_DEFAULT。
ddepth
图片深度类型:
在Sobel算子中支持如下src.depth()和ddepth的组合:
1、若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F
2、若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F
3、若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F
4、若src.depth() = CV_64F, 取ddepth = -1/CV_64F
参数ksize
int类型ksize,有默认值3,表示Sobel核的大小;必须取1,3,5或7。如果ksize=-1,就演变成为3x3的Scharr算子。
有些时候 Sobel函数求完导数后会有负值,还有会大于255的值。而原图像是uint8,即8位无符号数,所以Sobel建立的图像位数不够,会有截断。因此要使用16位有符号的数据类型,即cv2.CV_16S。处理完图像后,再使用cv2.convertScaleAbs()函数将其转回原来的uint8格式,否则图像无法显示
##soble算子
soble_edge = cv2.Sobel(No_area,cv2.CV_8U,1,1)
cv2.imshow('S_edge', soble_edge)
cv2.waitKey(0)
x = cv2.Sobel(No_area, cv2.CV_16S, 1, 0)
y = cv2.Sobel(No_area, cv2.CV_16S, 0, 1)
# 3 将数据进行转换
Scale_absX = cv2.convertScaleAbs(x) # convert 转换 scale 缩放
Scale_absY = cv2.convertScaleAbs(y)
# 4 结果合成
result = cv2.addWeighted(Scale_absX, 0.5, Scale_absY, 0.5, 0)
cv2.imshow('S_edge', result)
cv2.waitKey(0)
其他博客非常详细了
Canny边缘检测的算法包含下列5个步骤:
(1)使用高斯滤波去除图像噪声。
(2)使用Sobel核进行滤波,计算梯度。
(3)在边缘使用非最大值抑制。
(4)对检测出的边缘使用双阈值以去除假阳性。
(5)分析边缘之间的连接性,保留真正的边缘,消除不明显的边缘。
dst=cv2.Canny(src,threshold1,threshold2,apertureSize,L2gradient)
src:灰度图,
threshold1: minval,较小的阈值将间断的边缘连接起来
threshold2: maxval,较大的阈值检测图像中明显的边缘
apertureSize:为计算梯度时使用的Sobel核大小
threshold1即minval 一般取高于之的1/2 或1/3
##canny算子
canny_edge = cv2.Canny(No_area,100,200)
cv2.imshow('C_edge', canny_edge)
cv2.waitKey(0)
Sobel边缘检测算法比较简单,实际应用中效率比canny边缘检测效率要高,但是边缘不如Canny检测的准确,但是很多实际应用的场合,sobel边缘却是首选,Sobel算子是高斯平滑与微分操作的结合体,所以其抗噪声能力很强,用途较多。尤其是效率要求较高,而对细纹理不太关心的时候。如果需要对微小的图像做边缘检测、并对细节要求较高此时就需要用到canny算子