sobel算子的原理便是求出x,y方向的梯度。梯度的计算方法如下:
可以得到元素P5在x方向的梯度为P3-P1+2*(P6-P4)+P9-P7。
可以得到元素P5在y方向的梯度为P3-P1+2*(P6-P4)+P9-P7。
然后将Gx和Gy取绝对值相加,根据差值的大小来判断是否为边界。(注意这里要取绝对值,不然可能会丢失一些信息)
sobel算子检测边缘通过cv2.sobel(src,ddepth,dx.dy[,ksize])函数来实现。其中ddepth指的是处理图象的深度,等于1时表示与原图像相同的深度,但是要注意的是如果原图像为uint8类型的,需要转换成有符号的,例如cv2.CV_16S和cv2.CV_64F保留负数部分。当dx =0,dy=1时,求得是y方向的梯度。 ksize一般设置为-1。
求得梯度之后,通过cv2.convertScaleAbs(y) 函数来将求得的梯度转化为uint8类型的数,最后通过前面博文介绍的图像融合函数cv2.addWeighted(absX,0.5,absY,0.5,0) 将x和y方向的梯度合成便是最终的边缘信息。代码如下:
import cv2
import numpy as np
img = cv2.imread('F:\python\work\cv_learn\lena.jpg',1)#读取图像
x = cv2.Sobel(img,cv2.CV_16S,1,0) #求x方向梯度
y = cv2.Sobel(img,cv2.CV_16S,0,1)
absX = cv2.convertScaleAbs(x) # 转回uint8
absY = cv2.convertScaleAbs(y)
dst = cv2.addWeighted(absX,0.5,absY,0.5,0) #合成
cv2.imshow('sobel',dst)
cv2.waitKey(0)#保持图像
运行效果如下:
scharr算子只是一个加强版的sobel算子,他的核函数定义为
其余的操作步骤与sobel完全相同,只是求梯度时调用的是cv2.Scharr(src,ddepth,dx,dy)函数。
拉普拉斯算子进行边缘检测的原理是查看中间值与周围像素值的差别,如果相差大则判断为边界。
可以得到元素P5的值为(P2+P4+P6+P8)-4*P5。
通过调用cv2.Laplacian(src,cv2.CV_64F)直接得到边缘图像。
result = cv2.Laplacian(img,cv2.CV_64F)
canny边缘提取是非常经典的一种算法,它包括以下4个步骤:
在opencv中我们通过简单的cv2.canny(img,threshold1,threshold2)来实现。
效果如下:
PS:跟前面介绍的方法混合使用效果更佳