首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DFT/IDFT计算中的负值

DFT/IDFT计算中的负值
EN

Stack Overflow用户
提问于 2018-02-08 10:32:30
回答 1查看 621关注 0票数 0

我正在创建一个具有0.015截止频率的低通滤波器和相应的高通滤波器,如下所示:

代码语言:javascript
复制
auto getGaussianFilter(int32_t size) {
    const auto sigmaf = 0.015f*size; // cutoff freq.

    cv::Mat kernel = cv::Mat::zeros(size, size, CV_32FC1);

    for (auto fy = -size/2; fy < size/2; ++fy)
        for (auto fx = -size/2; fx < size/2; ++fx) 
            kernel.at<float>(fy + size/2, fx + size/2) = std::exp(-(fy*fy+fx*fx)/(2*sigmaf*sigmaf));
    return kernel;
} 

...

lowpassFilter  = getGaussianFilter(256);
highpassFilter = 1 - lowpassFilter; 

,这些应用于像下面的片段这样的图像。

代码语言:javascript
复制
std::vector<cv::Mat> planes { src, cv::Mat::zeros(src.size(), src.type()) }; 
std::vector<cv::Mat> fplanes { filter, filter };
cv::Mat complex, complexFilter;
cv::merge(planes, complex);
cv::merge(fplanes, complexFilter);

cv::dft(complex, complex, cv::DFT_COMPLEX_OUTPUT);
shift(complex); // swapping quadrants
cv::mulSpectrums(complex, complexFilter, complex, cv::DFT_ROWS);
shift(complex); 
cv::idft(complex, complex, cv::DFT_SCALE | cv::DFT_REAL_OUTPUT); 

输入图像为256×256,为对数尺度,并将低通滤波器应用于高通滤波输入图像的平方。

然后,我想要得到最终空闲结果的平方根,但是它包含负值;因此,出现了几个NaN值。

代码语言:javascript
复制
applyFilter(src, dst, highpassFilter);
cv::pow(dst, 2, dst);
applyFilter(dst, dst, lowpassFilter);
cv::sqrt(dst, dst);  // NaN !

为什么有负值,我如何处理它们才能取平方根呢?

编辑:添加shift代码

代码语言:javascript
复制
void shift(cv::Mat& src) {
    src = src(cv::Rect(0, 0, src.cols & -2, src.rows & -2)); 
    const auto cy = src.rows/2, cx = src.cols/2;
    cv::Mat q0(src, cv::Rect(0, 0, cx, cy));
    cv::Mat q1(src, cv::Rect(cx, 0, cx, cy));
    cv::Mat q2(src, cv::Rect(0, cy, cx, cy));
    cv::Mat q3(src, cv::Rect(cx, cy, cx, cy));
    cv::Mat tmp;
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);

    q1.copyTo(tmp);
    q2.copyTo(q1);
    tmp.copyTo(q2);
 } 
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-14 06:32:46

直到第三次或第四次读完你的代码我才明白.

代码语言:javascript
复制
std::vector<cv::Mat> fplanes { filter, filter };
cv::merge(fplanes, complexFilter);

这里创建了一个复值滤波器,它不是共轭对称的。应用这个滤波器产生一个频谱,它不是共轭对称的,因此你得到了一个非实反变换。

你想要做的是拥有一个纯粹的真正的过滤器:

代码语言:javascript
复制
std::vector<cv::Mat> fplanes { filter, cv::Mat::zeros(filter(), filter()) };
cv::merge(fplanes, complexFilter);

想想频域滤波器的大小和相位(而不是一个真实的和想象的成分)。幅值改变图像中每个频率分量的幅度,相移每个频率分量。通常(在非常特殊的情况下除外),你不想改变你的图像中的频率成分,因为它会搞乱你的图像。因此,将频域滤波器的相位保持在0.零相位意味着每个值都是非负的和真实的.

尽管如此,您的序列移动图像的频谱,应用滤波器,并移回:

代码语言:javascript
复制
cv::dft(complex, complex, cv::DFT_COMPLEX_OUTPUT);
shift(complex); // swapping quadrants
cv::mulSpectrums(complex, complexFilter, complex, cv::DFT_ROWS);
shift(complex); 
cv::idft(complex, complex, cv::DFT_SCALE | cv::DFT_REAL_OUTPUT); 

与简单地移动筛选器相同:

代码语言:javascript
复制
cv::dft(complex, complex, cv::DFT_COMPLEX_OUTPUT);
shift(complexFilter); // swapping quadrants
cv::mulSpectrums(complex, complexFilter, complex, 0);
cv::idft(complex, complex, cv::DFT_SCALE | cv::DFT_REAL_OUTPUT); 

还请注意,我将cv::DFT_ROWS替换为0。根据文献资料,该标志表示每个图像行是一个独立的一维转换。我的猜测是,这只对CCS填充的矩阵有影响,但最好还是忽略它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48683322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档