Python 影像處理 OpenCV (13): Scharr 運算元和 LOG 運算元邊緣檢測技術

極客挖掘機發表於2020-07-11

前文傳送門:

「Python 影像處理 OpenCV (1):入門」

「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

https://blog.csdn.net/qq_42722197/article/details/103825409

https://www.jianshu.com/p/2ac784fd22fc

相關文章