前言:在数字时代,图像已成为我们记录生活、传达信息、探索世界的重要媒介。然而,随着摄影技术的飞速发展,图像噪声——这一影响图像质量的顽疾,始终困扰着我们。Noise2Noise图像去噪技术为我们提供了一种全新的解决方案。不同于传统的去噪方法,Noise2Noise技术凭借其独特的思路和高效的性能,在图像处理领域引起了广泛关注。它不仅能够帮助我们恢复被噪声污染的图像,还能在保持图像细节的同时,提高图像的整体质量。
本文所涉及所有资源均在传知代码平台可获取
目录
概述
演示效果
核心代码
写在最后
概述
本文复现论文Noise2Noise: Learning Image Restoration without Clean Data中提出的图像去噪方法,并使用最广泛应用的高斯噪声与泊松噪声来做实验,原文连接 地址 ,具体如下:
该论文证明了,对于同一张干净图片,如果分两次污染它所用的噪声同分布且0均值的情况下,那么用这一对噪声图像进行网络训练即noise2noise的训练方法就能达到与用干净-噪声图像对即noise2clean的训练方法接近的去噪效果,该方法在无监督与自监督方法中效果几乎达到了最好,相比ZS-Noise2Noise这样的方法效果要优秀非常多,与有监督方法的效果相近! 论文在多种噪声和测试数据集上进行了实验,本文只选取高斯噪声与泊松噪声并在官方测试数据集中选取了一个进行测试。
对于干净的图片分布,我们用xcleanxclean表示。在现实的生产生活中,干净的图片经常会被噪声所污染,变为xnoisexnoise,污染的过程我们可以使用如下过程表示:
其中noisenoise最常见的分布便是高斯分布与泊松分布,在深度学习中,图像的去噪任务就是尽可能学习到一个模型使得:
其中f为模型,θ为训练过程中学习到的模型参数。当然在现实中是不可能的,我们只能使我们的模型尽可能去逼近理想效果,即:
为了达到以上效果,有监督学习采取的方法是是最小化训练数据与标签的损失函数来学习模型参数即:
其中L代表我们选取的损失函数,在图像训练中通常为L2损失或L1损失,具体到某个数据集上,有监督学习的过程实际上就是如下过程:
其中i代表数据集中的样本标号,当然,有监督学习的效果毋庸置疑,但是在现实生活中这样的图像对获取并不容易,这也成为了制约有监督学习的一大因素。本文算法的亮点就是不用传统有监督学习算法中使用的图像对,而是改用下面这样的图像对进行训练却能达到有监督方法的效果,该方法将有监督学习训练模型的过程改为了:
尽管对于noise1与noise2噪声分布的限制略显苛刻,但本文算法无疑为解决有监督学习的去噪任务中标签数据的难以获取问题提供了一种突破性的思路,在模拟数据的实验结果上证明Noise2Noise的训练方法性能非常接近有监督的训练方法。
演示效果
本代码于Ubuntu系统上编写与测试,在windows11系统上运行需要自行配置相应的版本的pytorch
基础镜像:python3.8.13,进入noise2noise-pytorch-myown项目路径运行以下命令:
pip install -r requirements.txt
不训练仅用已经训好的模型查看效果,可直接运行以下命令:
python example.py
为了简便训练,我们只用其中的5000张做训练集,1000张做验证集即可。完成解压后,运行下列命令即可获得训练集与验证集,分别存储在train与valid路径下:
mkdir train && mkdir valid
find data/ILSVRC2012_img_val/ -maxdepth 1 -type f | head -n 5000 | xargs -I {} mv {} ./train/
find data/ILSVRC2012_img_val/ -maxdepth 1 -type f | tail -n +5001 | head -n 1000 | xargs -I {} mv {} ./valid/
运行下列命令可直接获取BSD300数据集,并将其测试集放在我们项目的test路径下,如果您想在windows系统上使用,或是命令的方式觉得不太清楚,以上工作均可以手动完成,只要最终的结果保证训练集在./train路径下,验证集在./valid路径下,测试集在./test路径下即可:
wget https://www2.eecs.berkeley.edu/Research/Projects/CS/vision/grouping/segbench/BSDS300-images.tgz
tar -zxvf BSDS300-images.tgz
mkdir test
mv BSDS300/images/test/* ./test/
如果您想自行训练模型,用高斯噪声训练直接运行以下命令,需要修改train.py中下列的参数,将gaussian改为poisson即可,然后再运行如下命令:
python train.py
根据你要测试的模型,修改test.py中如下参数,后根据你想要测试的高斯或泊松模型选择在runs/Noise2Noisegaussian/checkpoints或runs/Noise2Noisepoisson/checkpoints路径下存储的你的训练模型路径,将test.py下列的参数替换为你的模型路径,最后,运行如下命令:
python test.py
即可得到测试结果,且会将你的测试集的第一张图的训练与输出结果放到result路径下,如下图所示
最终实现的效果如下所示:
核心代码
下面这段代码实现了对图像进行噪声注入,然后使用注入噪声的图像对去噪模型进行训练的过程。
具体来说,代码中的 get_noisePair 函数用于生成一对噪声图像,其中 noise_type 参数指定噪声类型,可以是高斯噪声或泊松噪声;mode 参数指定模式,可以是训练模式或测试模式。在训练模式下,函数会随机生成噪声参数,包括高斯噪声的标准差和泊松噪声的 λ;在测试模式下,函数会使用默认的噪声参数。生成的噪声图像会被剪裁到 [0, 255] 的范围内,并转换为 PyTorch 的张量。
代码中的 train 函数用于对去噪模型进行训练。它使用了一个数据加载器 train_loader,用于加载训练数据集中的图像。对于每个批次的数据,函数会从中获取一对噪声图像,然后将其中一个作为输入,另一个作为目标输出,对去噪模型进行训练。训练过程中使用了均方误差(MSE)作为损失函数,并使用随机梯度下降(SGD)优化器进行模型优化。在训练过程中,函数会计算平均损失,并将其写入 TensorBoard 中。每个 epoch 结束后,函数会调整学习率,并输出训练过程中的损失:
#获得噪声对
def get_noisePair(image, noise_type='gaussian', mode=None):# Convert tensor to numpy arrayimage_np = image.numpy()# Determine noise parameters based on modeif mode == 'train':if noise_type == 'gaussian':std = np.random.randint(0, 51) # Random standard deviation between 0 and 50elif noise_type == 'poisson':lam = np.random.randint(0, 51) # Random λ between 0 and 50else:std = 25 # Default standard deviation for Gaussian noiselam = 30 # Default λ for Poisson noise# Add noise based on noise_typeif noise_type == 'gaussian':noise = np.random.normal(0, std, size=image_np.shape)source = image_np + noisenoise = np.random.normal(0, std, size=image_np.shape)target = image_np + noiseelif noise_type == 'poisson':noise = np.random.poisson(lam, size=image_np.shape)source = image_np + noisenoise = np.random.poisson(lam, size=image_np.shape)target = image_np + noise# Clip noisy image values to ensure they are within [0, 255] rangesource = np.clip(source, 0, 255)# Convert back to tensorsource = torch.tensor(source, dtype=torch.float32)target = np.clip(target, 0, 255)target = torch.tensor(target, dtype=torch.float32)return source, target#用噪声对训练以获取去噪模型
def train(train_loader, model, optimizer, scheduler, writer, epoch):batch_time = AverageMeter()loss_img = AverageMeter()model.train()end = time.time()step = 0for data in train_loader:source=data["source"]#噪声图像1source=source.cuda()target=data["target"]#噪声图像2target=target.cuda()pred=model(source)loss=mse(pred,target)# loss = 0.01 * loss1 + loss3loss_img.update(loss.item(), target.size(0))batch_time.update(time.time() - end)end = time.time()optimizer.zero_grad()loss.backward()optimizer.step()step += 1writer.add_scalars('train_loss', {'loss_img': loss_img.avg}, epoch + 1)scheduler.step()print('Train Epoch: {}\t train_loss: {:.6f}\t'.format(epoch + 1, loss_img.avg))
写在最后
在深入探讨了Noise2Noise图像去噪技术的原理、应用以及其在图像处理领域的广阔前景后,我们不禁为这一技术的强大潜力所折服。Noise2Noise不仅为我们提供了一种全新的图像去噪思路,更为图像处理领域带来了新的变革,回顾整篇文章,我们不难发现,Noise2Noise技术的核心优势在于其能够在无需清洁图像样本的情况下,仅通过多张含噪声图像的训练,实现对图像噪声的有效去除。这一特点使得Noise2Noise技术在实际应用中具有极高的灵活性和适应性,能够在各种复杂环境下保持稳定的去噪效果。
随着人工智能和深度学习技术的不断发展,Noise2Noise图像去噪技术将迎来更多的发展机遇。我们有理由相信,在不远的将来,Noise2Noise技术将在医疗影像、遥感监测、安防监控等领域发挥更加重要的作用,为我们的生活带来更多便利和美好。
详细复现过程的项目源码、数据和预训练好的模型可从该文章下方附件获取。