DJE*_*ric 8 python image-processing deconvolution
我试图在Python中对图像进行去模糊,但遇到了一些问题.这是我尝试过的,但请记住,我不是这个主题的专家.根据我的理解,如果你知道点扩散函数,你应该能够通过执行反卷积来简单地对图像进行去模糊.然而,这似乎不起作用,我不知道我是在做一些愚蠢的事情,还是我不理解事情.在Mark Newman的计算物理学书籍(使用Python)中,他在问题7.9中触及了这个主题.在这个问题中,他提供了一个他使用高斯点扩散函数(psf)故意模糊的图像,问题的目的是使用高斯对图像进行去模糊.这是通过将模糊图像的2D FFT除以psf的2D FFT然后进行逆变换来实现的.这工作得相当好.
为了解决这个问题,我想对使用故意失焦的相机拍摄的真实图像进行去模糊.所以我设置了一个相机并拍了两组照片.第一组照片是焦点.第一个是在一个完全黑暗的房间里的一个非常小的LED灯,第二个是一张纸上有文字(使用闪光灯).然后,在不改变任何距离或任何东西的情况下,我改变了相机上的焦点设置,使文本非常失焦.然后,我使用闪光灯拍摄了文本照片,然后拍摄了第二张LED照片(没有闪光灯).这是模糊的图像.
现在,根据我的理解,模糊点光源的图像应该是点扩散函数,因此我应该能够用它来去模糊我的图像.问题在于,当我这样做时,我得到一个看起来像噪音的图像.经过一些研究后,使用反卷积技术时噪声似乎是个大问题.然而,鉴于我已经测量了我认为确切的点扩散函数,我很惊讶噪声在这里是一个问题.
我尝试过的一件事就是用1或者epsilon替换psf变换中的小值(小于epsilon),我尝试使用epsilon的大范围值.这产生的图像不仅仅是噪点,而且也不是图像的模糊版本; 它看起来像原始(非模糊)图像的奇怪,模糊版本.这是我的程序中的图像(您可以忽略sigma的值,该程序中未使用该值).
我相信我正在处理一个噪音问题,但我不知道为什么,我不知道该怎么办.任何建议都会非常感激(请记住,我不是这方面的专家).
请注意,我故意不发布代码,因为我认为这在某种程度上是无关紧要的.但如果有人认为有用,我会很高兴这样做.我不认为这是一个编程问题,因为我使用了相同的技术,并且当我具有已知的点扩散函数时(例如当我通过FFT的out-of划分原始对焦图像的FFT时)它工作正常 - 聚焦图像然后逆变换).我只是不明白为什么我似乎无法使用我的实验测量点扩散函数.
不幸的是,你想要解决的问题比你想象的要困难得多.让我分四个部分来解释.第一部分假设您对傅立叶变换感到满意.
但首先,一些符号:
我使用I来表示图像,使用K来表示卷积内核.I*K是图像I与内核K的卷积.˚F(I)是(n维)傅立叶变换图像的我和˚F(K)的傅里叶变换的卷积核ķ(这也被称为点扩散函数或PSF).类似地,Fi是逆傅立叶变换.
当你说我们可以恢复一个模糊的图像你是正确的磅= I*K除以傅里叶变换的磅由傅立叶变换ķ.然而,镜头模糊不是卷积模糊操作.这是一种改进的卷积模糊操作,其中模糊内核K取决于到您拍摄的对象的距离.因此,内核从像素变为像素.
您可能认为这不是图像的问题,因为您已经在图像的位置测量了正确的内核.但是,情况可能并非如此,因为远离图像的部分可能会影响图像中接近的部分.解决此问题的一种方法是裁剪图像,使其仅显示可见的纸张.
该卷积定理指出,I*K = 连接(˚F(I)˚F(K)) .该定理导致合理的假设,即如果我们有一个图像,Ib = I*K被卷积核K模糊,那么我们可以通过计算I =(F(Ib)/ F(K))来恢复去模糊图像.
在我们看看为什么这是一个坏主意之前,我想对Convolution定理的含义有所了解.当我们使用内核对图像进行卷积时,这与获取图像的频率分量并将其与元素的频率分量相乘.
现在,让我解释一下为什么用FFT对图像进行去卷积是很困难的.默认情况下,模糊会删除高频信息.因此,K的高频必须趋向于零.其原因在于I的高频信息在模糊时丢失 - 因此,Ib的高频分量必须趋向于零.为此,K的高频分量也必须趋于零.
由于K的高频分量几乎为零,我们看到当我们对FFT进行去卷积时,Ib的高频分量被显着放大(因为我们几乎除以零).这在无噪音的情况下不是问题.
然而,在嘈杂的情况下,这是一个问题.其原因在于,根据定义,噪声是高频信息.因此,当我们尝试对Ib进行去卷积时,噪声会被放大到几乎无限的程度.这就是FFT反卷积的一个坏主意.
此外,您需要考虑基于FFT的卷积算法如何处理边界条件.通常,当我们对图像进行卷积时,分辨率会有所降低.这是不需要的行为,因此我们引入了指定图像外部像素像素值的边界条件.这种边界条件的例子是
最终边界条件通常对1D信号有意义.然而,对于图像来说,这没什么意义.不幸的是,卷积定理指定使用周期性边界条件.
除此之外,似乎基于FFT的反演方法对于错误的内核比迭代方法(例如梯度下降和FISTA)更加敏感.
现在似乎所有的希望都消失了,因为所有的图像都很嘈杂,而去卷积会增加噪音.然而,事实并非如此,因为我们有迭代方法来执行反卷积.让我首先向您展示最简单的迭代方法.
设|| I ||²是我所有像素的平方和.求解方程
Ib = I*K.
相对于我来说,这相当于解决了以下优化问题:
min L(I)= min || I*K - Ib ||²
关于我.这可以使用梯度下降来完成,因为L的梯度由下式给出
DL = Q*(I*K - Ib)
其中Q是通过转置K获得的内核(在信号处理文献中也称为匹配滤波器).
因此,您可以获得以下将对图像进行去模糊的迭代算法.
from scipy.ndimage import convolve
blurred_image = # Load image
kernel = # Load kernel/psf
learning_rate = # You need to find this yourself, do a logarithmic line search. Small rate will always converge, but slowly. Start with 0.4 and divide by 2 every time it fails.
maxit = 100
def loss(image):
return np.sum(convolve(image, kernel) - blurred_image)
def gradient(image):
return convolve(convolve(image, kernel) - blurred_image)
deblurred = blurred_image.copy()
for _ in range(maxit):
deblurred -= learning_rate*gradient(image)
Run Code Online (Sandbox Code Playgroud)
上述方法可能是最简单的迭代反卷积算法.这些在实践中使用的方式是通过所谓的正则化反卷积算法.这些算法通过首先指定测量图像中的噪声量的函数,例如,工作电视(I) (总变化我).然后在L(I)+ wTV(I)上执行优化过程.如果您对此类算法感兴趣,我建议您阅读Amir Beck和Marc Teboulle撰写的FISTA论文.这篇论文非常重要,但你不需要了解它的大部分内容 - 只有如何实现电视去模糊算法.
除了使用常规器之外,我们还使用加速方法来最小化损失L(I).一个这样的例子是Nesterov加速梯度下降.有关此类方法的信息,请参阅Brendan O'Donoghue,Emmanuel Candes的自适应重启加速梯度方案.