前面提到,带有噪声的图像可以看作原始图像函数与噪声函数的和。 
f(x,y)=I(x,y)+Noise(x,y)
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。如下图所示: 

深度学习图像降噪任务 图像降噪的目的_深度学习图像降噪任务_02

通过像素点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", 0)
row, column = lena.shape
noise_salt = np.random.randint(0, 256, (row, column))
rand = 0.01
noise_salt = np.where(noise_salt < rand * 256, 255, 0)
lena.astype("float")
noise_salt.astype("float")
salt = lena + noise_salt
salt = np.where(salt > 255, 255, salt)
salt.astype("uint8")

深度学习图像降噪任务 图像降噪的目的_像素点_03

下面的代码用于平均操作对图像进行降噪,可以看到白点淡化了许多:

reduce = salt[:]
for x in range(1, row - 1):
    for y in range(1, column - 1):
        average = 0
        for i in [-1, 0, 1]:
            for j in [-1, 0, 1]:
                average += salt[x + i, y + j]
        reduce[x, y] = average // 9
reduce.astype("uint8")

深度学习图像降噪任务 图像降噪的目的_深度学习图像降噪任务_04