Здравствуйте. Имеется код на Matlab, делающий обратное преобразование фурье по картинке следующим образом:
1. Исходная картинка:
Код на матлабе:
>>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) //Выводим пирамидку автокорреляции на экран
В результате получаются следующие картинки:
Спектр Фурье:
и обратное преобразование Фурье:
Когда же на С++ использую модифицированный мною пример (
пример)
спектр Фурье по исходной картинке получается следующим:
а обратное преобразование выглядит так:
Как видите, результаты, полученные с помощью OpenCV и Matlab разные и задача состоит в том, чтобы результаты были похожи.
Код функции на C++, который выводит данные результаты следующий:
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 = ©
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)));
}
В данном С++ коде постарались реализовать тот же алгоритм, который реализован на Matlab, но как видите, картинки получаются разные.
И тут возникает вопрос, а где мы напортачили на C++?