I am trying to do a 2D FFT with complex input and output and I am not getting the expected results in the imaginary part. Using OpenCV 4.5.1 on Debian 11.
Here is my code:
const cv::Size imgSize = { 256, 256 };
cv::Mat I = cv::Mat::zeros(imgSize, CV_64FC1);
cv::circle(I, {imgSize.width/2, imgSize.height/2}, imgSize.height/2-1,
cv::Scalar::all(1.0), cv::FILLED, cv::LINE_4);
cv::imshow("Intensity", I);
cv::Mat phase = cv::Mat::zeros(imgSize, CV_64FC1);
cv::imshow("Phase", phase);
// Make complex matrix
cv::Mat planesIn[] = { I, phase };
cv::Mat complexFieldIn = cv::Mat::zeros(imgSize, CV_64FC2);
cv::merge(planesIn, 2, complexFieldIn);
cv::Mat complexFieldOut = cv::Mat::zeros(imgSize, CV_64FC2);
cv::dft(complexFieldIn, complexFieldOut, cv::DFT_COMPLEX_INPUT|cv::DFT_COMPLEX_OUTPUT);
std::cout << complexFieldOut.rows << "x" << complexFieldOut.cols
<< " " << complexFieldOut.depth() << " " << complexFieldOut.type()
<< " " << complexFieldOut.elemSize1()
<< " " << complexFieldOut.step1() << std::endl;
fftshift(complexFieldOut); // (impl. copied from example code)
cv::Mat planesOut[] = { cv::Mat::zeros(imgSize, CV_64FC1), cv::Mat::zeros(imgSize, CV_64FC1) };
cv::split(complexFieldOut, planesOut);
// Normalize for display
cv::Mat real, imag;
cv::normalize(planesOut[0], real, 0, 1, cv::NORM_MINMAX);
cv::imshow("REAL", real);
cv::normalize(planesOut[1], imag, 0, 1, cv::NORM_MINMAX);
cv::imshow("IMAG", imag);
// Compute magnitude
cv::Mat magI;
cv::magnitude(planesOut[0], planesOut[1], magI);
// Normalize for display
cv::normalize(magI, magI, 0, 10, cv::NORM_MINMAX);
cv::imshow("Magnitude", magI);
Here is the output (normalized for display):
And here is the output from the equivalent in MATLAB using fft2:
(forum not letting me upload another image here)
What is happening with the imaginary part in the OpenCV implementation?