sobel算子
定义
Sobel 算子是一个主要用作边缘检测的离散微分算子 (discrete differentiation operator)。 它Sobel算子结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。在图像的任何一点使用此算子,将会产生对应的梯度矢量或是其法矢量。
步骤
我们假设被作用图像为 I.然后进行如下的操作:
- 分别在x和y两个方向求导。
- 水平变化: 将 I 与一个奇数大小的内核进行卷积。
- 垂直变化: 将: I 与一个奇数大小的内核进行卷积。
- 在图像的每一点,结合以上两个结果求出近似梯度
API
dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
- ddepth:图像的深度
- dx和dy分别表示水平和竖直方向
- ksize是Sobel算子的大小
实例
import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
%matplotlib inline
def cv_showimg(name,img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
原图
img = cv2.imread('pie.png',cv2.IMREAD_GRAYSCALE)
cv_showimg('img',img)
原图.PNG
水平方向
由sobel算子的卷积核可知,它是固定右减左的,白到黑是正数,黑到白就是负数了,所有的负数会被截断成0,所以实战时通常要做绝对值处理
# 不做绝对值处理
obelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
cv_showimg('sobelx',sobelx)
sobel水平方向-不取绝对值.PNG
# 绝对值处理
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
cv_showimg('sobelx',sobelx)
水平方向-绝对值处理.PNG
垂直方向
与水平方向同理
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
cv_showimg('sobely',sobely)
垂直方向.PNG
结果相加
将两个方向的结果整合到一起,有两种方法:
- 分别计算x和y,再求和。
- 直接计算,结果不好,不建议这么做。
# 方法一:分开计算
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_showimg('sobelxy',sobelxy)
分开计算效果图.PNG
# 方法二:直接计算
sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy)
cv_showimg('sobelxy',sobelxy)
直接计算.PNG
Scharr算子
概念
当内核大小为 3 时, 我们的Sobel内核可能产生比较明显的误差(毕竟,Sobel算子只是求取了导数的近似值而已)。 为解决这一问题,OpenCV提供了Scharr 函数,但该函数仅作用于大小为3的内核。该函数的运算与Sobel函数一样快,但结果却更加精确,其内核是这样的:
Scharr算子因为Sobel算子结合了高斯平滑和分化(differentiation),因此结果会具有更多的抗噪性。大多数情况下,我们使用sobel函数
API
dst = cv2.Scharr(src, ddepth, dx, dy)
- ddepth:图像的深度
- dx和dy分别表示水平和竖直方向
- 没有ksize,因为它的内核大小固定为3
实例
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)
cv_showimg('scharrxy',scharrxy)
scharr算子结果.PNG
laplacian算子
概念
Laplacian 算子是n维欧几里德空间中的一个二阶微分算子,定义为梯度grad()的散度div()。因此如果f是二阶可微的实函数,则f的拉普拉斯算子定义为:
-
f的拉普拉斯算子也是笛卡儿坐标系xi中的所有非混合二阶偏导数求和:
-
作为一个二阶微分算子,拉普拉斯算子把C函数映射到C函数,对于k ≥ 2。表达式(1)(或(2))定义了一个算子Δ :C(R) → C(R),或更一般地,定义了一个算子Δ : C(Ω) → C(Ω),对于任何开集Ω。
根据图像处理的原理我们知道,二阶导数可以用来进行检测边缘 。 因为图像是 “二维”, 我们需要在两个方向进行求导。使用Laplacian算子将会使求导过程变得简单。
Laplacian 算子的定义:
拉普拉斯算子
API
dst = cv2.Laplacian(src, ddepth)
- ddepth:图像的深度
实例
laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)
cv_showimg('laplacian',laplacian)
拉普拉斯算子结果图.PNG
三种算子在实际图中的比较
scharr算子比sobel算子更关注细节,边界信息更细致。
laplacian算子单独使用效果并不是很好,要结合其它的算法一起使用。
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_showimg('res',res)
三种算子的比较图.PNG
网友评论