图像去模糊算法 循序渐进 附完整代码
2019-11-29

关于图像模糊算法的实现,

我相信大多数学习图像算法的朋友都很熟悉。

例如常见的毛玻璃效果,高斯模糊等等。

而图像模糊最简单的实现就是 在一定区域 对像素做平均值计算。

术语描述,卷积。

1.认识卷积

而平均值计算可以,看做是一种常见的卷积计算,卷积核权重都为1。

OpenCV中与之对应的算法是BoxBlur。

图像方面深度学习中最重要的两个层,一个池化层,一个卷积层,

其中池化层可以认为是一种特例的卷积层,与求平均值类似。

从网上找了一张卷积操作的示例图片。

这样看,虽然知道是在做一个点面计算的操作,但是要具体描述卷积的用途或者原理,是有点困难的。

在两年前一次公司的内部技术分享会上,我是这么定义卷积的。

卷积计算从形象上来描述,在图像领域,一般是2维,

所以可以这么说 “计算两个物体在n维空间的相似度(叠加度)的操作,就称之为(n维)卷积。”

所以图像是计算两个物体在2维空间的相似度(叠加度)的操作,就称之为卷积。

如果两个物体完全一致,卷积完全重合,重合度为1,这时可以认为它就是同一个物体。

以上描述的两个物体,在算法中一般 指的是 卷积核 和被卷积图片,卷积结果就是其两者的重合度。

看下深度学习中的池化层和均值层。

根据上面的描述,重新理解一下,这两个层的作用。

这里就不展开细讲了,大概大家能理解一下卷积这个操作即可。

而一般情况下,卷积操作,是一种信息外散或内聚的计算,

当然也有卷积,反卷积,转置卷积的说法。

举个例子,例如均值池化或者说均值卷积,均值模糊。

从计算来看,是取目标像素临近区域像素的平均值,而所有临近像素的权重都为1.

最终目标像素的值为n分之1. 

那么这个计算就好像是把一个物品在2维空间直接摊平,还不能理解的再看下上面对卷积的描述。

就像你有9只蚂蚁,你希望他们长得一样大,你一巴掌下去,身体全部压平。

而在图像领域,绝大多数的模糊,就是受到一个“物体”或者说“卷积核”的干扰,

致使采集到的信息丢失,或者说不准确。

例如在按下快门的一瞬间,你手抖了,或者说失去焦点,

就会很容易造成呈像模糊。

2.图像修复

假设我们能找到导致成像模糊的原因,是不是就能实现修复模糊图像呢?

答案是肯定的。

不过取决于最终采集到的信息的完整度。

如果最后成像一片漆黑,那这个时候是无能为力的。

因为已经没有足够的信息了。

而一般图像是由色光三原色组成,红绿蓝。

理论上只要其中一种颜色信息完整,就可以用于辅助修复其他色光。

只要能计算到当时的色光分布情况即可实现。

这里我们就需要稍微提及一下摄像领域3大算法,自动白平衡,自动对焦,自动曝光。

简单讲下 这三个算法的区别。

白平衡是为了解决色光分布不均,信息缺失或失真问题的。

自动对焦是为了成像清晰,人为干扰辅助最终成像。

自动曝光当然是为了解决采光问题,弥补感光元件的不足。

大概的先后顺序,理论上应该是 对焦->曝光->白平衡

一般而言,从这逻辑来看,白平衡是最难解决的,因为它受到前面两个因素的干扰。

但是实际上,白平衡和曝光目前都解决得很好。

HDR严格意义上来说,能兼顾白平衡和曝光。

但是对焦或者说失焦,抖动的问题,一直以来都是老大难。

原因也很简单,导致成像模糊的因素有很多,通过什么样的方法来有效评估修复,就显得比较困难。

 假设能知道计算到当时受到什么“物体”的干扰,通过卷积的方式,移除这干扰,是不是就能修复模糊,恢复图片呈像。

假设造成模糊的因素为:   清晰的图片 + 干扰因素 = 最终成像

那么反之恢复图像即为:   最终成像 - 干扰因素 = 清晰图片

而这里把干扰因素和清晰的图片都认为是一种卷积“物体”。

3.去模糊

有了前面的基础知识,我们可以做一个假设,进行验证。

例如,我先对一张图片做卷积操作,模拟模糊成像。

这个时候: 你同时有了  清晰的图片 + 干扰因素 = 最终成像

验证一下:  最终成像 - 干扰因素 = 清晰图片

这里不展开算法实现,

但是结果我可以告诉大家,这思路没错,但是有一个干扰因素错了。

它就是卷积核的大小。

卷积核大小直接决定它的作用范围。

而我们第一步拿到的 清晰的图片 + 干扰因素 = 最终成像

这里 最终成像-干扰因素 却绝对不等于清晰的图片。

因为 这里的干扰因素和最终成像 两者之间并不是简单的线性关系,相加或者相减,

他们的关系是卷积关系,也就是说他们都受到卷积核的影响。

如果想要达到 最终成像 - 干扰因素 = 清晰图片

必须 在最终成像的时候用类似卷积的方式,消除卷积核的内容以及范围的影响。

换句话说,这个操作必须控制好变量。

这个问题说真的,我思考了很久很久。

最后终于知道问题在哪里,就是图像的明度,也就是最终成像。

也就是最终成像中是含有卷积核权重信息的,如果要消除这个信息,

必须将成像也作为权重参与计算。

 也就是说,造成模糊的情况应该是:

if( sqrt(nx-x) + sqrt(ny-y) < sqrt(radius) ) { w = luminance(rgb) sum += w*s; wsum += w; } sum /= wsum;

 伪代码,简洁形象地表达这个现象。

知道这个前因后果,现在恢复模糊,该如何计算。

这个留个作业给大家。

上面伪代码我称之为  散焦 算法,反之为 聚焦 也就是去模糊 。

聚焦算法最终可以实现耗时模糊半径无关,它是去模糊的一种特例。

目前,此算法暂无开源计划。

好几年前就有去模糊的商业软件,当然早期版本作者也开源了。

项目地址:https://github.com/Y-Vladimir/SmartDeblur

但是这个项目并没有很好准确计算到去模糊卷积核。

前几天ipol.im公布了一个比较优秀的评估去模糊卷积核的算法。

Estimating an Image"s Blur Kernel Using Natural Image Statistics, and Deblurring it: An Analysis of the Goldstein-Fattal Method

从官网demo演示来看,效果特别不错。

但是,它和SmartDeblur 都有着一样的问题,就是用到傅里叶变换去做卷积操作,

十分耗时。

都采用了fftw,计算量还是居高不下。

我对它提供的代码,做了一些简单的裁剪,cmake编译通过,仅依赖fftw。

而代码的算法调优等等,还没做,算法优化空间比较大,最近精力有限,

在音频算法上花的时间比较多,图像暂时没有精力做起来。

感兴趣的朋友,可以移步项目:

https://github.com/cpuimage/Deblurring

而近些年,深度学习大兴,各种各样的模型以及训练集,五花八门。

当然也有去模糊的实现。

效果非常惊艳!

网络结构如下:

对于采用深度学习的方法进行去模糊实现,可以参阅文章:

https://blog.sicara.com/keras-generative-adversarial-networks-image-deblurring-45e3ab6977b5

项目地址:

https://github.com/RaphaelMeudec/deblur-gan

相关论文:

DeblurGAN: Blind Motion Deblurring Using Conditional Adversarial Networks

https://arxiv.org/pdf/1711.07064.pdf

 

最后做一个简单的总结,在图像领域,使用卷积就能非常好解决 图像的空间问题,

而深度学习训练得到的权重,可以简单的类比上面提到的干扰因素。

通过大量的数据,训练提取 可能性的干扰因素(物体),若是当前图像也有符合这个特征的因素(物体),

则进行相应的操作计算。

定位特征,确认特征,发现并处理特征。

分别 对应物体检测,物体识别,风格化或其他增强修复处理。

采用深度学习最大的好处就是能预先训练得到已知的信息,然后进行对应的处理。

而传统算法,则需要采用先验条件,

然后在一张图片中去发现可能性因素,由于参数较少,鲁棒性一般不佳。

相比而言,传统算法困难重重,因为你要通过科学方式找到一种适配数据自然规律的先验,真的太不容易。

而深度学习是另一个问题,数据依赖,数据干扰,数据处理,这些预处理也着实够人头大的了,

然后还要设计一个比较有效且优良的神经网络。

就目前来看,经典传统算法稳定性比较高,但是泛化能力一般较差。

深度学习目前还需要不少传统算法配合进行训练处理,以求达到更好的效果。

就目前来看,工业化落地也有不少问题,不过相信很快就能做得很好了。

因为有大公司和大量资金资本的助推,应该不是难事。

 

若有其他相关问题或者需求也可以邮件联系俺探讨。

邮箱地址是: gaozhihan@vip.qq.com