图像降噪算法——图像噪声模型
图像降噪算法——图像噪声模型
1. 图像噪声建模
首先,我们要区分图像传感器噪声和图像噪声,图像传感器噪声我在博客图像传感器与信号处理——详解图像传感器噪声中有过总结,图像传感器噪声会造成各种各样的图像噪声。
其次,我们需要了解图像降噪模型,图像降噪模型可以建模为: y = x + n y=x+n y=x+n其中, y y y是观察到的噪声图像, x x x是图像真值, n n n是图像噪声,图像降噪过程就是通过 y y y获取 x x x,在许多论文中将这个过程描述为不可逆过程,这也就是为什么图像降噪难。本博客就是对图像噪声 n n n进行建模:
《数字图像处理》一书中对噪声建模主要有一下几种类型:
(1)高斯噪声
高斯噪声是最常见也是最重要的的一种噪声,众多的图像降噪算法都是以降低高斯噪声为目标设计的,其概率密度函数如下所示:
p
(
z
)
=
1
2
π
σ
2
e
−
(
z
−
μ
)
2
/
2
σ
2
p(z)=\frac{1}{\sqrt{2 \pi \sigma^{2}}} e^{-(z-\mu)^{2}} /_{2 \sigma^{2}}
p(z)=2πσ21e−(z−μ)2/2σ2其中,
σ
\sigma
σ是标准偏差,
μ
\mu
μ是灰度值的平均值,这个公式说明的是灰度值为
z
z
z的概率为多少。
(2)瑞利噪声
瑞丽噪声的概率密度函数如下所示:
p
(
z
)
=
{
2
b
(
z
−
a
)
e
−
(
z
−
a
)
2
/
b
,
z
⩾
a
0
,
z
<
a
p(z)=\left\{\begin{array}{ll} \frac{2}{b}(z-a) \mathrm{e}^{-(z-a)^{2} / b}, & z \geqslant a \\ 0, & z<a \end{array}\right.
p(z)={b2(z−a)e−(z−a)2/b,0,z⩾az<a概率密度的均值和方法分别为:
z
ˉ
=
a
+
π
b
/
4
\bar{z}=a+\sqrt{\pi b / 4}
zˉ=a+πb/4
σ
2
=
b
(
4
−
π
)
4
\sigma^{2}=\frac{b(4-\pi)}{4}
σ2=4b(4−π)瑞利噪声对于图像直方图近似倾斜的图像中的噪声建模较为有效。
(3)伽马噪声
伽马噪声的概率密度函数如下所示:
p
(
z
)
=
{
a
b
z
b
−
1
(
b
−
1
)
!
e
−
a
z
,
z
⩾
a
0
,
z
<
a
p(z)=\left\{\begin{array}{cl} \frac{a^{b} z^{b-1}}{(b-1) !} \mathrm{e}^{-a z}, & z \geqslant a \\ 0, & z<a \end{array}\right.
p(z)={(b−1)!abzb−1e−az,0,z⩾az<a其中均值和方差分别为
z
ˉ
=
b
a
\bar{z}=\frac{b}{a}
zˉ=ab
σ
2
=
b
a
2
\sigma^{2}=\frac{b}{a^{2}}
σ2=a2b伽马噪声相对瑞利噪声分布会更加倾斜
(4)指数噪声
指数噪声的概率密度函数如下所示:
p
(
z
)
=
{
a
e
−
a
z
,
z
⩾
0
0
,
z
<
0
p(z)=\left\{\begin{array}{ll} a \mathrm{e}^{-a z}, & z \geqslant 0 \\ 0, & z<0 \end{array}\right.
p(z)={ae−az,0,z⩾0z<0其概率密度函数的均值和方差分别为
z
ˉ
=
1
a
\bar{z}=\frac{1}{a}
zˉ=a1
σ
2
=
1
a
2
\sigma^{2}=\frac{1}{a^{2}}
σ2=a21指数噪声分布相对伽马噪声又会进一步倾斜
(5)量化噪声
量化噪声又称均匀噪声,此类噪声是由于将模拟数据转换为数字数据而引起的,因此是幅度量化过程中固有的,其概率密度函数如下:
p
(
z
)
=
{
1
b
−
a
,
a
⩽
z
⩽
b
0
o
t
h
e
r
w
i
s
e
p(z)=\left\{\begin{array}{ll} \frac{1}{b-a}, & a \leqslant z \leqslant b \\ 0 & otherwise \end{array}\right.
p(z)={b−a1,0a⩽z⩽botherwise
(6)椒盐噪声
椒盐噪声又称脉冲噪声、尖峰噪声,在图像上表现为随机分布的黑白点,其概率密度函数如下图所示:
p
(
z
)
=
{
P
a
,
z
=
a
P
b
,
z
=
b
1
−
P
a
−
P
b
,
o
t
h
e
r
w
i
s
e
p(z)=\left\{\begin{array}{ll} P_{a}, & z=a \\ P_{b}, & z=b \\ 1-P_{a}-P_{b}, & otherwise \end{array}\right.
p(z)=⎩⎨⎧Pa,Pb,1−Pa−Pb,z=az=botherwise椒盐噪声可以通过中值滤波器进行消除。
以上即《数字图像处理》中对各个图像噪声的建模,对于的概率密度函数的不同,书中给出了这样一张图予以区分:
那么除了《数字图像处理》中提到的几种图像噪声模型外,一般还有如下几种模型:
(7)泊松噪声
泊松噪声又称散粒噪声,我们知道,光源每秒发射的光子到达CMOS的越多,则该像素的灰度值越大。但是因为光源发射和CMOS接收之间都有可能存在一些因素导致某个光子并没有被CMOS接收到或者某个像素一时间段内发射的光子特别多,所以这就导致了灰度值的波动,也就产生了泊松噪声,方程描述为:
p
[
(
N
(
t
+
τ
)
−
N
(
t
)
)
=
k
]
=
e
−
λ
τ
(
λ
τ
)
k
k
!
k
=
0
,
1
,
…
p[(N(t+\tau)-N(t))=k]=\frac{e^{-\lambda \tau}(\lambda \tau)^{k}}{k !} \quad k=0,1, \dots
p[(N(t+τ)−N(t))=k]=k!e−λτ(λτ)kk=0,1,…这个公式说明的是某个像素在间隔时间
τ
\tau
τ内接收到
k
k
k个光子的概率为多少。
(8)斑点噪声
在相干成像系统(如雷达,激光和声学等)中可以看到斑点噪声的出现,其概率密度函数如下:
p
(
z
)
=
z
a
−
1
e
−
z
/
a
a
−
1
!
a
a
p(z)=\frac{z^{a-1} e^{-z / a}}{a-1 ! a^{a}}
p(z)=a−1!aaza−1e−z/a斑点噪声在光学成像系统中很少出现,因此这里不作赘述。
(6)周期性噪声
周期性噪声无法用概率密度函数进行描述,也无法在空间域中进行消除,通常的方法是通过频域中的带阻滤波器进行消除,如下图所示,从左至右,第一幅图原始图像,第二幅图为频域图像,第三幅图为带阻滤波器,第四幅图为滤波后的图像。
2. C++代码实现
下面分别是生成椒盐噪声和高斯噪声的函数:
at Noise::CreateSaltNoise(const Mat &src, int n)
{
Mat dst = src.clone();
for(int k = 0; k<n; k++)
{
int i = rand() % dst.rows;
int j = rand() % dst.cols;
if(dst.channels() == 1)
{
dst.at<uchar>(i,j) = 255;
}
else
{
dst.at<Vec3b>(i,j)[0] = 255;
dst.at<Vec3b>(i,j)[1] = 255;
dst.at<Vec3b>(i,j)[2] = 255;
}
}
for(int k = 0; k<n; k++)
{
int i = rand() % dst.rows;
int j = rand() % dst.cols;
if(dst.channels() == 1)
{
dst.at<uchar>(i,j) = 0;
}
else
{
dst.at<Vec3b>(i,j)[0] = 0;
dst.at<Vec3b>(i,j)[1] = 0;
dst.at<Vec3b>(i,j)[2] = 0;
}
}
return dst;
}
Mat Noise::CreateGaussianNoise(const Mat &src, double mu, double sigma)
{
Mat dst = src.clone();
int row = dst.rows;
int col = dst.cols;
for(int i = 0; i<row; i++)
{
for(int j = 0; j<col; j++)
{
if(dst.channels() == 1)
{
//构建高斯噪声
double u1, u2;
do
{
u1 = rand() * (1.0 / RAND_MAX);
u2 = rand() * (1.0 / RAND_MAX);
} while (u1 <= numeric_limits<double>::min());//u1不能为0
double z = sigma * sqrt(-2.0 * log(u1)) * cos(2 * CV_PI * u2) + mu;
//double z = sigma * sqrt(-2.0 * log(u1)) * sin(2 * CV_PI * u2) + mu;
int val = dst.at<uchar>(i,j) + z * 32;
val = (val<0)?0:val;
val = (val>255)?255:val;
dst.at<uchar>(i,j) = (uchar)val;
}
else
{
for(int k = 0; k<dst.channels(); k++)
{
//构建高斯噪声
double u1, u2;
do
{
u1 = rand() * (1.0 / RAND_MAX);
u2 = rand() * (1.0 / RAND_MAX);
} while (u1 <= numeric_limits<double>::min());//u1不能为0
double z = sigma * sqrt(-2.0 * log(u1)) * cos(2 * CV_PI * u2) + mu;
//double z = sigma * sqrt(-2.0 * log(u1)) * sin(2 * CV_PI * u2) + mu;
int val = dst.at<Vec3b>(i,j)[k] + z * 32;
int test = dst.at<Vec3b>(i,j)[k];
val = (val<0)?0:val;
val = (val>255)?255:val;
dst.at<Vec3b>(i,j)[k] = (uchar)val;
}
}
}
}
return dst;
}
下面是运行结果:
首先,下面是原图:
加上高斯噪声后的结果
加上椒盐噪声后的结果:
3. 结论
- 高斯噪声、瑞丽噪声、伽马噪声、指数噪声其实是比较类似的,只是统计分布会稍有区别,如果用代码实现应该是类似的。
- 研究图像噪声模型对于图像降噪算法的实现是非常重要的,比如我看Review的时候就有大佬提到,对于目前效果最好的深度学习降噪算法,其难于实际应用的一个方面就是训练模型所用的噪声都是高斯噪声,而我们摄像头拍摄图像的实际噪声要远比高斯噪声复杂,因此如果更好地对图像噪声进行建模非常重要。
那这一小节就总结到这儿啦,有问题欢迎交流~
此外,这里我写一个各种算法的总结目录图像降噪算法——图像降噪算法总结,对图像降噪算法感兴趣的同学欢迎参考