【问题标题】:fftw + opencv inconsistent outputfftw + opencv 输出不一致
【发布时间】:2017-08-04 13:18:46
【问题描述】:

我最近尝试为 Opencv 的 Mat 实现 FFT 函数。 我主要从 FFTW 的代码示例和以下方面启发了我的实现: FFTW-OpenCV

我非常注意调整输入图像的大小以加快处理速度。 似乎我做错了什么,因为输出始终是黑色图像。

这是我的实现:

void fft2_32f(const cv::Mat1f& _src, cv::Mat2f& dst)
    {

        cv::Mat2f src;

        const int rows = cv::getOptimalDFTSize(_src.rows);
        const int cols = cv::getOptimalDFTSize(_src.cols);

    //    const int total = cv::alignSize(rows*cols,steps);


        if(_src.isContinuous() && _src.rows == rows && _src.cols == cols)
        {

            src = cv::Mat2f::zeros(src.size());
            dst = cv::Mat2f::zeros(src.size());

            // 1) copy the source into a complex matrix (the imaginary component  is set to 0).

            cblas_scopy(src.total(), _src.ptr<float>(), 1, src.ptr<float>(), 2);

            // 2) prepare and apply the transform.

            fftwf_complex* ptr_in = reinterpret_cast<fftwf_complex*>(src.ptr<float>());
            fftwf_complex* ptr_out = reinterpret_cast<fftwf_complex*>(dst.ptr<float>());

    //        fftwf_plan fft = fftwf_plan_dft_1d(src.total(), ptr_in, ptr_out, FFTW_FORWARD, FFTW_ESTIMATE);
            fftwf_plan fft = fftwf_plan_dft_2d(src.rows, src.cols, ptr_in, ptr_out, FFTW_FORWARD, FFTW_ESTIMATE);

            fftwf_execute(fft);
            fftwf_destroy_plan(fft);

            // 3) normalize

            cblas_saxpy(dst.rows * dst.step1(), 1.f/dst.total(), dst.ptr<float>(), 1, dst.ptr<float>(), 1);

        }
        else
        {

            src = cv::Mat2f::zeros(rows, cols);
            dst = cv::Mat2f::zeros(rows, cols);

            // 1) copy the source into a complex matrix (the imaginary component  is set to 0).

            support::parallel_for(cv::Range(0, _src.rows), [&src, &_src](const cv::Range& range)->void
            {

                for(int r=range.start; r<range.end; r++)
                {
                    int c=0;

                    const float* it_src = _src[r];
                    float* it_dst = src.ptr<float>(r);

    #if CV_ENABLE_UNROLLED
                    for(;c<=_src.cols-4; c+=4, it_src+=4, it_dst+=8)
                    {
                        *it_dst = *it_src;
                        *(it_dst+2) = *(it_src+1);
                        *(it_dst+4) = *(it_src+2);
                        *(it_dst+6) = *(it_src+3);
                    }
    #endif
                    for(; c<_src.cols; c++, it_src++, it_dst+=2)
                        *it_dst = *it_src;
                }   
            }, 0x80);

            // 2) prepare and apply the transform.

            fftwf_complex* ptr_in = reinterpret_cast<fftwf_complex*>(src.ptr<float>());
            fftwf_complex* ptr_out = reinterpret_cast<fftwf_complex*>(dst.ptr<float>());

            fftwf_plan fft = fftwf_plan_dft_2d(src.rows, src.cols, ptr_in, ptr_out, FFTW_FORWARD, FFTW_ESTIMATE);

            fftwf_execute(fft);
            fftwf_destroy_plan(fft);

            double min(0.);
            double max(0.);

            // 3) normalize

            cblas_saxpy(dst.rows * dst.step1(), 1.f/dst.total(), dst.ptr<float>(), 1, dst.ptr<float>(), 1);

        }    
    }

注意:

parallel_for 实现的灵感来自:How to use lambda as a parameter to parallel_for_

提前感谢您的帮助。

【问题讨论】:

  • 连续版好用吗?如果您删除规范化,或者在fftw_execute 之后,它是否有效?有很多方法可以调试这个......
  • 实际上 fft 在这两种情况下都适用于连续数据。在第一种情况下,如果图像尺寸符合最佳 DFT 尺寸,则将数据复制到复矩阵中会更快。但它们都不起作用。

标签: c++ opencv fft fftw dft


【解决方案1】:

我发现了我的问题。 这个按原样编写的函数确实可以完美运行(至少对于我制作它的目的而言)。 我的问题是:

cv::Mat dst = cv::Mat::zeros(src.size(), CV_32FC2);

cv::Mat1f srcw = src;
cv::Mat1f dstw = dst;

fft2_32f(srcw, dstw); // realocate dstw to the optimal size for receive the output depending on the size of srcw. ... so the dstw is reallocate but not dst.

dst.copyTo(_outputVariable);

在这种情况下,由于函数内部的重新分配,正确的信息存储在 dstw 中而不是 dst 中。 因此,当我尝试可视化我的数据时,我得到了一张黑色的图像。

正确的调用是:

cv::Mat dst;

cv::Mat1f srcw = src;
cv::Mat1f dstw;

fft2_32f(srcw, dstw); // realocate dstw to the optimal size for receive the output depending on the size of srcw. ... so the dstw is reallocate but not dst.

dst = dstw;

dst.copyTo(_outputVariable); // or dstw.copyTo(_outputVariable);

使用该代码,我得到了正确的输出。

请注意,根据应用程序,与输入大小相对应的 roi(查看 OpenCV 的 Mat 容器的 operator()(const cv::Rect&))可能有助于保留尺寸。

感谢您的帮助:)。

有人可以帮我将此主题标记为关闭吗?请。

【讨论】:

    猜你喜欢
    • 2018-11-16
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-07
    • 2018-04-30
    • 2013-04-15
    • 1970-01-01
    相关资源
    最近更新 更多