梯度简单来说就是求导。OpenCV 提供了三种不同的梯度滤波器,或者说高通滤波器: Sobel,Scharr 和 Laplacian。其中Sobel,Scharr 是求一阶导数。Scharr 是对 Sobel(使用小的卷积核求解求解梯度角度时)的优化,而 Laplacian 是求二阶导数。
原理
Sobel算子是高斯平滑和微分操作的结合体,所以他的抗噪声能力很好。你可以设定求导的方向(xorder 或 yorder)。还可以设定使用的卷积核大小(ksize)。当ksize=-1时,会使用3x3 的Scharr滤波器,他的效果要比3x3的Sobel滤波器好,而且速度相同,所以在使用3x3滤波器时应该尽量使用Scharr滤波器(一般就用Sobel算子即可)。
前一个Sobel矩阵与原始图像A进行卷积操作后得到的是右边的像素值减去左边的像素值;后一个Sobel矩阵与原始图像A进行卷积操作后得到的是下边的像素值减去上边的像素值。
dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
cv_show(sobelx,'sobelx')
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
res = np.hstack((sobelx,sobely))
cv_show(res,'res')
白到黑是正数,黑到白就是负数了,所有的负数会被截断成0,所以要取绝对值
# x方向取边缘
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
# 白到黑是正数,黑到白就是负数了,所有的负数会被截断成0,所以要取绝对值
sobelx = cv2.convertScaleAbs(sobelx) # 也可以用 sobelx = np.absolute(gradX)
cv_show(sobelx,'sobelx')
# y方向取边缘
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
cv_show(sobely,'sobely')
img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(sobelxy,'sobelxy')
原理
其实就是将Sobel算子的数增大了,这样对边缘的检测更敏感。
scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)
原理
由G矩阵的形式可知,拉普拉斯算子只关心离中心点最近的几个边缘点。
#不同算子的差异
img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.convertScaleAbs(sobely)
sobelxy= cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)
laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)
res = np.hstack((sobelxy,scharrxy,laplacian))
cv_show(res,'res')