Python 圖像處理 OpenCV (13): Scharr 算子和 LOG 算子邊緣檢測技術
前文傳送門:
「Python 圖像處理 OpenCV (2):像素處理與 Numpy 操作以及 Matplotlib 顯示圖像」
「Python 圖像處理 OpenCV (3):圖像屬性、圖像感興趣 ROI 區域及通道處理」
「Python 圖像處理 OpenCV (4):圖像算數運算以及修改顏色空間」
「Python 圖像處理 OpenCV (5):圖像的幾何變換」
「Python 圖像處理 OpenCV (6):圖像的閾值處理」
「Python 圖像處理 OpenCV (7):圖像平滑(濾波)處理」
「Python 圖像處理 OpenCV (8):圖像腐蝕與圖像膨脹」
「Python 圖像處理 OpenCV (9):圖像處理形態學開運算、閉運算以及梯度運算」
「Python 圖像處理 OpenCV (10):圖像處理形態學之頂帽運算與黑帽運算」
「Python 圖像處理 OpenCV (11):Canny 算子邊緣檢測技術」
「Python 圖像處理 OpenCV (12): Roberts 算子、 Prewitt 算子、 Sobel 算子和 Laplacian 算子邊緣檢測技術」
Scharr 算子
在說 Scharr 算子之前,必須要提的是前面我們介紹過的 Sobel 算子, Sobel 算子雖然可以有效的提取圖像邊緣,但是對圖像中較弱的邊緣提取效果較差。
這是由於 Sobel 算子在計算相對較小的核的時候,其近似計算導數的精度比較低,例如一個 3 * 3
的 Sobel 算子,在梯度角度接近水平或垂直方向時,其不精確性就非常明顯。
因此引入 Scharr 算子。 Scharr 算子是對 Sobel 算子差異性的增強,兩者之間的在檢測圖像邊緣的原理和使用方式上相同。
而 Scharr 算子的主要思路是通過將模版中的權重係數放大來增大像素值間的差異。
Scharr 算子又稱爲 Scharr 濾波器,也是計算 x 或 y 方向上的圖像差分,在 OpenCV 中主要是配合 Sobel 算子的運算而存在的,其濾波器的濾波係數如下:
\[Gx = \left[ \begin{matrix} -3 & 0 & 3\\ -10 & 0 & 10\\ -3 & 0 & 3\\ \end{matrix} \right] \]
\[Gy = \left[ \begin{matrix} -3 & -10 & -3\\ 0 & 0 & 0\\ 3 & 10 & 3\\ \end{matrix} \right] \]
Scharr 算子在 OpenCV 中的方法原型如下:
def Scharr(src, ddepth, dx, dy, dst=None, scale=None, delta=None, borderType=None):
- src: 表示輸入圖像
- ddepth: 表示目標圖像所需的深度,針對不同的輸入圖像,輸出目標圖像有不同的深度
- dx: 表示 x 方向上的差分階數,取值 1 或 0
- dy: 表示 y 方向上的差分階數,取值 1 或 0
可以看到,函數 Scharr()
和 Sobel()
是非常的相似,在使用上也是完全一樣的,下面看一個示例:
import cv2 as cv import matplotlib.pyplot as plt img = cv.imread("maliao.jpg") rgb_img = cv.cvtColor(img, cv.COLOR_BGR2RGB) gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # Scharr 算子 x = cv.Scharr(gray_img, cv.CV_16S, 1, 0) # X 方向 y = cv.Scharr(gray_img, cv.CV_16S, 0, 1) # Y 方向 absX = cv.convertScaleAbs(x) absY = cv.convertScaleAbs(y) Scharr = cv.addWeighted(absX, 0.5, absY, 0.5, 0) # 顯示圖形 plt.rcParams['font.sans-serif']=['SimHei'] titles = ['原始圖像', 'Scharr 算子'] images = [rgb_img, Scharr] for i in range(2): plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray') plt.title(titles[i]) plt.xticks([]), plt.yticks([]) plt.show()
LOG 算子
LOG ( Laplacian of Gaussian ) 邊緣檢測算子是 David Courtnay Marr 和 Ellen Hildreth 在 1980 年共同提出的,也稱爲 Marr & Hildreth 算子,它根據圖像的信噪比來求檢測邊緣的最優濾波器。該算法首先對圖像做高斯濾波,然後再求其拉普拉斯( Laplacian )二階導數,根據二階導數的過零點來檢測圖像的邊界,即通過檢測濾波結果的零交叉( Zero crossings )來獲得圖像或物體的邊緣。
LOG 算子實際上是把 Gauss 濾波和 Laplacian 濾波結合了起來,先平滑掉噪聲,再進行邊緣檢測。
LOG 算子與視覺生理中的數學模型相似,因此在圖像處理領域中得到了廣泛的應用。
它具有抗干擾能力強,邊界定位精度高,邊緣連續性好,能有效提取對比度弱的邊界等特點。
常見的 LOG 算子是 5 * 5
的模板;
\[Gy = \left[ \begin{matrix} -2 & -4 & -4 & -4 & -2\\ -4 & 0 & 8 & 0 & -4\\ -4 & 8 & 24 & 8 & -4\\ -4 & 0 & 8 & 0 & -4\\ -2 & -4 & -4 & -4 & -2\\ \end{matrix} \right] \]
LOG 算子到中心的距離與位置加權係數的關係曲線像墨西哥草帽的剖面,所以 LOG 算子也叫墨西哥草帽濾波器。
示例代碼如下:
import cv2 as cv import matplotlib.pyplot as plt # 讀取圖像 img = cv.imread("maliao.jpg") rgb_img = cv.cvtColor(img, cv.COLOR_BGR2RGB) gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 先通過高斯濾波降噪 gaussian = cv.GaussianBlur(gray_img, (3, 3), 0) # 再通過拉普拉斯算子做邊緣檢測 dst = cv.Laplacian(gaussian, cv.CV_16S, ksize=3) LOG = cv.convertScaleAbs(dst) # 用來正常顯示中文標籤 plt.rcParams['font.sans-serif'] = ['SimHei'] # 顯示圖形 titles = ['原始圖像', 'LOG 算子'] images = [rgb_img, LOG] for i in range(2): plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray') plt.title(titles[i]) plt.xticks([]), plt.yticks([]) plt.show()
小結
邊緣檢測算法主要是基於圖像強度的一階和二階導數,但導數通常對噪聲很敏感,因此需要採用濾波器來過濾噪聲,並調用圖像增強或閾值化算法進行處理,最後再進行邊緣檢測。
參考
https://blog.csdn.net/Eastmount/article/details/89056240