【问题标题】:C++ - Eigen FFT use for Deconvolution of 2 dimensional imageC++ - 本征 FFT 用于二维图像的反卷积
【发布时间】:2018-02-08 15:44:51
【问题描述】:

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

我看到另一篇关于如何使用 Eigen FFT 执行前向变换的帖子,here

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

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];

那么我的输出是:

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

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

【问题讨论】:

  • 我可能知道为什么 FFT 改变了图像。我在这个网站上读到:homepages.inf.ed.ac.uk/rbf/HIPR2/fourier.htm 通常傅立叶将 DC 值(索引 0,0 处的值)移动到中心。所以我们必须重新调整原始图像的值。如果我在这里不正确,请纠正我。
  • 是的,这就是如果卷积核以 (n/2,n/2) 为中心,图像会发生偏移的原因。实际上,在这种情况下,卷积还通过向量 (n/2,n/2) 执行平移。高频噪声可能是由于最高频率,称为奈奎斯特频率。如果图像的大小是偶数(比如 4),则频率 n/2 可能是问题的根源。索引 0 是平均值,索引 1 是频率 1/4,索引 3 是频率 -1/4,但索引 2 可以对应于频率 2/4 或 -2/4。因此,在反向 dft 之前将这些高频分量归零可能有助于...
  • 我不太明白为什么我们需要将高频归零。因为如果我从图像中获得高频,将它们归零将意味着该图像的数据丢失,对吧?
  • 反卷积一般是ill posed inverse problem。即使是数字舍入添加的噪声也会导致伪影。你需要做一些正则化。
  • 为什么图像的左上部分镜像到右上而右下部分镜像到左下?我可以如何防止这种情况发生吗?

标签: fft eigen convolution eigen3 deconvolution


【解决方案1】:

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

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

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

这样想:逆 DFT 反转了 DFT 的过程。如果 DFT 为real-&gt;complex-&gt;complex,则逆必须为complex-&gt;complex-&gt;real。中间图像具有空间和频率维度。频率分量总是需要很复杂。


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


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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-09
    • 2010-11-09
    • 2013-10-16
    • 2020-02-21
    • 2015-04-11
    • 1970-01-01
    • 2014-09-05
    • 2016-08-18
    相关资源
    最近更新 更多