(1)理论部分
x 水平方向的梯度, 其实也就是右边 - 左边,有的权重为1,有的为2 。
若是计算出来的值很大 说明是一个边界 。
y 竖直方向的梯度,其实也就是下面减上面,权重1,或2 。
若是计算出来的值很大 说明是一个边界 。
图像的梯度为:
有时简化为:
即:
(2)程序部分
函数:Sobel
ddepth 通常取 -1,表示取值范围为0-255,这样会导致结果溢出,检测不出边缘,故使用cv2.CV_64F增大数值范围。但是一般增大范围也没用,因为负值会默认为0,故要结合convertScaleAbs使用,将负数调为正数。
通常不写后面两个参数
计算sobel算子 两种方式:
1,dx=1 dy=1 这种方法不太严谨
2,分别计算dx dy 再相加 为了防止相加之后大于255溢出 通常加个系数
用下面这个函数实现
结果= 图像1 *系数 + 图像2 *系数 + 修正值
将ddepth 分别设置为-1 和 cv2.CV_64F对比 发现均没有检测到全部的边界。原因是计算结果仍然为负数。
import cv2
a=cv2.imread('image\\sobel.bmp',cv2.IMREAD_GRAYSCALE)
sobelx=cv2.Sobel(a,-1,1,0)
sobelx1=cv2.Sobel(a,cv2.CV_64F,1,0)
cv2.imshow('a',a)
cv2.imshow('sobelx',sobelx)
cv2.imshow('sobelx1',sobelx1)
cv2.waitKey()
cv2.destroyAllWindows()
正确的如下所示:
import cv2
a=cv2.imread('image\\sobel.bmp',cv2.IMREAD_GRAYSCALE)
sobelx=cv2.Sobel(a,-1,1,0) #水平梯度
sobelx1=cv2.Sobel(a,cv2.CV_64F,1,0) #水平梯度
sobelx2=cv2.convertScaleAbs(sobelx1) #负数取绝对值
cv2.imshow('a',a)
cv2.imshow('sobelx',sobelx)
cv2.imshow('sobelx1',sobelx1)
cv2.imshow('sobelx2',sobelx2)
cv2.waitKey()
cv2.destroyAllWindows()
import cv2
a=cv2.imread('image\\sobel.bmp',cv2.IMREAD_GRAYSCALE)
sobelx=cv2.Sobel(a,cv2.CV_64F,1,0) #水平梯度
sobely=cv2.Sobel(a,cv2.CV_64F,0,1) #竖直梯度
sobelx=cv2.convertScaleAbs(sobelx) #负数取绝对值
sobely=cv2.convertScaleAbs(sobely) #负数取绝对值
sobelxy=cv2.addWeighted(sobelx,0.5,sobely,0.5,0) #求sobel算子,系数为0.5,0.5。修正值为0
cv2.imshow('a',a)
cv2.imshow('sobelx',sobelx)
cv2.imshow('sobelx1',sobely)
cv2.imshow('sobelxy',sobelxy)
cv2.waitKey()
cv2.destroyAllWindows()
对比一下fx fy 均为1的情况,发现只检测到一些点
import cv2
a=cv2.imread('image\\sobel.bmp',cv2.IMREAD_GRAYSCALE)
sobelx=cv2.Sobel(a,cv2.CV_64F,1,0) #水平梯度
sobely=cv2.Sobel(a,cv2.CV_64F,0,1) #竖直梯度
sobelx=cv2.convertScaleAbs(sobelx) #负数取绝对值
sobely=cv2.convertScaleAbs(sobely) #负数取绝对值
sobelxy=cv2.addWeighted(sobelx,0.5,sobely,0.5,0) #求sobel算子,系数为0.5,0.5。修正值为0
sobelxy11=cv2.Sobel(a,cv2.CV_64F,1,1)
sobelxy11=cv2.convertScaleAbs(sobelxy11)
cv2.imshow('a',a)
cv2.imshow('sobelxy',sobelxy)
cv2.imshow('sobelxy11',sobelxy11)
cv2.waitKey()
cv2.destroyAllWindows()