Search code examples
c++opencvfftdft

opencv c++ inverse fourier transformation does not give same image


I have a bgr image and convert to lab channels.

I tried to check if the idft image of the result of dft of L channel image is the same.

// MARK: Split LAB Channel each
cv::Mat lab_resized_host_image;
cv::cvtColor(resized_host_image, lab_resized_host_image, cv::COLOR_BGR2Lab);
imshow("lab_resized_host_image", lab_resized_host_image);
cv::Mat channel_L_host_image, channel_A_host_image, channel_B_host_image;
std::vector<cv::Mat> channel_LAB_host_image(3);
cv::split(lab_resized_host_image, channel_LAB_host_image);

// MARK: DFT the channel_L host image.
channel_L_host_image = channel_LAB_host_image[0];
imshow("channel_L_host_image", channel_L_host_image);
cv::Mat padded_L;
int rows_L = getOptimalDFTSize(channel_L_host_image.rows);
int cols_L = getOptimalDFTSize(channel_L_host_image.cols);
copyMakeBorder(channel_L_host_image, padded_L, 0, rows_L - channel_L_host_image.rows, 0, cols_L - channel_L_host_image.cols, BORDER_CONSTANT, Scalar::all(0));

Mat planes_L[] = {Mat_<float>(padded_L), Mat::zeros(padded_L.size(), CV_32F)};
Mat complexI_L;
merge(planes_L, 2, complexI_L);
dft(complexI_L, complexI_L);

// MARK: iDFT Channel_L.
Mat complexI_channel_L = complexI_L;
Mat complexI_channel_L_idft;
cv::dft(complexI_L, complexI_channel_L_idft, cv::DFT_INVERSE|cv::DFT_REAL_OUTPUT);
normalize(complexI_channel_L_idft, complexI_channel_L_idft, 0, 1, NORM_MINMAX);
imshow("complexI_channel_L_idft", complexI_channel_L_idft);

Each imshow give me different image... I think normalization would be error... what is wrong? help!

original image

enter image description here

idft

enter image description here


Solution

  • OpenCV’s FFT is not normalized by default. One of the forward/backward transform pair must be normalized for the pair to reproduce the input values. Simply add cv::DFT_SCALE to the options:

    cv::dft(complexI_mid_frequency_into_channel_A, iDFT_mid_frequency_into_channel_A, cv::DFT_INVERSE|cv::DFT_REAL_OUTPUT|cv::DFT_SCALE);