我创建了一个图像的 dft,在用过滤器进行了一些调整后,我想将它转换回真实图像,但是每次我这样做时它都会给我错误的结果......似乎它没有将它转换回来。ForierTransform
和 createGaussianHighPassFilter
是我自己的函数,我使用的代码的其余部分如下所示,用于反转回真实图像。
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 进行卷积,并且 而不是 multiply 。
其次,createGaussianHighPassFilter
仅输出单 channel 非复杂滤波器。您可能只需要像对输入图像所做的那样将复杂 channel 设置为 Mat::zeros
。
第三,不要将 FFT 的输出转换为对数幅度频谱。它不会与过滤器正确组合,并且在执行逆操作时您不会得到相同的结果。因此,只需在执行 DFT 后立即返回 complexImg
。对数幅度频谱对于人类查看数据很有用,但不适用于您尝试执行的操作。
最后,请务必注意 dft
的全复杂输出与复杂共轭对称 (CCS) 打包输出之间的区别。英特尔在如何格式化 here 上有一个很好的页面。在您的情况下,为了简单起见,我会将所有内容都保留在全复杂模式中,以使您的生活更轻松。
希望有帮助!
关于c++ - OpenCV 到空间域的 DFT 不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9646652/