下面来介绍Scharr算子,他和sobel算子类似,只不过矩阵的边缘检测敏感度不同,也就是赋值更敏感。
\begin{equation*}
\text{Scharr}(x,y) = \frac{3}{2} \left[ \text{Sobel}(x+1,y+1) - \text{Sobel}(x-1,y-1) \right] - \frac{1}{2} \left[ \text{Sobel}(x+1,y-1) - \text{Sobel}(x-1,y+1) \right]
\end{equation*}
这是什么玩意,通俗的说,就是这样。
\begin{equation*}
G_x(x) =
\begin{bmatrix}
-3 & 0 & 3 \
-10 & 0 & 10 \
-3 & 0 & 3
\end{bmatrix} \ , \
G_y(x) =
\begin{bmatrix}
3 & 10 & 3 \
0 & 0 & 0 \
-3 & -10 & -3
\end{bmatrix}
\end{equation*}
也就是说用了近大远小的道理,中间都是10,角上是3,更加对边缘敏感。

1
2
3
4
5
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
import ipykernel
from IPython.display import Latex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
img = cv.imread("def.jpg", cv.IMREAD_GRAYSCALE)
sobelx = cv.Sobel(img, cv.CV_64F, 1, 0, ksize=5)
sobely = cv.Sobel(img, cv.CV_64F, 0, 1, ksize=5)
sobelx = cv.convertScaleAbs(sobelx)
sobely = cv.convertScaleAbs(sobely)
sobelxy = cv.addWeighted(sobelx, 0.5, sobely, 0.5, 0)


scharrx = cv.Scharr(img, cv.CV_64F, 1, 0)#不用标ksize
scharry = cv.Scharr(img, cv.CV_64F, 0, 1)
scharrx = cv.convertScaleAbs(scharrx)#转换绝对值,不能取负值,否则直接截断为0了
scharry = cv.convertScaleAbs(scharry)
scharrxy = cv.addWeighted(scharrx, 0.5, scharry, 0.5, 0)

#确实更加逼真。
laplacian = cv.Laplacian(img, cv.CV_64F)
laplacian = cv.convertScaleAbs(laplacian)#拉普拉斯更突出每个像素的中间值和两边的差别。

res = np.hstack((img, sobelxy, scharrxy, laplacian))
cv.imshow("res", res)
cv.waitKey(0)
cv.destroyAllWindows()