OpenCV-python 高通濾波器

前言

本節將要介紹OpenCV 提供的三種不同的梯度濾波器,或者說高通濾波器:Sobel,Scharr 和 Laplacian。

總的來說:Sobel,Scharr 其實就是求一階或二階導數。Scharr 是對 Sobel(使用小的卷積核求解求解梯度角度時)的優化。而Laplacian 是求二階導數。


一、Sobel算子

其API如下:

dst = cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])

函數返回其處理結果。

前四個是必須的參數:

    第一個參數是需要處理的圖像;
    第二個參數是圖像的深度,-1表示採用的是與原圖像相同的深度。目標圖像的深度必須大於等於原圖像的深度;
    第三、四參數:dx和dy表示的是求導的階數,0表示這個方向上沒有求導,一般爲0、1、2。

其後是可選的參數:

    dst不用解釋了;
    ksize是Sobel算子的大小,必須爲1、3、5、7。
    scale是縮放導數的比例常數,默認情況下沒有伸縮係數;
    delta是一個可選的增量,將會加到最終的dst中,同樣,默認情況下沒有額外的值加到dst中;
    borderType是判斷圖像邊界的模式。這個參數默認值爲cv2.BORDER_DEFAULT。

注意:第二個參數在代碼中通常使用的卻是 cv2.CV_16S,cv2.CV_64F。這是爲什麼呢?想象一下一個從黑到白的邊界的導數是整數,而一個從白到黑的邊界點導數卻是負數。如果原圖像的深度是np.int8 時,所有的負值都會被截斷變成 0,換句話說就是把把邊界丟失掉。所以如果這兩種邊界你都想檢測到,最好的的辦法就是將輸出的數據類型設置的更高,比如 cv2.CV_16S,cv2.CV_64F 等。取絕對值然後再把它轉回到 cv2.CV_8U。
 

import cv2
import numpy as np
 
filenames = '/longmao.png'
img = cv2.imread(filenames)
cv2.imshow('orginal',img)
#sobel處理
imgx = cv2.Sobel(img,cv2.CV_16S,1,0,ksize=3)
imgy = cv2.Sobel(img,cv2.CV_16S,0,1,ksize=3)
#轉回uint8
imgx_uint8 = cv2.convertScaleAbs(imgx)
imgy_uint8 = cv2.convertScaleAbs(imgy)
#x,y方向組合
img = cv2.addWeighted(imgx_uint8,0.5,imgy_uint8,0.5,0)
 
cv2.imshow('sobelimg',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

結果:

二、Scharr算子

基本和Sobel算子一樣,只是沒有了超參數ksize,使用固定的3*3ksize。

#scharr處理
sobelimgx = cv2.Scharr(img,cv2.CV_16S,1,0)
sobelimgy = cv2.Scharr(img,cv2.CV_16S,0,1)

三、Laplacian 算子

圖像中的邊緣區域,像素值會發生“跳躍”,對這些像素求導,在其一階導數在邊緣位置爲極值,這就是Sobel算子使用的原理——極值處就是邊緣。如下圖:

如果對像素值求二階導數,會發現邊緣處的導數值爲0。如下:

Laplace函數實現的方法是先用Sobel 算子計算二階x和y導數,再求和

#laplace處理
laplace = cv2.Laplacian(img,cv2.CV_16S,ksize=3)
#轉回uint8
laplace_img = cv2.convertScaleAbs(laplace)

結果:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章