OpenCV中对空间域的DFT不起作用

DFT to spatial domain in OpenCV is not working

本文关键字:DFT 不起作用 空间 OpenCV      更新时间:2023-10-16

我创建了一个图像的dft,经过一些滤波器调整后,我想将其转换回真实图像,但每次这样做都会给我错误的结果。。它似乎没有把它转换回来。ForierTransformcreateGaussianHighPassFilter是我自己的函数,我使用的代码的其余部分如下所示,用于反转回真实图像。

Mat fft = ForierTransform(HeightPadded,WidthPadded);
Mat ghpf = createGaussianHighPassFilter(Size(WidthPadded, HeightPadded), db);
Mat res;
cv::multiply(fft,ghpf,res);
imshow("fftXhighpass1", res);
idft(res,res,DFT_INVERSE,res.rows);
cv::Mat croped = res(cv::Rect(0, 0, img.cols,img.rows));
//res.convertTo(res,CV_32S);
imshow("fftXhighpass", res);

即使我不应用滤波器,我也无法反转dft结果。。。这是我的dft代码,我找不到任何样本将dft反转回正常图像。。

Mat ForierTransform(int M,int N)
{
    Mat img = imread("thumb1-small-test.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    Mat padded;
    copyMakeBorder(img, padded, 0, M - img.rows, 0, N - img.cols, BORDER_CONSTANT, Scalar::all(0));
    Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
    Mat complexImg;
    merge(planes, 2, complexImg);
    dft(complexImg, complexImg);

    split(complexImg, planes);
    magnitude(planes[0], planes[1], planes[0]);
    Mat mag = planes[0];
    mag += Scalar::all(1);
    log(mag, mag);
        // crop the spectrum, if it has an odd number of rows or columns
    mag = mag(Rect(0, 0, mag.cols & -2, mag.rows & -2));

    normalize(mag, mag, 0, 1, CV_MINMAX);
    return mag;
}

好心帮助

[编辑:在我找到mevatron的帮助下的解决方案后](下面是正确的代码)

 Mat ForierTransform(int M,int N)
{
    Mat img = imread("thumb1-small-test.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    Mat padded;
    copyMakeBorder(img, padded, 0, M - img.rows, 0, N - img.cols, BORDER_CONSTANT, Scalar::all(0));
    Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
    Mat complexImg;
    merge(planes, 2, complexImg);
    dft(complexImg, complexImg);
    return complexImg;
}
Mat img = imread("thumb1-small-test.jpg",CV_LOAD_IMAGE_GRAYSCALE);
int WidthPadded=0,HeightPadded=0;
WidthPadded=img.cols*2;
HeightPadded=img.rows*2;
int M = getOptimalDFTSize( img.rows );
//Create a Gaussian Highpass filter 5% the height of the Fourier transform
double db  = 0.05 * HeightPadded;

Mat fft = ForierTransform(HeightPadded,WidthPadded);
Mat ghpf = createGaussianHighPassFilter(Size(WidthPadded, HeightPadded), db);
Mat res;
cv::mulSpectrums(fft,ghpf,res,DFT_COMPLEX_OUTPUT);

idft(res,res,DFT_COMPLEX_OUTPUT,img.rows);
Mat padded;
copyMakeBorder(img, padded, 0, img.rows, 0, img.cols, BORDER_CONSTANT, Scalar::all(0));
Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
split(res, planes);
magnitude(planes[0], planes[1], planes[0]);
Mat mag = planes[0];
mag += Scalar::all(1);
log(mag, mag);
// crop the spectrum, if it has an odd number of rows or columns
mag = mag(Rect(0, 0, mag.cols & -2, mag.rows & -2));
int cx = mag.cols/2;
int cy = mag.rows/2;
normalize(mag, mag, 1, 0, CV_MINMAX);
cv::Mat croped = mag(cv::Rect(cx, cy, img.cols,img.rows));
cv::threshold(croped , croped , 0.56, 1, cv::THRESH_BINARY);
imshow("fftPLUShpf", mag);
imshow("cropedBinary", croped);

它现在可以显示手指的脊谷,并且可以在阈值方面进行更优化

我看到这里出现了一些问题。

首先,您需要使用mulSpectrums函数来卷积两个FFT,并且而不是相乘。

其次,createGaussianHighPassFilter仅输出单通道非复数滤波器。您可能只需要将复杂通道设置为Mat::zeros,就像您对输入图像所做的那样。

第三,不要将FFT的输出转换为对数幅度谱。它不会与过滤器正确组合,在执行反向操作时也不会得到相同的结果。因此,只要在DFT执行之后立即返回complexImg即可。对数幅度谱对人类查看数据很有用,但对你想要做的事情却没有帮助

最后,请注意dft的全复输出和复共轭对称(CCS)压缩输出之间的差异。英特尔在这里有一个关于如何格式化这些数据的好页面。在你的情况下,为了简单起见,我会让一切都处于完全复杂的模式,让你的生活更轻松。

希望能有所帮助!