首页 > 解决方案 > 去模糊图像

问题描述

我正在尝试在 Python 中对图像进行去模糊处理,但遇到了一些问题。这是我尝试过的方法,但请记住,我不是该主题的专家。根据我的理解,如果你知道点扩散函数,你应该能够很简单地通过执行反卷积来对图像进行去模糊。但是,这似乎不起作用,我不知道我是否在做一些愚蠢的事情,或者我只是没有正确理解事情。在 Mark Newman 的 Computational Physics 书(使用 Python)中,他在问题 7.9 中触及了这个主题。在这个问题中,他提供了一张他故意使用高斯点扩散函数 (psf) 模糊的图像,并且该问题的目标是使用高斯对图像进行去模糊。这是通过将模糊图像的 2D FFT 除以 psf 的 2D FFT 然后进行逆变换来实现的。这工作得相当好。

为了扩展这个问题,我想对使用故意失焦的相机拍摄的真实图像进行去模糊处理。于是我架起了相机,拍了两组照片。第一组照片是焦点。第一个是在一个完全黑暗的房间里的一个非常小的 LED 灯,第二个是一张上面有文字的纸(使用闪光灯)。然后,在不改变任何距离或任何东西的情况下,我改变了相机上的焦点设置,使文本非常失焦。然后我用闪光灯拍了一张文字的照片,然后拍了第二张 LED 的照片(没有闪光灯)。这是模糊的图像。

模糊的文本

模糊点光源

现在,根据我的理解,模糊点光源的图像应该是点扩散函数,因此我应该可以使用它对我的图像进行去模糊处理。问题是,当我这样做时,我得到的图像看起来就像噪点。在做了一些研究之后,似乎噪声在使用反卷积技术时可能是一个大问题。然而,鉴于我已经测量了我认为是精确的点扩散函数,我很惊讶噪声在这里会成为一个问题。

我尝试过的一件事是用 1 或 epsilon 替换 psf 变换中的小值(小于 epsilon),并且我尝试使用大范围的 epsilon 值。这产生的图像不仅是噪声,而且不是图像的去模糊版本;它看起来像是原始(非模糊)图像的奇怪、模糊版本。这是我程序中的一张图片(你可以忽略 sigma 的值,这个程序中没有用到)。

在此处输入图像描述

我相信我正在处理噪音问题,但我不知道为什么,也不知道该怎么做。任何建议将不胜感激(请记住,我不是这方面的专家)。

请注意,我故意不发布代码,因为我认为此时这有点无关紧要。但如果有人认为这很有用,我会很乐意这样做。我不认为这是一个编程问题,因为我使用了相同的技术,并且当我有已知的点扩散函数时它工作正常(例如当我将原始对焦图像的 FFT 除以失焦图像的 FFT 时) -聚焦图像,然后进行逆变换)。我只是不明白为什么我似乎无法使用实验测量的点扩散函数。

标签: pythonimage-processingdeconvolution

解决方案


不幸的是,您试图解决的问题比您预期的要困难得多。让我分四个部分来解释。第一部分假设您对傅里叶变换很熟悉。

  1. 为什么你不能用简单的反卷积来解决这个问题。
  2. 如何执行图像去模糊的概述。
  3. FFT 反卷积以及为什么这是一个坏主意
  4. 执行反卷积的另一种方法

但首先,一些符号:

我用I表示图像,用K表示卷积核。I * K是图像I与核K的卷积。F (I)是图像I的(n 维)傅里叶变换,F ( K)是卷积核K的傅里叶变换(这也称为点扩散函数,或 PSF)。类似地,Fi是傅里叶逆变换。

为什么你不能用简单的反卷积来解决这个问题:

当您说我们可以通过将Ib的傅立叶变换除以 K 的傅立叶变换来恢复模糊图像Ib = I * K时,您是对的。然而,镜头模糊不是卷积模糊操作。这是一种改进的卷积模糊操作,其中模糊核K取决于到您拍摄的对象的距离。因此,内核从一个像素变为另一个像素。

您可能认为这不是您的图像的问题,因为您已经在图像的位置测量了正确的内核。但是,情况可能并非如此,因为远处的图像部分会影响靠近的图像部分。解决此问题的一种方法是裁剪图像,使其仅是可见的纸张。

为什么 FFT 去卷积是个坏主意:

卷积定理指出I * K = Fi ( F ( I) F (K))。这个定理导致了一个合理的假设,如果我们有一个图像Ib = I * K被卷积核K模糊,那么我们可以通过计算I = ( F (Ib)/ F (K))来恢复去模糊的图像.

在我们了解为什么这是一个坏主意之前,我想先了解一下卷积定理的含义。当我们将图像与内核进行卷积时,这与获取图像的频率分量并将其与内核的频率分量相乘是相同的。

现在,让我解释一下为什么很难用 FFT 对图像进行反卷积。默认情况下,模糊会删除高频信息。因此, K的高频必须趋近于零。原因是I的高频信息在模糊时丢失了——因此, Ib的高频分量必须趋近于零。为此, K的高频分量也必须趋近于零。

由于K的高频分量几乎为零,我们看到当我们用 FFT 去卷积时, Ib的高频分量被显着放大(因为我们几乎除以零)。在无噪声情况下,这不是问题。

然而,在嘈杂的情况下,这是一个问题。其原因是,根据定义,噪声是高频信息。因此,当我们尝试对Ib进行反卷积时,噪声被放大到几乎无限的程度。这就是 FFT 去卷积是一个坏主意的原因。

此外,您需要考虑基于 FFT 的卷积算法如何处理边界条件。通常,当我们对图像进行卷积时,分辨率会有所降低。这是不需要的行为,因此我们引入了边界条件来指定图像外部像素的像素值。这种边界条件的例子是

  1. 图像外的像素与图像内最近的像素具有相同的值
  2. 图像外的像素具有恒定值(例如 0)
  3. 图像是周期性信号的一部分,因此最上面一行的像素行等于最下面一行的像素。

最终的边界条件通常对一维信号有意义。然而,对于图像来说,它没有多大意义。不幸的是,卷积定理指定使用周期性边界条件。

除此之外,似乎基于 FFT 的反演方法比迭代方法(例如梯度下降和 FISTA)对错误内核更敏感。

执行反卷积的另一种方法

现在似乎所有希望都失去了,因为所有图像都很嘈杂,而去卷积会增加噪音。然而,情况并非如此,因为我们有迭代方法来执行反卷积。让我首先向您展示最简单的迭代方法。

|| I ||²是所有I像素的平方和。求解方程

Ib = I * K

相对于I等价于解决以下优化问题:

最小 L(I) = 最小 ||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)

上述方法可能是最简单的迭代反卷积算法。这些在实践中的使用方式是通过所谓的正则化反卷积算法。这些算法通过首先指定一个函数来测量图像中的噪声量,例如TV(I) ( I的总变化量)。然后在L(I) + wTV(I)上执行优化过程。如果您对此类算法感兴趣,我建议您阅读 Amir Beck 和 Marc Teboulle 的 FISTA 论文。这篇论文的数学很重,但你不需要理解大部分内容——只需要了解如何实现 TV 去模糊算法。

除了使用正则化器之外,我们还使用加速方法来最小化损失L(I)。一个这样的例子是 Nesterov 加速梯度下降。有关此类方法的信息,请参阅 Brendan O'Donoghue、Emmanuel Candes 的加速梯度方案的自适应重启。

如何执行图像去模糊的概述。

  1. 裁剪图像,使所有物体与相机的距离相同
  2. 以与您现在相同的方式找到卷积核(首先在合成模糊图像上测试您的反卷积算法)
  3. 实现一种迭代方法来计算去卷积
  4. 去卷积图像。

推荐阅读