noise2noise学习与修改

最近偶然看到的这篇论文,感觉很神奇。才发现已经发表有一段时间了,虽然关注神经网络很久了,但是为我所用的却很少,一方面自己根本就还是个入门者,才刚刚会搭建神经网络,还没训练出一个能用的。另一方面,对神经网络的理解停留在“拟合”层面,不愿再深入研究,只需要找到合适自己的网络拿来用即可。n2n这篇论文很明显是我需要的,但仍然需要消化消化。

目前我面对的问题基本上可以分为两类:

1.求逆过程,如系统标定、计算成像等等

2.图像增强,如denoise、hdr映射

个人认为神经网络类似于黑匣子,用大量的输入输出来作为信息来源,猜测系统的性能参数,很类似于系统的定标,其最大的优势是可以获得先验信息,即目标的特性,类似于求逆问题中的正则项。但用于成像系统的增强,很大一个劣势就是无法获得真正的ground truth。有研究人员为此也付出了很大的努力,如learning to see in the dark文章中的研究组自己使用长曝光时间的图像作为ground truth。那么这篇n2n就给出了一个很好的理论依据,只需要对同一目标独立观测两次,作为输入和输出。原理也很简单,谈一下自己的理解:当样本足够多时,神经网络的输出趋向于图像真值时,loss才最小,因为噪声是随机的,有限的参数是无法将一个随机量映射到另一个随机量,那么唯一的策略就是将噪声去除。

之所以对这篇文章很关注是因为他解决了我面临的问题,我不再需要去费力的采集各种各样的ground truth,只需要快速的采集两次数据,就可以开始训练了。所以我一开始把NVlab的代码扒下来学习一下,傻眼了,代码太复杂,对于我这种代码小白简直就是天书,于是就轻易放弃了。但是一直魂牵梦绕的,于是又开始扒代码,无意中扒到了第三方复现代码,很感谢,这次仔细看了readme文档,发现了新大陆,给出了如何训练、如何验证,不过还是被命令纠缠了一段时间,没见过那么用的,高手就是高手啊。。。人家写的代码,你只要在终端输入命令和参量,就可开始训练了,让我的python世界观彻底改变了。

第三方代码是依照论文实现的,结果也相似。配置好环境,在我的垃圾电脑上居然可以运行了,非常激动,第一次跑起来别人写好的神经网络,赶紧换一台工作站。使用代码作者的数据跑了1个epoch就够了,psnr就达到了28,但是花了我3个小时,就不再继续提示,赶紧试一下效果,很是惊艳。

训练结果对不同power的噪声的适应性还算可以,我自己用matlab自己加了高斯噪声图像进行验证,效果是一样的,但是噪声太大了也是不行的,在一定范围内是可以的。到这里就已经成功了一半,论文也不写了,只想赶快把代码读懂修改成自己可用的。对于这个网络的groundtruth开始我是迷惑的,直到看了github上别人咨询,才直到是对同一图像处理了两次。那么问题就好解决了,只要找到代码中读取图像的位置进行修改就可以,其实代码仔细看看,还是可以理解的,缺的就是安静下来专心看。修改的代码主要在generator.py里面:

class NoisyImageGenerator(Sequence):

    def __init__(self, image_dir, source_noise_model, target_noise_model, batch_size=32, image_size=64):

        image_suffixes = (".jpeg", ".jpg", ".png", ".bmp")

        self.image_paths = [p for p in Path(image_dir).glob("**/*") if p.suffix.lower() in image_suffixes]

        self.source_noise_model = source_noise_model

        self.target_noise_model = target_noise_model

        self.image_num = len(self.image_paths)

        self.batch_size = batch_size

        self.image_size = image_size



        if self.image_num == 0:

            raise ValueError("image dir '{}' does not include any image".format(image_dir))



    def __len__(self):

        return self.image_num // self.batch_size



    def __getitem__(self, idx):

        batch_size = self.batch_size

        image_size = self.image_size

        x = np.zeros((batch_size, image_size, image_size, 3), dtype=np.uint8)

        y = np.zeros((batch_size, image_size, image_size, 3), dtype=np.uint8)

        sample_id = 0



        while True:

            image_path = random.choice(self.image_paths)

            image = cv2.imread(str(image_path))

            h, w, _ = image.shape



            if h >= image_size and w >= image_size:

                h, w, _ = image.shape

                i = np.random.randint(h - image_size + 1)

                j = np.random.randint(w - image_size + 1)

                clean_patch = image[i:i + image_size, j:j + image_size]

                x[sample_id] = self.source_noise_model(clean_patch)

                y[sample_id] = self.target_noise_model(clean_patch)



                sample_id += 1



                if sample_id == batch_size:

                    return x, y

x就是输入,y就是ground truth。所以只要让y重新读入一组图像,和x一一对应就可以了。我只增加了一个groundtruth的路径参数,模仿了读取x的代码,读取y的数据,其他的都不变。当然函数的输入参数也要有变化,验证集数据读取函数中也要相应更改,然后gauss噪声的参数设置为0,0,表示不加噪声。于是开始愉快的训练了,还没有出结果,自己先造一组数据测试下代码是否有误,没问题就开始制作自己的数据,如果没问题可以开始验证自己的想法了。

目前有这样几个想法:

1.既然这个网络的目的是去噪,那么从另一个角度来说,就是获得信号真值本身,这就是一个很好的切入点,这一点本身的应用就很多,我只关心和我相关的。我可以用于光谱成像系统定标,一般光谱定标会多次测量求均值提高精度,但只能增加定标系数的精度,原始数据的精度取决于信噪比,是无法改变的,而实际应用时只能观测一次,所以噪声对光谱的精度影响是无法消除的,那么现在就可利用神经网络将噪声去除,提高精度。

2.探测器的量化噪声也是一种噪声,如果能进一步修改代码,使输出能够提高位深度,是不是就可以在降噪的基础上,提高动态范围?这从另一个角度看,就可以应用于弱信号探测(写到这里突然想起以为老师的优秀算法,可以从信噪比为1的数据中提取出运动小目标的轨迹,也许原理相似),当然这里的弱信号没有被淹没在量化噪声中,弱信号还是比背景要大于(或小于)一个灰度值。

3. 高增益下的图像去噪,一直以为相机的增益没啥用,就是在低增益图像上乘个系数而已,可能噪声还大了。后来才意识到自己错了,增益的最大用处是使电压信号放大到AD的有效范围内,虽然有噪声,甚至信噪比更差,但是信号可以有效的利用AD的位深度。那么这个网络就是一个很好的工具,在特殊应用场景(如高速摄影),可以提高增益,降低曝光时间,使用该网络提高图像质量,也算是一个很好的应用吧。

4.计算成像方面,很多问题是病态问题,或者理论上是适定问题,但实际上噪声抑制成为主要矛盾,其主要原因是相关的矩阵条件数很大,对噪声很敏感,那么如果从原始数据上减少噪声,会不会一定程度上提高计算成像的图像质量呢?当然,这个问题和问题1有相似之处,就是这个网络训练到的参数处理出的数据是不是真值的估计,需要进一步验证。

 

现在就静静的等代码效果了

刚看了deep image prior的效果,貌似没有n2n效果好,个人感觉。

2020.2.28更新

昨晚看了一下效果,PSNR只能到14.9,比较低不知道是哪里的问题,可能我加的噪声比较大?虽然效果不如原始结果惊艳,但是图像效果也有很大的提升。把模型用于没有噪声的图像,发现图像的分辨率是有下降的,对于代码作者的结果,用于无噪声图像,基本上没什么变化,个人认为是训练图像噪声强度不太大。所以如果用于问题1,光谱分辨率可能会下降,这是需要验证的一个内容。

对于这个网络能处理多大强度的噪声,也是需要时间摸索的,昨天的噪声是使用matlab中imnoise增加的,噪声参数是2500/255^2,今天加的噪声是4900/255^2,噪声算挺大了,如果也能处理的不错(目视至少要比BM3D好),那说明这个网络的适用性还是很不错的。

接下来要做的工作有两个,一个是真实图像的去噪验证,可以写一个程序对同一目标采集多次,计算信噪比后保存几幅图(均值图像、信噪比分布、原始图像),然后采集下一个目标,大约采集100多个目标开始训练。可以采集不同曝光时间的图像,摸索适用范围,及效果评估;另一个是应用于光谱图像,评估对光谱的影响。

~~~~~~~~~~~~~~~~~~~~~~~~~~继续更新~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

加大了噪声,训练了一个周期,PSNR下不来,看了代码,这是应该的。试验结果也有了些结论:噪声大的时候,效果似乎有些得不偿失,分辨率也会下降比较多。问题3是无法适用了,至少在不改代码的情况下。下面贴一些结果

加载2500/255^2的噪声左边为原始图像,中间可以忽略,右边为降噪图像

这样效果还可以,稍微有些降分辨率。

噪声增大至4900/255^2

分辨率下降的厉害了。然后对真实图像做了个处理,效果不明显,模型不适用。

对于噪声大不适用的问题也很好理解,考虑一个极端的情况,如信号淹没在噪声里,已经找不到信号了,无论什么样的模型,都不可能恢复出来。所以,这种模型转移到实际应用中还需要界定适用边界。那么评价一个模型,是否不能以静止的指标评价呢?例如这个模型,对噪声功率小时效果比较好,噪声功率大时效果差,那么输出图像的质量是和噪声有一个函数关系,可以作为一个动态指标进行评价,也许在同一噪声水平下比别的模型效果好,但是换到另一个噪声水平下,效果就不如别的模型好,这时候就需要动态的看待模型的效果,综合评价模型。

 

  • 13
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值