这篇文章上次修改于 298 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

梯度算子

Sobel算子

image.png
如图所示,sobel算子属于x轴和y轴相减,从而用于检测边缘,但是sobel算子的中心边缘部位权重更大,因此其优点是更突出图像中心部位的边缘。
这里引用一张月球的照片作为例子:

import cv2 
import numpy as np
img=cv2.imread('yue.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow("img_gray", img_gray)
cv2.waitKey(0)    
cv2.destroyAllWindows() 

image.png

为了提取月球的表面边缘细节,现在使用sobel算子进行处理,sobel算子应用如下:
dst = cv2.Sobel(src, ddepth, dx, dy, ksize)

  • ddepth:图像的深度
  • dx和dy分别表示水平和竖直方向
  • ksize是Sobel算子的大小

首先是水平方向提取和计算:

sobelx = cv2.Sobel(img_gray,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
cv_show(sobelx,'sobelx')

image.png

可以看到,针对于水平方向的边缘细节能够很好的显示出来,但是竖直方向不明显。
我们再对竖直方向进行处理:

sobely = cv2.Sobel(img_gray,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)  
cv_show(sobely,'sobely')

image.png

单独的水平方向和竖直方向并不能很好的体现整体的边缘细节,因此,可以对其水平和竖直方向处理后求和进行处理:

sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(sobelxy,'sobelxy')

二者权重均为0.5,效果如下:
image.png

可以看到,经过sobel计算后的边缘细节被很好的显示出来。

laplacian算子

laplacian算子属于二阶微分算子,具有各向同性的特点(旋转不变性),laplacian算子强调图像中灰度的突变,弱化灰度慢变化的区域。
image.png

下面比较下laplacian算子与sibelxy算子的差异:
image.png

这里只介演示基本的两个算子,其它算子还有Prewitt算子(与sobel算子类似,但各个位置权重相同),Roberts算子(强调对角线的边缘计算)等等就不一一举例了。

边缘检测

Canny边缘检测

  • 使用高斯滤波器,以平滑图像,滤除噪声。
  • 计算图像中每个像素点的梯度强度和方向。
  • 应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
  • 应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
  • 通过抑制孤立的弱边缘最终完成边缘检测。

具体原理太复杂,这里略过,演示代码:

img=cv2.imread("lena.jpg",cv2.IMREAD_GRAYSCALE)

v1=cv2.Canny(img,80,150)#最小阀值和最大阀值
v2=cv2.Canny(img,50,100)

res = np.hstack((v1,v2))
cv_show(res,'res')

image.png

阀值上下限和大小对细节的提取效果很明显。

再以一张图片为示例:

img=cv2.imread("car.png",cv2.IMREAD_GRAYSCALE)

v1=cv2.Canny(img,120,250)
v2=cv2.Canny(img,50,100)

res = np.hstack((v1,v2))
cv_show(res,'res')

image.png