1

我正在尝试对图像I执行反卷积,即nxm。用于对其进行卷积的内核是K,也是nxm。现在我想通过执行反卷积找到原始图像O 。我知道我可以通过对IK执行傅立叶变换并划分:I / K来检索图像O,因为在傅立叶域中,卷积是一个乘积。(我从这里得到了这个信息)。

我在这里看到了关于如何使用 Eigen FFT 执行正向变换的另一篇文章

我的正向傅里叶变换代码是:

I = 输入图像(时域)

O = 输出图像(频域)

tempFreq = 计算的临时矩阵(频域)

timevec1 = 浮点向量

freqvec1, freqvec2, freqvec3 = 复向量

for (Int32 i = 0; i < I->uRowsCount; ++i)
{
    for (Int32 j = 0; j < I->uColumnsCount; ++j)
    {
        timevec1.push_back((*I)(i, j));
    }

    fft.fwd(freqvec1, timevec1);

    for (Int32 j = 0; j < I->uColumnsCount; ++j)
    {
        (tempFreq)(i, j) = freqvec1[j];
    }

    freqvec1.clear();
    timevec1.clear();
}

freqvec1.clear();
timevec1.clear();


for (Int32 j = 0; j < I->uColumnsCount; ++j)
{
    for (Int32 i = 0; i < I->uRowsCount; ++i)
    {
        freqvec2.push_back((tempFreq)(i, j));
    }

    fft.fwd(freqvec1, freqvec2);

    for (Int32 i = 0; i < I->uRowsCount; ++i)
    {
        (O)(i, j) = freqvec1[i];
    }

    freqvec2.clear();
    freqvec1.clear();
}

我的傅里叶逆变换代码是:

I = 输入图像(频域)

O = 输出图像(时域)

tempTime = 计算的临时矩阵(时域)

timevec1, timevec2 = 浮点向量

freqvec1, freqvec2 = 复向量

    for (Int32 j = 0; j < O->uColumnsCount; ++j)
    {
        for (Int32 i = 0; i < O->uRowsCount; ++i)
        {
            freqvec1.push_back((I)(i, j));
        }

        fft.inv(timevec1, freqvec1);

        for (Int32 i = 0; i < O->uRowsCount; ++i)
        {
            (*tempTime)(i, j) = timevecCol[i];
        }

        freqvec1.clear();
        timevec1.clear();
    }

    freqvec1.clear();
    timevec1.clear();

    for (Int32 i = 0; i < O->uRowsCount; ++i)
    {
        for (Int32 j = 0; j < O->uColumnsCount; ++j)
        {
            freqvec2.push_back((*tempTime)(i, j));
        }

        fft.inv(timevec2, freqvec2);

        for (Int32 j = 0; j < O->uColumnsCount; ++j)
        {
            (*O)(i, j) = timevec2[j];
        }

        freqvec2.clear();
        timevec2.clear();
    }

对于反卷积,我将频域中的输入图像与频域中的内核相除:

freqDomainOutputImage = freqDomainInputImage.cwiseQuotient(freqDomainKernel);

为了得到原始图像,我对 freqDomainOutputImage 执行傅里叶逆变换。

我得到的结果是: 在此处输入图像描述

我相信 FFT 将左上角镜像到另一边,但我不知道为什么?我没有使用 halfSpectrum。第二,为什么图像偏移?如果我通过用这个替换最后一个循环将输出图像移动到中心:

(*O)((i + O->uRowsCount/2)%O->uRowsCount, (j + O->uColumnsCount/2)%O->uColumnsCount) = timevec2[j];

然后我的输出是: 在此处输入图像描述

(您可以看到图像是从左上象限镜像的)。

最后,为什么即使我自己添加了没有噪音的模糊,它似乎也有噪音?

4

1 回答 1

2

tempTime需要很复杂。您似乎正在丢弃那个虚构的组件,因此您获得了镜像效果。

从具有复共轭对称性的复频域图像开始,您应用一维 DFT(例如沿行)。此变换的结果是仅沿列具有复共轭对称性的复图像。下一个 1D DFT 采用这些列并从中创建实值信号,从而产生实值图像。

如果在第一步之后您丢弃了虚部,那么您沿着该维度移除空间域图像的奇数分量,留下偶数(对称)图像。这就是为什么您会在结果中看到这种对称性。

可以这样想:逆 DFT 反转了 DFT 的过程。如果 DFT 成立real->complex->complex,则反之亦然complex->complex->real。中间图像具有空间和频率维度。频率分量总是需要很复杂。


您已经发现需要交换象限。这是因为 DFT 在空间域和频域都使用最左边的像素作为原点。因此,您的空间域卷积核的原点必须位于左上角,这样所有这些才能正常工作。


最后,你想知道噪音。这是由数值不稳定引起的。图像的某些频率分量只是具有非常小的值。对于低通滤波图像尤其如此。在那里,您将非常小的值除以其他非常小的值,从而产生废话。

反卷积在实践中总是需要正则化。维纳滤波器是向反卷积添加正则化的最简单方法。有关详细信息,请参阅此其他答案

于 2018-02-17T16:49:06.250 回答