《FFDNet: Toward a Fast and Flexible Solution for CNN based Image Denoising》閱讀筆記

目錄

一、摘要

二、網絡結構

三、實驗

A. Dataset Generation and Network Training

B.Experiments on AWGN Removal

C. Experiments on Spatially Variant AWGN Removal

D. Experiments on Noise Level Sensitivity

E. Experiments on Real Noisy Images

四、代碼

五、參考資料


一、摘要

已存在的模型存在如下缺點:不同的噪聲水平需要不同的模型,不能用來處理空間噪聲,缺乏靈活性。

爲了解決這些問題,我們提出了一種快速、靈活的卷積神經網絡,即FFDNet,它以一個可調的噪聲水平圖作爲輸入。提出的

FFDNet對下采樣的子圖像進行處理,在推理速度和去噪性能之間取得了良好的平衡。與現有的有區別的去噪器相比,

FFDNet具有幾個令人滿意的特性,包括

(i)處理不同噪音水平的能力

(ii)通過指定非均勻的噪聲水平圖來消除空間變異噪聲的能力;

(iii)即使在CPU上也比基準BM3D更快的速度,同時不犧牲去噪性能。

To overcome the drawbacks of existing CNN based denoising methods, we present a fast and flexible denoising convolutional neural network (FFDNet). Specifically, our FFDNet is formulated as x = F(y; M; Θ), where M is a noise level
map. In the DnCNN model x = F(y; Θσ), the parameters Θσ vary with the change of noise level σ, while in the FFDNet
model, the noise level map is modeled as an input and the  model parameters Θ are invariant to noise level. Thus, FFDNet
provides a flexible way to handle different noise levels with a single network.

The main contribution of our work is summarized as follows: 

1、提出了一種快速、靈活的圖像去噪網絡FFDNet。通過一個可調的噪聲水平圖作爲輸入,一個FFDNet能夠處理不同水平的噪

聲,以及空間變化的噪聲。

2、我們強調確保噪音聲級圖在控制降噪和細節保護之間的平衡方面發揮作用的重要性。

3、FFDNet在AWGN破壞的合成噪聲圖像和真實世界噪聲圖像上都顯示了令人感興趣的結果,展示它在實際圖像去噪方面的力。

We present a single discriminative CNN model, namely FFDNet, to achieve the following three objectives:

1、速度快:降噪器在不犧牲降噪性能的前提下,具有很高的降噪效率。

2、靈活性:去噪器能夠處理不同噪聲水平的圖像,甚至空間變化的噪聲。

3、穩健性:降噪器在控制降噪和細節保存之間的權衡時不應引入視覺假象。

二、網絡結構

在這項工作中,我們採用可調噪聲水平圖M作爲輸入,使去噪模型靈活地達到噪聲水平。爲了提高降噪器的效率,引入了可逆的下采樣操作器,以將W*H*C大小的輸入圖像重新整形爲尺寸爲W/2*H/2*4C的四個下采樣子圖像。這裏C是通道數,即灰度圖像的C=1和彩色圖像的C=3。爲了使噪聲水平圖能夠通過不引入視覺僞像來穩健地控制降噪和細節保持之間的權衡,我們對卷積濾波器採用正交初始化方法。

inputs:  a tensor ~y of size W2 × H2 × (4C + 1)  對於具有噪聲水平σ的空間不變AWGN,M是均勻映射,其中所有元素都是σ。

the first convolution layer:“Conv+ReLU”

the middle layers:“Conv+BN+ReLU”

the last convolution layer:“Conv”

零填充用於在每次卷積後保持特徵映射的大小不變。在最後一個卷積層之後,應用放大操作作爲在輸入級中應用的下采樣操作符的反向運算符,以產生大小爲W*H*C的估計清潔圖像x。

噪聲水平圖

三、實驗

A. Dataset Generation and Network Training

1、訓練數據集

400 BSD images
400 images selected from the validation set of ImageNet
the 4,744 images from the Waterloo Exploration Database
In each epoch, we randomly crop N = 128×8; 000 patches from these images for training.The noisy patches are obtained by adding AWGN of noise level σ 2 [0; 75] to the clean patches.

The mini-batch size is set as 128, and  the rotation and flip based data augmentation is also adopted during training.
2、測試數據集

use BSD68 and Set12 datasets to test FFDNet for removing AWGN noise

use the “RNI6” dataset  to test FFDNet for removing real noise

use the quantized “Clip300” dataset which comprises the 100 images of test set from the BSD300 dataset and 200 images from

PASCALVOC 2012 dataset for evaluating FFDNet-Clip

As for color image denoising, we employ four datasets, namely CBSD68, Kodak24 [59], McMaster [60], and “RNI15” [56], [61].

B.Experiments on AWGN Removal

不同方法對噪聲水平分別爲15、25、35、50和75的SET12數據集的PSNR(DB)結果。最好的兩個結果是分別用紅色和藍色突出顯示

 不同方法在BSD68上的平均PSNR(DB)結果噪音水平分別爲15、25、35、50及75

首先,FFDNet大大超過BM3D,並且在BSD68上的各種噪聲水平上優於WNNM,MLP和TNRD約0.2dB。第二,當噪聲電平低時(例如,),FFDNet稍差於DnCNN,但隨着噪聲電平的增加(例如,)逐漸優於DnCNN。這種現象可能是由於接收場尺寸和建模能力之間的權衡所致。第三,FFDNet在諸如“House”之類的圖像上優於WNNM,而在圖像“Barbara”上則不如WNNM。這是因爲“芭芭拉”具有豐富的重複結構,可以通過非局部自相似性WNNM方法有效地利用。

爲了評估FFDNet-Clip,表IV顯示了Clip300數據集上與DCGRF和RBDN的PSNR比較。可以看出,具有匹配噪聲水平的FFDNet-Clip實現了比DCGRF和RBDN更好的性能,表明FFDNet在削波設置下表現良好。我們還在剪切設置的BSD68數據集上測試了FFDNet-Clip,發現PSNR結果類似於具有非剪切設置的FFDNet。

  對於彩色圖像去噪,我們將FFDNet與CBM3D和CDnCNN 進行比較。表V報告了CBSD68,Kodak24和McMaster數據集上不同方法的性能,圖4顯示了可視化比較。可以看出,FFDNet在定量和定性評估方面在不同噪聲水平上始終優於CBM3D,並且與CDnCNN具有競爭性能。

CBM3D,CDnCNN和FFDNet在噪聲水平 50上的彩色圖像去噪結果。

對於彩色圖像的去噪,我們將FFDNet與CBM3D[11]和CDnCNN[20]。表V報告了不同方法在CBSD68、Kodak24和上的性能
McMaster數據集,圖4給出了可視化比較。可以看出,在不同的噪聲水平下,FFDNet在定量和定性評價上都始終優於CBM3D,並具有與之競爭的性能CDnCNN。

C. Experiments on Spatially Variant AWGN Removal

FFDNet去除空間變異AWGN的例子。(a)噪聲圖像(20.55dB),空間變異AWGN。(b) FFDNet的地面真噪級圖及相應的去噪圖像(30.08dB);(c)利用地面真實噪聲水平圖的均值和相應的FFDNet去噪圖像(27.45dB)構造均勻噪聲水平圖。

D. Experiments on Noise Level Sensitivity

在所有噪聲水平上,FFDNet在輸入噪聲水平相同的情況下,其去噪效果與BM3D和DnCNN相似。

在固定的輸入噪聲水平下,三種方法的PSNR值在地面真噪水平較低時趨於一致,在地面真噪水平較高時開始下降。

當輸入噪聲水平與地面真值水平匹配時,獲得最佳的視覺質量。BM3D和FFDNet在較低的輸入噪聲水平下產生相似的視覺效果,但在較高的輸入噪聲水平下表現出一定的差異。這兩種方法都能在平坦區域平滑噪聲,並隨着輸入噪聲水平的增加,逐步平滑圖像結構。特別地,FFDNet可能會消除一些低對比度的線結構由於使用了非局部信息,無論輸入噪聲水平如何,BM3D仍然可以保持平均patch。

使用較高的輸入噪聲水平通常可以比使用較低的輸入噪聲水平產生更好的視覺效果。此外,當輸入噪聲水平略高於地面真值水平時,沒有多大的視覺差異。

根據以上觀察,FFDNet在平衡降噪和細節保存方面表現出與BM3D和DnCNN相似的噪聲水平敏感性。當地面真實噪聲水平未知時,設置較大的輸入噪聲水平比設置較低的輸入噪聲水平更有利於去除感知質量較好的噪聲。

E. Experiments on Real Noisy Images

不同方法對實際噪聲圖像的灰度圖像去噪效果不同。自上而下:噪聲圖像,噪聲診所降噪圖像,BM3D降噪圖像,DnCNN降噪圖像,dncn - b降噪圖像,FFDNet降噪圖像。(一)σ= 14 DnCNN (15);(b)σ
= 15;(c)σ= 10;(d)σ= 20;(e)σ= 20;(f)σ= 7 DnCNN (10)。

不同方法對實際噪聲圖像的彩色圖像去噪效果不同。從上到下:噪聲圖像,噪聲診所降噪圖像,CBM3D降噪圖像,cdncn - b降噪圖像,FFDNet降噪圖像。(一)σ= 28;(b)σ= 15;(c)σ= 12;(d)σ= 40;(e)σ= 45。

FFDNet對真實圖像的去噪效果較好。(一)σ= 70;(b)σ= 15;(c)σ= 10;(d)σ= 15;(e)σ= 18;(f)σ= 15;(g)σ= 30;(h)
σ= 12;σ= 25。

以FFDNet爲例,研究了具有空間變異噪聲的圖像“玻璃”。(一)嘈雜的圖像;(b)噪音診所去噪圖像;(c)的去噪圖像FFDNetσ= 10;(d)的去噪圖像FFDNetσ= 25;(e)的去噪圖像FFDNetσ= 35;(f)採用FFDNet對圖像進行去噪處理,得到非均勻噪聲水平圖

四、代碼

鏈接https://github.com/Aoi-hosizora/FFDNet_pytorch

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable

import utils

class FFDNet(nn.Module):

    def __init__(self, is_gray):
        super(FFDNet, self).__init__()

        if is_gray:
            self.num_conv_layers = 15 # all layers number
            self.downsampled_channels = 5 # Conv_Relu in
            self.num_feature_maps = 64 # Conv_Bn_Relu in
            self.output_features = 4 # Conv out
        else:
            self.num_conv_layers = 12
            self.downsampled_channels = 15
            self.num_feature_maps = 96
            self.output_features = 12
            
        self.kernel_size = 3
        self.padding = 1
        
        layers = []
        # Conv + Relu
        layers.append(nn.Conv2d(in_channels=self.downsampled_channels, out_channels=self.num_feature_maps, \
                                kernel_size=self.kernel_size, padding=self.padding, bias=False))
        layers.append(nn.ReLU(inplace=True))

        # Conv + BN + Relu
        for _ in range(self.num_conv_layers - 2):
            layers.append(nn.Conv2d(in_channels=self.num_feature_maps, out_channels=self.num_feature_maps, \
                                    kernel_size=self.kernel_size, padding=self.padding, bias=False))
            layers.append(nn.BatchNorm2d(self.num_feature_maps))
            layers.append(nn.ReLU(inplace=True))
        
        # Conv
        layers.append(nn.Conv2d(in_channels=self.num_feature_maps, out_channels=self.output_features, \
                                kernel_size=self.kernel_size, padding=self.padding, bias=False))

        self.intermediate_dncnn = nn.Sequential(*layers)

    def forward(self, x, noise_sigma):
        noise_map = noise_sigma.view(x.shape[0], 1, 1, 1).repeat(1, x.shape[1], x.shape[2] // 2, x.shape[3] // 2)

        x_up = utils.downsample(x.data) # 4 * C * H/2 * W/2
        x_cat = torch.cat((noise_map.data, x_up), 1) # 4 * (C + 1) * H/2 * W/2
        x_cat = Variable(x_cat)

        h_dncnn = self.intermediate_dncnn(x_cat)
        y_pred = utils.upsample(h_dncnn)
        return y_pred

下采樣與上採樣

def downsample(x):
    """
    :param x: (C, H, W)
    :param noise_sigma: (C, H/2, W/2)
    :return: (4, C, H/2, W/2)
    """
    # x = x[:, :, :x.shape[2] // 2 * 2, :x.shape[3] // 2 * 2]
    N, C, W, H = x.size()
    idxL = [[0, 0], [0, 1], [1, 0], [1, 1]]

    Cout = 4 * C
    Wout = W // 2
    Hout = H // 2

    if 'cuda' in x.type():
        down_features = torch.cuda.FloatTensor(N, Cout, Wout, Hout).fill_(0)
    else:
        down_features = torch.FloatTensor(N, Cout, Wout, Hout).fill_(0)
    
    for idx in range(4):
        down_features[:, idx:Cout:4, :, :] = x[:, :, idxL[idx][0]::2, idxL[idx][1]::2]

    return down_features

def upsample(x):
    """
    :param x: (n, C, W, H)
    :return: (n, C/4, W*2, H*2)
    """
    N, Cin, Win, Hin = x.size()
    idxL = [[0, 0], [0, 1], [1, 0], [1, 1]]
    
    Cout = Cin // 4
    Wout = Win * 2
    Hout = Hin * 2

    up_feature = torch.zeros((N, Cout, Wout, Hout)).type(x.type())
    for idx in range(4):
        up_feature[:, :, idxL[idx][0]::2, idxL[idx][1]::2] = x[:, idx:Cin:4, :, :]

    return up_feature

五、參考資料

1、discriminative learning methods

機器學習與深度學習裏生成模型和判別模型的理解

2、downsampled subimages:

卷積神經網絡CNN基本概念(二)上採樣 下采樣

3、spatially variant noise

4、Bayesian

初探貝葉斯推斷

5、additive white Gaussian noise (AWGN)

基礎知識補充——白噪聲、高斯白噪聲

噪聲,白噪聲,加性噪聲和乘性噪聲

6、orthogonal  initialization

RNN的梯度消失/爆炸與正交初始化

7、MAP Inference Guided Discriminative Learning

詳解最大似然估計(MLE)、最大後驗概率估計(MAP),以及貝葉斯公式的理解

8、Plain Discriminative Learning(普通判別學習)

生成模型 VS 判別模型 (含義、區別、對應經典算法)

9、Clipping of Noisy Images for Training

10、RNI6 dataset

11、ground-truth clean images

圖像中裏面的Ground Truth是什麼意思

12、receptive field

感受野( Receptive Field)

13、pytorch repeat() view()粗淺認識

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章