F
F
Fedor2015-01-23 20:11:50
Qt
Fedor, 2015-01-23 20:11:50

What can cause differences when working with Fourier transforms in OpenCV and matlab?

Hello. There is a Matlab code that does the inverse Fourier transform on the picture as follows:
1. Original picture:
bd115a5a94c04d478ee42a953d099dc5.bmp
Matlab code:

>>a1=imread('E:\F_1.bmp');
>> a2=a1(:,:,1); //Выбираем из рисунка 1 слой (красный)
>> a3=double(a2); 
>> a4=a3/255; //Нормируем матрицу на единицу
>> a6=fft2(a4); //Делаем двумерное Фурье-преобразование
>> a7=fftshift(a6); //Переставляем квадраты матрицы
>> a8=abs(a7); //Рассчитываем модуль
>> mesh(a8) //Выводим Фурье спектр на экран
>> x1=a6.*a6; //Поэлементно перемножаем (элементы матрицы ДО перестановки квадратов, т.е. a6) 
>> x2=ifft2(x1); //Делаем обратное Фурье-преобразование от результата перемножения
>> x3=ifftshift(x2); //Переставляем квадраты матрицы (чтобы пирамидка автокорреляции имела нормальный вид)
>> x4=abs(x3); //Вычисляем модуль
>> mesh(x4) //Выводим пирамидку автокорреляции на экран

As a result, the following pictures are obtained:
Fourier spectrum:
001a4f91e7c44b77835d573cfb3115a6.png
and inverse Fourier transform:
a6e677f30811435b8fb1461c70eed390.png
When I use the example modified by me ( example ) in C ++,
the Fourier spectrum for the original picture is as follows:
cbbb44031a7c462691c0422ad5743842.png
and the inverse transform looks like this:
08b34c818a124ea5a6146f567e54bf49.png
As you can see, the results obtained using OpenCV and Matlab are different and the challenge is to keep the results similar.
The C++ function code that outputs these results is as follows:
void MainWindow::getFourierData(Mat img)
{
    src = img; 
    cvtColor(src, src_gray, CV_RGB2GRAY); //преобразуем в градации серого
//ниже, как в <a href="http://docs.opencv.org/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.html?highlight=dft">примере</a>
    int M = getOptimalDFTSize( src_gray.rows );
        int N = getOptimalDFTSize( src_gray.cols );
        Mat padded;
        copyMakeBorder(src_gray, padded, 0, M - src_gray.rows, 0, N - src_gray.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);

        // compute log(1 + sqrt(Re(DFT(img))**2 + Im(DFT(img))**2))
        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));

        int cx = mag.cols/2;
        int cy = mag.rows/2;

        // rearrange the quadrants of Fourier image
        // so that the origin is at the image center
        Mat tmp;
        Mat q0(mag, Rect(0, 0, cx, cy));
        Mat q1(mag, Rect(cx, 0, cx, cy));
        Mat q2(mag, Rect(0, cy, cx, cy));
        Mat q3(mag, Rect(cx, cy, cx, cy));

        q0.copyTo(tmp);
        q3.copyTo(q0);
        tmp.copyTo(q3);

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

        //normalize(mag, mag, 0, 1, CV_MINMAX);

        normalize(mag, mag, 0, 255, CV_MINMAX);

//тут пример заканчивается
//теперь повторяем тоже самое, чтобы получить обратное преобразование

     M = getOptimalDFTSize( mag.rows );
        N = getOptimalDFTSize( mag.cols );
        copyMakeBorder(mag, padded, 0, M - mag.rows, 0, N - mag.cols, BORDER_CONSTANT, Scalar::all(0));
      Mat plans[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
        merge(plans, 2, complexImg);
        complexImg.mul(complexImg); //поэлементное перемножение

        idft(complexImg, complexImg); //обратное преобразование
        complexImg=cv::abs(complexImg); //берём модуль

//далее для развёртки изображения повторяем код с примера
        split(complexImg, plans);
        magnitude(plans[0], plans[1], plans[0]);
        mag = plans[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));

         cx = mag.cols/2;
         cy = mag.rows/2;
        // rearrange the quadrants of Fourier image
        // so that the origin is at the image center

        Mat qq0(mag, Rect(0, 0, cx, cy));
        Mat qq1(mag, Rect(cx, 0, cx, cy));
        Mat qq2(mag, Rect(0, cy, cx, cy));
        Mat qq3(mag, Rect(cx, cy, cx, cy));

        qq0.copyTo(tmp);
        qq3.copyTo(qq0);
        tmp.copyTo(qq3);

        qq1.copyTo(tmp);
        qq2.copyTo(qq1);
        tmp.copyTo(qq2);


    normalize(mag, mag, 0, 255, CV_MINMAX);
        mag.copyTo(src_gray); 




    IplImage copy =src_gray;
    IplImage* bi = &copy; 
    cvSaveImage("buffer.png", bi);
    image_bin.load("buffer.png");
    //для соотношений сторон отличных 4:3 возникает искажение изображения
    //поэтому, пока решение не найдено, сохраняем картинку в буфер, считываем
    //и выводим её на результат.
    ui->imageBin->setPixmap(QPixmap::fromImage(image_bin.scaled(
                                                   ui->imageBin->geometry().width(),
                                                   ui->imageBin->geometry().height(), Qt::IgnoreAspectRatio)));
}

In this C++ code, we tried to implement the same algorithm that is implemented in Matlab, but as you can see, the pictures are different.
And here the question arises, where did we screw up in C ++?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
S
Sergey, 2015-01-23
@begemot_sun

At a minimum, after the forward and inverse Fourier transforms, you should get a blurry tighter picture, neither there nor there it is observed. Smoke sources.

F
Fedor, 2015-01-29
@krox

In general, I don’t know if I received it correctly or not, but I got the following.
69f7e73ca7584cfaa3e92abc39b5d5db.pngThe result with the module
is the following code:

cv::Mat MainWindow::fourierSpectrum(Mat img)
{

    src = img; //imread(path.toStdString(), 1); //читаем открытое изображение


   cvtColor(src, src_gray, CV_RGB2GRAY);

    int M = getOptimalDFTSize( src_gray.rows );
        int N = getOptimalDFTSize( src_gray.cols );
        Mat padded;
        copyMakeBorder(src_gray, padded, 0, M - src_gray.rows, 0, N - src_gray.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, DFT_COMPLEX_OUTPUT);

        cv::multiply(cv::abs(complexImg), complexImg, complexImg);

        idft(complexImg,complexImg);
        split(complexImg, planes);

        magnitude(planes[0], planes[1], planes[0]);
        Mat mag = planes[0];
        mag += Scalar::all(1);
        //log(mag, mag); //если это не закомментить получается спектр, показанный в вопросе

        normalize(mag, mag, 0, 255, CV_MINMAX);
        mag.copyTo(src_gray);
        return src_gray;

}

A little fun: by drawing a heart and applying this transformation with the addition of red color
cvtColor(src_gray, src_gray, CV_GRAY2RGB);
src_gray += CV_RGB(255,0,0);

It turns out quite a funny effect
. Maybe someone will come in handy.
PS> if you remove cv::abs from the code, you get the following picture:
a45c8fe323834bf9a9173d69e543d53e.pngResult without the
PSS module> Pictures uploaded to Habr in black tones are distorted for some reason ....

U
URURU, 2015-01-26
@URURU

Ask better on the exhibitor forum:
matlab.exponenta.ru/forum

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question