您的位置:

noise2noise:从去噪到图像修复

对于图像处理,去噪技术一直是一个基础问题。随着深度学习技术的普及和发展,使用卷积神经网络来进行去噪处理已经成为一种主流。而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算法在各个领域都将得到更加深入的运用和探索。