1. 程式人生 > >Python3+OpenCV3影象處理(七)—— 濾波與模糊操作

Python3+OpenCV3影象處理(七)—— 濾波與模糊操作

過濾是訊號和影象處理中基本的任務。其目的是根據應用環境的不同,選擇性的提取影象中某些認為是重要的資訊。過濾可以移除影象中的噪音、提取感興趣的可視特徵、允許影象重取樣等等。頻域分析將影象分成從低頻到高頻的不同部分。低頻對應影象強度變化小的區域,而高頻是影象強度變化非常大的區域。在頻率分析領域的框架中,濾波器是一個用來增強影象中某個波段或頻率並阻塞(或降低)其他頻率波段的操作。低通濾波器是消除影象中高頻部分,但保留低頻部分。高通濾波器消除低頻部分。參考部落格:https://blog.csdn.net/sunny2038/article/details/9155893

個人認為模糊操作就是過濾掉影象中的一些特殊噪音。

  

一、均值模糊、中值模糊、使用者自定義模糊

程式碼如下:

複製程式碼

#均值模糊、中值模糊、自定義模糊    模糊是卷積的一種表象
import cv2 as cv
import numpy as np

def blur_demo(image):      #均值模糊  去隨機噪聲有很好的去燥效果
    dst = cv.blur(image, (1, 15))    #(1, 15)是垂直方向模糊,(15, 1)還水平方向模糊
    cv.namedWindow('blur_demo', cv.WINDOW_NORMAL)
    cv.imshow("blur_demo", dst)

def median_blur_demo(image):    # 中值模糊  對椒鹽噪聲有很好的去燥效果
    dst = cv.medianBlur(image, 5)
    cv.namedWindow('median_blur_demo', cv.WINDOW_NORMAL)
    cv.imshow("median_blur_demo", dst)

def custom_blur_demo(image):    # 使用者自定義模糊
    kernel = np.ones([5, 5], np.float32)/25   #除以25是防止數值溢位 
    dst = cv.filter2D(image, -1, kernel)
    cv.namedWindow('custom_blur_demo', cv.WINDOW_NORMAL)
    cv.imshow("custom_blur_demo", dst)

src = cv.imread('E:\imageload\lenanoise.jpg')
cv.namedWindow('input_image', cv.WINDOW_NORMAL)
cv.imshow('input_image', src)

blur_demo(src)
median_blur_demo(src)
custom_blur_demo(src)

cv.waitKey(0)
cv.destroyAllWindows()

複製程式碼

執行結果:

注意:

1.均值濾波是典型的線性濾波演算法,它是指在影象上對目標畫素給一個模板,該模板包括了其周圍的臨近畫素(以目標畫素為中心的周圍8個畫素,構成一個濾波模板,即去掉目標畫素本身),再用模板中的全體畫素的平均值來代替原來畫素值。

低通濾波(均值模糊)函式原型:blur(src, ksize[, dst[, anchor[, borderType]]]) -> dst

src引數表示待處理的輸入影象。

ksize引數表示模糊核心大小。比如(1,15)表示生成的模糊核心是一個1*15的矩陣。

dst引數表示輸出與src相同大小和型別的影象。

anchor引數、borderType引數可忽略

中值濾波(中值模糊)函式原型:medianBlur(src, ksize[, dst]) -> dst

src引數表示待處理的輸入影象。

ksize引數表示濾波視窗尺寸,必須是奇數並且大於1。比如這裡是5,中值濾波器就會使用5×5的範圍來計算,即對畫素的中心值及其5×5鄰域組成了一個數值集,對其進行處理計算,當前畫素被其中值替換掉。

dst引數表示輸出與src相同大小和型別的影象。

3.使用者自定義模糊

所用函式:filter2D()

函式原型: filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]) -> dst

src引數表示待處理的輸入影象。

ddepth引數表示目標影象深度,輸入值為-1時,目標影象和原影象深度保持一致

 kernel: 卷積核(或者是相關核),一個單通道浮點型矩陣。修改kernel矩陣即可實現不同的模糊

二、高斯模糊

程式碼如下:

複製程式碼

#高斯模糊    輪廓還在,保留影象的主要特徵  高斯模糊比均值模糊去噪效果好
import cv2 as cv
import numpy as np

def clamp(pv):
    if pv > 255:
        return 255
    if pv < 0:
        return 0
    else:
        return pv

def gaussian_noise(image):        #加高斯噪聲
    h, w, c = image.shape
    for row in range(h):
        for col in range(w):
            s = np.random.normal(0, 20, 3)
            b = image[row, col, 0]   #blue
            g = image[row, col, 1]   #green
            r = image[row, col, 2]   #red
            image[row, col, 0] = clamp(b + s[0])
            image[row, col, 1] = clamp(g + s[1])
            image[row, col, 2] = clamp(r + s[2])
    cv.namedWindow("noise image", cv.WINDOW_NORMAL)
    cv.imshow("noise image", image)
    dst = cv.GaussianBlur(image, (15, 15), 0)  # 高斯模糊
    cv.namedWindow("Gaussian", cv.WINDOW_NORMAL)
    cv.imshow("Gaussian", dst)

src = cv.imread('E:\imageload\lena.jpg')
cv.namedWindow("input_image", cv.WINDOW_NORMAL)
cv.imshow('input_image', src)

gaussian_noise(src)
dst = cv.GaussianBlur(src, (15,15), 0)   #高斯模糊
cv.namedWindow("Gaussian Blur", cv.WINDOW_NORMAL)
cv.imshow("Gaussian Blur", dst)

cv.waitKey(0)
cv.destroyAllWindows()

複製程式碼

執行結果:

注意:

1.高斯模糊實質上就是一種均值模糊,只是高斯模糊是按照加權平均的,距離越近的點權重越大,距離越遠的點權重越小。通俗的講,高斯濾波就是對整幅影象進行加權平均的過程,每一個畫素點的值,都由其本身和鄰域內的其他畫素值經過加權平均後得到。

2.高斯分佈的一維和二維原理如下:

   補:高斯分佈的標準差σ。標準差代表著資料的離散程度,如果σ較小,那麼生成的模板的中心繫數較大,而周圍的係數較小,這樣對影象的平滑效果就不是很明顯;反之,σ較大,則生成的模板的各個係數相差就不是很大,比較類似均值模板,對影象的平滑效果比較明顯。高斯模糊具體原理見博文:https://blog.csdn.net/u012992171/article/details/51023768

3.高斯模糊GaussianBlur函式原型:GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]]) -> dst

src引數表示待處理的輸入影象。

ksize引數表示高斯濾波器模板大小。 ksize.width和ksize.height可以不同,但它們都必須是正數和奇數。或者,它們可以是零,即(0, 0),然後從σ計算出來。

sigmaX引數表示 X方向上的高斯核心標準差。

sigmaY引數表示 Y方向上的高斯核心標準差。 如果sigmaY為零,則設定為等於sigmaX,如果兩個sigma均為零,則分別從ksize.width和ksize.height計算得到。

  補:若ksize不為(0, 0),則按照ksize計算,後面的sigmaX沒有意義。若ksize為(0, 0),則根據後面的sigmaX計算ksize

4.numpy包裡的random模組用於生成隨機數,random模組裡的normal函式表示的是生成高斯隨機數。

normal函式預設原型:normal(loc=0.0, scale=1.0, size=None)。

loc引數表示高斯分佈的中心點。

scale引數表示高斯分佈的標準差σ。

size引數表示產生隨機數的個數。size取值可以為(m,n,k),表示繪製m*n*k個樣本。

三、邊緣保留濾波EPF

  進行邊緣保留濾波通常用到兩個方法:高斯雙邊濾波和均值遷移濾波。

程式碼如下:

複製程式碼

#邊緣保留濾波(EPF)  高斯雙邊、均值遷移
import cv2 as cv
import numpy as np

def bi_demo(image):   #雙邊濾波
    dst = cv.bilateralFilter(image, 0, 100, 15)
    cv.namedWindow("bi_demo", cv.WINDOW_NORMAL)
    cv.imshow("bi_demo", dst)

def shift_demo(image):   #均值遷移
    dst = cv.pyrMeanShiftFiltering(image, 10, 50)
    cv.namedWindow("shift_demo", cv.WINDOW_NORMAL)
    cv.imshow("shift_demo", dst)

src = cv.imread('E:/imageload/example.png')
cv.namedWindow('input_image', cv.WINDOW_NORMAL)
cv.imshow('input_image', src)

bi_demo(src)
shift_demo(src)

cv.waitKey(0)
cv.destroyAllWindows()

複製程式碼

執行結果:

注意:

1.雙邊濾波(Bilateral filter)是一種非線性的濾波方法,是結合影象的空間鄰近度和畫素值相似度的一種折中處理,同時考慮空域資訊和灰度相似性,達到保邊去噪的目的。雙邊濾波器顧名思義比高斯濾波多了一個高斯方差sigma-d,它是基於空間分佈的高斯濾波函式,所以在邊緣附近,離的較遠的畫素不會太多影響到邊緣上的畫素值,這樣就保證了邊緣附近畫素值的儲存。但是由於儲存了過多的高頻資訊,對於彩色影象裡的高頻噪聲,雙邊濾波器不能夠乾淨的濾掉,只能夠對於低頻資訊進行較好的濾波

2.雙邊濾波函式原型:bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]]) -> dst

src引數表示待處理的輸入影象。

d引數表示在過濾期間使用的每個畫素鄰域的直徑。如果輸入d非0,則sigmaSpace由d計算得出,如果sigmaColor沒輸入,則sigmaColor由sigmaSpace計算得出。

sigmaColor引數表示色彩空間的標準方差,一般儘可能大。較大的引數值意味著畫素鄰域內較遠的顏色會混合在一起,從而產生更大面積的半相等顏色。

sigmaSpace引數表示座標空間的標準方差(畫素單位),一般儘可能小。引數值越大意味著只要它們的顏色足夠接近,越遠的畫素都會相互影響。當d > 0時,它指定鄰域大小而不考慮sigmaSpace。 否則,d與sigmaSpace成正比。

雙邊濾波原理:

3.均值漂移pyrMeanShiftFiltering函式原型:pyrMeanShiftFiltering(src, sp, sr[, dst[, maxLevel[, termcrit]]]) -> dst

src引數表示輸入影象,8位,三通道影象。

sp引數表示漂移物理空間半徑大小。

sr引數表示漂移色彩空間半徑大小。

dst引數表示和源圖象相同大小、相同格式的輸出圖象。

maxLevel引數表示金字塔的最大層數。

termcrit引數表示漂移迭代終止條件。

均值漂移原理: