天天看點

圖像平均操作為什麼能降噪

前面提到,帶有噪聲的圖像可以看作原始圖像函數與噪聲函數的和。

f(x,y)=I(x,y)+Noise(x,y)

那麼我們怎樣從帶有噪聲的圖像f(x, y)中去掉Noise得到I(x, y)呢?很自然的能想到,既然能加上噪聲函數,那麼把噪聲函數減去不就行了。

是這樣的,當然可以這樣想。但是,絕大多數時候我們并不知道噪聲函數是怎樣的,即使知道噪聲函數的表達式,但噪聲函數一般都是随機的。例如鹽噪聲就是随機的改變圖像中的像素點,你并不知道到底改變的是哪些像素點!

那怎麼辦呢?我們知道圖像帶有如下天然的特性:圖像中每個像素點的值與其旁邊的像素點的值比較接近。這很顯然。因為圖像是現實世界的反映。我們現實世界是連續的,除了對象邊界外,每個對象反映在圖像中,其覆寫的區域亮度都比較近似。

既然圖像中的每個像素點的值與其旁邊像素的值比較接近,如果一個像素點的值被噪聲幹擾,那麼是否可以用其周邊區域的像素平均值來代替這個像素點的值呢。

這就是平均操作:即把每個像素的值改變為其與領域像素組成區域的平均值。

領域是針對像素而言的,也就是像素點的周邊區域像素。位于坐标(x, y)處的像素p有4個水準和垂直方向的相鄰像素,這4個像素稱為p的4領域,下圖中标黑色的就是4領域。4領域的像素與p都隻有1個機關距離。

圖像平均操作為什麼能降噪

p還有4個對角相鄰像素,上圖中标綠色的方塊就是。4領域與4對角領域合稱為p的8領域。當然還可以再向外擴充一圈相鄰像素。為什麼用矩形定義領域區域呢?而不是圓,橢圓呢?這當然是為了計算機表達和處理的友善。圖像就是矩陣嘛,領域區域當然也可以看作矩陣。

如果p在圖像的邊界上,那麼其有些相鄰像素将位于圖像外部,這個我們以後再探讨。

如果因為是椒鹽噪聲,像素點的值被噪聲改變成0或255了,那麼通過領域像素的平均值就能把這個像素點的值近似找回來。

我們假設像素點p的值是56,被椒鹽噪聲改變成了0。如下圖所示:

圖像平均操作為什麼能降噪

通過像素點p和周圍8領域的平均操作:(56+56+55+57+0+57+57+56+56)/9=50,像素點p的值就又找回來了。

下面的代碼用于添加1%的鹽噪聲。

import numpy as np
import cv2
lena = cv2.imread("lena.bmp", )
row, column = lena.shape
noise_salt = np.random.randint(, , (row, column))
rand = 
noise_salt = np.where(noise_salt < rand * , , )
lena.astype("float")
noise_salt.astype("float")
salt = lena + noise_salt
salt = np.where(salt > , , salt)
salt.astype("uint8")
           
圖像平均操作為什麼能降噪

下面的代碼用于平均操作對圖像進行降噪,可以看到白點淡化了許多:

reduce = salt[:]
for x in range(, row - ):
    for y in range(, column - ):
        average = 
        for i in [-, , ]:
            for j in [-, , ]:
                average += salt[x + i, y + j]
        reduce[x, y] = average // 9
reduce.astype("uint8")
           
圖像平均操作為什麼能降噪