我正在尝试对Python中的图像进行模糊处理,但是遇到了一些问题。这是我尝试过的方法,但请记住,我不是该主题的专家。根据我的理解,如果您知道点扩散函数,则应该能够通过执行反卷积相当简单地对图像进行模糊处理。但是,这似乎不起作用,而且我不知道我是在做愚蠢的事情还是只是对事情的理解不正确。在马克·纽曼(Mark Newman)的《计算物理》一书(使用Python)中,他谈到了问题7.9。在这个问题中,他提供了使用高斯点扩展函数(psf)故意模糊的图像,并且该问题的目的是使用高斯对图像进行模糊处理。这是通过将模糊图像的2D FFT除以psf的2D FFT,然后进行逆变换来实现的。效果很好。
为解决这个问题,我想对故意没有对焦的相机拍摄的真实图像进行模糊处理。因此,我安装了相机并拍摄了两组照片。第一组照片聚焦。第一个是在完全昏暗的房间里的很小的LED灯,第二个是上面有文字的纸(使用闪光灯)。然后,在不更改任何距离或任何内容的情况下,我更改了相机的焦点设置,以使文本非常不清晰。然后,我使用闪光灯拍摄了文字图片,并为LED拍摄了第二张图片(没有闪光灯)。这是模糊的图像。
现在,根据我的理解,模糊点光源的图像应该是点扩散函数,因此,我应该能够使用它对图像进行模糊处理。问题是,当我这样做时,我得到的图像看起来像是噪点。经过一些研究,使用去卷积技术似乎似乎是一个大问题。但是,考虑到我已经测量了我认为确切的点扩散函数,我感到惊讶的是噪声在这里是个问题。
我尝试做的一件事是用1或epsilon替换psf变换中的小值(小于epsilon),然后我尝试了大范围的epsilon值。这样产生的图像不仅是噪点,而且不是图像的去模糊版本。它看起来像是原始(非模糊)图像的怪异,模糊的版本。这是我程序中的图像(您可以忽略sigma的值,该值未在该程序中使用)。
我相信我正在处理噪音问题,但是我不知道为什么,也不知道该怎么办。任何建议将不胜感激(请记住,我不是该领域的专家)。
请注意,我故意不发布代码,因为我认为这在当时并不重要。但是,如果有人认为这样做会有用,我将很乐意这样做。我不认为这是一个编程问题,因为我使用了相同的技术,并且当我拥有已知的点扩展函数时(例如,当我将原始对焦图像的FFT除以外焦-聚焦图像,然后进行逆变换)。我只是不明白为什么我似乎无法使用实验测量的点扩散函数。
答案 0 :(得分:6)
不幸的是,您要解决的问题比您预期的要困难得多。让我分四个部分进行说明。第一部分假定您对傅立叶变换感到满意。
但首先要注意一些符号:
我用 I 表示图像,用 K 表示卷积核。 I * K 是图像 I 与内核 K 的卷积。 F (I)是图像 I 和 F 的(n维)傅立叶变换(K)是卷积核 K 的傅立叶变换(也称为点扩展函数或PSF)。同样, Fi 是傅立叶逆变换。
当您说我们可以通过将 Ib 的傅立叶变换除以的傅立叶变换来恢复模糊图像 Ib = I * K 时,您是正确的K 。但是,镜头模糊不是卷积模糊操作。这是一种改进的卷积模糊操作,其中模糊内核 K 取决于与您拍摄的物体的距离。因此,内核在像素之间变化。
您可能会认为这与图像无关,因为您已在图像位置测量了正确的内核。但是,情况可能并非如此,因为图像的较远部分会影响图像的较近部分。解决此问题的一种方法是裁剪图像,以便只有可见的纸张。
卷积定理指出 I * K = Fi ( F (I) F (K))。该定理导致一个合理的假设,即如果我们有一个图像 Ib = I * K 被卷积核 K 模糊,那么我们可以通过以下方法恢复去模糊的图像:计算 I =( F (Ib)/ F (K))。
在研究为什么这是一个坏主意之前,我想对卷积定理的含义有一些直觉。当我们用核对卷积图像进行卷积时,这与获取图像的频率成分并将其与内核的频率成分相乘是一样的。
现在,让我解释一下为什么很难用FFT对图像进行反卷积。默认情况下,模糊会删除高频信息。因此, K 的高频必须接近零。原因是 I 的高频信息在模糊时会丢失-因此, Ib 的高频分量必须接近零。为此, K 的高频分量也必须趋近于零。
由于 K 的高频分量几乎为零,我们看到 Ib 的高频分量得到了显着放大(因为我们几乎将当我们对FFT去卷积时在无噪声的情况下这不是问题。
但是,在嘈杂的情况下,这是一个问题。其原因是,按照定义,噪声就是高频信息。因此,当我们尝试对 Ib 进行反卷积时,噪声几乎被无限放大。这就是使用FFT进行反卷积的想法不好的原因。
此外,您需要考虑基于FFT的卷积算法如何处理边界条件。通常,当我们对图像进行卷积时,分辨率会有所降低。这是不必要的行为,因此我们引入了边界条件,这些条件指定了图像外部像素的像素值。这样的边界条件的例子是
最终边界条件通常对一维信号有意义。但是,对于图像来说,这毫无意义。不幸的是,卷积定理规定使用周期性边界条件。
除此之外,似乎基于FFT的反演方法比迭代方法(例如梯度下降和FISTA)对错误的内核更加敏感。
由于所有图像都嘈杂,似乎现在所有的希望都已荡然无存,去卷积会增加噪点。但是,事实并非如此,因为我们有迭代方法来执行去卷积。首先让我向您展示最简单的迭代方法。
让 || I ||²是所有 I 像素的平方和。求解方程
Ib = I * K
关于 I 的等效于解决以下优化问题:
min L(I)= min || I * K-Ib ||²
关于 I 的。这可以使用梯度下降来完成,因为 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)
上面的方法也许是最简单的迭代反卷积算法。在实践中使用这些方法的方式是通过所谓的正则反卷积算法。这些算法通过首先指定测量图像中噪声量的函数来工作,例如 TV(I)( I 的总变化)。然后在 L(I)+ wTV(I)上执行优化过程。如果您对此类算法感兴趣,建议阅读Amir Beck和Marc Teboulle撰写的FISTA论文。该论文的数学运算量很大,但是您不需要了解其中的大部分内容,只需了解如何实现电视去模糊算法即可。
除了使用调节器外,我们还使用加速方法来将损耗 L(I)降至最低。内斯特罗夫加速梯度下降就是这样一个例子。有关此类方法的信息,请参阅Emmanuel Candes的Brendan O'Donoghue的《自适应加速梯度方案的重新启动》。