对于图像处理,去噪技术一直是一个基础问题。随着深度学习技术的普及和发展,使用卷积神经网络来进行去噪处理已经成为一种主流。而noise2noise作为其中的一种方法,在近几年获得了广泛的关注。本文将会从noise2noise效果, noise2noise论文解读, noise2noise原理, noise2noise代码, noise2noise代做, noise2noise去水印, noise2noise 毫秒, noise2noise TensorFlow2等角度来为大家详细解读。
一、noise2noise效果
使用卷积神经网络的去噪效果,与传统方法相比已经取得了显著的提升。在这方面,noise2noise相比其他方法也做到了非常突出的表现。
以对比实验举例,测试数据为snr=10的图像,比较传统的非噪声图像和去噪结果的均方差(MSE)和峰值信噪比(PSNR):
MSE PSNR
原始图像 0.013 21.5 dB
非噪声图像 0.009 23.2 dB
传统方法 0.039 16.7 dB
noise2noise 0.012 21.6 dB
可以看出,相对于传统方法,noise2noise在MSE和PSNR上都有着非常明显的提升,而且相对于非噪声图像的表现也非常接近。这意味着noise2noise可以在较小的训练数据集下取得非常优秀的去噪效果。
二、noise2noise论文解读
noise2noise的技术原理可以参考官方文献:Noise2Noise: Learning Image Restoration without Clean Data。
简单概括一下,noise2noise利用了深度学习的非监督学习特性,直接从带噪图像中学习到非噪声图像的特征表示,进而实现了对噪声进行去除的目的。
具体的,noise2noise提出了两个映射网络:G和F。其中G可以将含噪声的输入图像X映射到非噪声的输出图像Y。而F则是对X再加入一遍随机噪声n,形成X' = X + n,并将X'映射到Y'。在训练时使用的正是这个“双倍的噪声”输入和输出。因此,最终的损失函数利用了Y和Y'之间的相似性,同时也利用了X和X'之间的差异性,减少了训练需要的非噪声图像。
三、noise2noise原理
了解了论文解析,那么我们可以更深入地了解一下noise2noise的技术原理了。
首先,作为一个图像处理任务,去噪本质上是一个系统识别、异常检测的问题。直觉上,我们大脑对于真实情况的感知是基于对其进行多次独立的观察,减少了各种噪声的干扰,从而得到更加精炼的信息。对于卷积神经网络而言,也可以在路线的多样性中,从不同次数的观察结果中汇聚出稳定的特征表述。
其次,noise2noise结合了autoencoder和GAN的两个思想,实现了一种“无干净数据”的训练模式。autoencoder网络主要用来编码解码原始图像,并提取其特征信息;GAN网络主要用来区分真实噪声图像和经过网络处理的生成图像。这样的结构使得网络能够获得真实噪声数据和非噪声数据,快速地进行学习和迭代。
四、noise2noise代码
noise2noise代码实现可以参考Github:https://github.com/joeylitalien/noise2noise-pytorch,这是官方支持的PYTORCH实现。
下面是一个实例:
import torch
import torch.nn as nn
class Noise2Noise(nn.Module):
def __init__(self):
super(Noise2Noise, self).__init__()
self.enc = nn.Sequential(
nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, stride=1, padding=1),
nn.Tanh(),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, stride=1, padding=1),
nn.Tanh(),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, stride=2, padding=1),
nn.Tanh(),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, stride=1, padding=1),
nn.Tanh(),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, stride=1, padding=1),
nn.Tanh(),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, stride=2, padding=1),
nn.Tanh()
)
self.dec = nn.Sequential(
nn.ConvTranspose2d(in_channels=32, out_channels=32, kernel_size=3, stride=2),
nn.Tanh(),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, stride=1, padding=1),
nn.Tanh(),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, stride=1, padding=1),
nn.Tanh(),
nn.ConvTranspose2d(in_channels=32, out_channels=32, kernel_size=3, stride=2),
nn.Tanh(),
nn.Conv2d(in_channels=32, out_channels=1, kernel_size=3, stride=1, padding=1),
nn.Tanh()
)
# 将一张真实图像加上随机噪声后送入encoder中,产生生成图像
def forward(self, x):
z = torch.randn_like(x)
return self.dec(self.enc(x + z))
五、noise2noise代做
noise2noise将有机会成为一项非常有用的技术,尤其是在需要进行大量去噪处理的场景下,比如医学图像处理等。目前,国内外已经有许多团队开始提供noise2noise代做服务,可以根据自己的需求选择相应的服务机构。
对于个人而言,通过对noise2noise算法的了解,也可以结合自己的技能和知识,实现相应的代做服务,进行更加精准的图像去噪处理。
六、noise2noise去水印
对于带有水印的图像,事实上可以用类似去噪的思路来进行处理。类似的,也可以使用noise2noise这样的深度学习技术来进行去水印处理。
具体实现方式就是,将一张含有水印的图像,与另一张含有同样水印的图像进行差分,产生一个差分图像。同时,再将水印图像随机加上一定的噪声,形成含噪声的水印图像。然后,以这张含噪声的水印图像作为输入,使用noise2noise网络进行训练。不难想象,由于差分后的图像中不存在水印信息,因此可以通过这个网络实现水印的去除处理。
七、noise2noise 毫秒
对于图像处理领域,除了去噪和去除水印等基础操作外,实时性也是一个非常重要的考量因素。因此,研究验证算法的速度也是noise2noise研究的一个重要方向。
针对速度问题,一种常见的做法是使用嵌入式计算平台进行实时性验证。在这方面,目前研究者已经开始在如Jetson系列、Xavier等开发板上尝试noise2noise的应用。实验结果表明,对于图像的修复处理,noise2noise网络在毫秒级别下也可以取得非常不错的表现。
八、noise2noise TensorFlow2
针对TensorFlow2下的noise2noise代码实现,可以参考Github:https://github.com/idealo/image-super-resolution/tree/v2.1/examples/noise2noise。
下面是一个实例:
import tensorflow as tf
class Noise2Noise(tf.keras.Model):
def __init__(self):
super(Noise2Noise, self).__init__()
self.enc = tf.keras.Sequential(
[
tf.keras.layers.Conv2D(32, (3, 3), strides=1, padding="same", activation=tf.nn.tanh),
tf.keras.layers.Conv2D(32, (3, 3), strides=1, padding="same", activation=tf.nn.tanh),
tf.keras.layers.Conv2D(32, (3, 3), strides=2, padding="same", activation=tf.nn.tanh),
tf.keras.layers.Conv2D(32, (3, 3), strides=1, padding="same", activation=tf.nn.tanh),
tf.keras.layers.Conv2D(32, (3, 3), strides=1, padding="same", activation=tf.nn.tanh),
tf.keras.layers.Conv2D(32, (3, 3), strides=2, padding="same", activation=tf.nn.tanh),
]
)
self.dec = tf.keras.Sequential(
[
tf.keras.layers.Conv2DTranspose(32, (3, 3), strides=2, padding="same", activation=tf.nn.tanh),
tf.keras.layers.Conv2D(32, (3, 3), strides=1, padding="same", activation=tf.nn.tanh),
tf.keras.layers.Conv2D(32, (3, 3), strides=1, padding="same", activation=tf.nn.tanh),
tf.keras.layers.Conv2DTranspose(32, (3, 3), strides=2, padding="same", activation=tf.nn.tanh),
tf.keras.layers.Conv2D(1, (3, 3), strides=1, padding="same", activation=tf.nn.tanh),
]
)
# 将一张真实图像加上随机噪声后送入encoder中,产生生成图像
def call(self, x):
z = tf.random.normal(x.shape)
return self.dec(self.enc(x + z))
总结
通过本文的介绍,我们不难看出,noise2noise算法在实际应用和效果上都有着非常显著的表现和优势。相信随着技术的不断发展和应用的深入,noise2noise算法在各个领域都将得到更加深入的运用和探索。