Перейти к содержимому
Compvision.ru
Vicul

Пример Фурье преобразования

Recommended Posts

Всем привет,

кто-нибудь подкиньте пример с cvDFT(), реально работающий, ну чтобы на входе картинка и на выходе ее результат.

Заранее благодарю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Всем привет,

кто-нибудь подкиньте пример с cvDFT(), реально работающий, ну чтобы на входе картинка и на выходе ее результат.

Заранее благодарю.

Можно здесь глянуть: http://nashruddin.com/an-example-on-using-...ith-opencv.html, не cvDFT но вроде работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

За библиотеку спасибо, но хотелось бы посмотреть, как работает cvDFT() для обучения.

В книге по OpenCV есть пример, но я его не могу понять как его в реальности применить.

Пытался сделать, как я его понимаю, в результате получил черное пятно в белой рамке. Поэтому

хочу посмотреть живой пример для этой функции.

На всякий случай привожу свой код, может кто подскажет, где я неправ.

/*

Take the Fourier transform of a small Gaussian distribution and the Fourier transform

of an image. Multiply them and take the inverse Fourier transform of the results.

What have you achieved? As the filters get bigger, you will find that working

in the Fourier space is much faster than in the normal space.

*/

		IplImage* img = cvLoadImage("Img17.jpeg");

		IplImage* dst = cvCreateImage(cvSize(2*img->width -1, 2*img->height -1),

			IPL_DEPTH_32F, 1);

		IplImage* dst2 = cvCreateImage(cvSize(2*img->width -1, 2*img->height -1),

			IPL_DEPTH_8U, 1);

		cvZero(dst);

		cvZero(dst2);

		cvNamedWindow("Img", 0);

		cvShowImage("Img", img);

		//sobel

		IplImage* gauss = cvCloneImage(img);

		cvZero(gauss);

		cvSmooth(img, gauss, CV_GAUSSIAN, 3);

		cvNamedWindow("Gauss", 0);

		cvShowImage("Gauss", gauss);

		//fourier img

		IplImage* img2 = cvCreateImage(cvSize(img->width, img->height),

			IPL_DEPTH_32F, 3);

		cvZero(img2);

		cvConvertScale(img, img2);

		cvReleaseImage(&img);

		IplImage* img3 = cvCreateImage(cvSize(img2->width, img2->height), 

			img2->depth, 1);

		cvSplit(img2, img3, NULL, NULL, NULL);

		cvReleaseImage(&img2);

		int dft_M = cvGetOptimalDFTSize(2 * img3->height -1);

		int dft_N = cvGetOptimalDFTSize(2 * img3->width -1);

		CvMat tmp;

		CvMat* dft_img = cvCreateMat(dft_M, dft_N, CV_32FC1);

		cvGetSubRect(dft_img, &tmp, cvRect(0, 0, img3->width, img3->height));

		cvCopy(img3, &tmp);

		cvGetSubRect(dft_img, &tmp, 

			cvRect(img3->width, 0, dft_img->cols-img3->width, img3->height));

		cvZero(&tmp);

		cvDFT(dft_img, dft_img, CV_DXT_FORWARD, img3->height); 

		cvReleaseImage(&img3);

		cvNamedWindow("Fourier_img", 0);

		cvShowImage("Fourier_img", dft_img);

		//fourier gaussian

		IplImage* gauss2 = cvCreateImage(cvSize(gauss->width, gauss->height), 

			IPL_DEPTH_32F, gauss->nChannels);

		cvZero(gauss2);

		cvConvertScale(gauss, gauss2);

		cvReleaseImage(&gauss);

		IplImage* gauss3 = cvCreateImage(cvSize(gauss2->width, gauss2->height), 

			gauss2->depth, 1);

		cvSplit(gauss2, gauss3, NULL, NULL, NULL);

		cvReleaseImage(&gauss2);

		CvMat* dft_gauss = cvCreateMat(dft_M, dft_N, CV_32FC1);

		cvGetSubRect(dft_gauss, &tmp, cvRect(0, 0, gauss3->width, gauss3->height));

		cvCopy(gauss3, &tmp);

		cvGetSubRect( dft_gauss, &tmp,

			cvRect(gauss3->width, 0, dft_gauss->width-gauss3->width, gauss3->height));

		cvZero(&tmp);

		cvDFT(dft_gauss, dft_gauss, CV_DXT_FORWARD, gauss3->height);

		cvReleaseImage(&gauss3);

		cvNamedWindow("Fourier_gauss", 0);

		cvShowImage("Fourier_gauss", dft_img);

		//mul

		cvMulSpectrums(dft_img, dft_gauss, dft_gauss, CV_DXT_FORWARD);

		cvDFT(dft_gauss, dft_gauss, CV_DXT_INV_SCALE, dst->height);

		cvGetSubRect(dft_gauss, &tmp, cvRect(0, 0, dst->width, dst->height));

		cvCopy(&tmp, dst);

		cvReleaseMat(&dft_gauss);

		cvReleaseMat(&dft_img);

	//	cvConvertScale(dst, dst2);

		cvNamedWindow("Fourier", 0);

		cvShowImage("Fourier", dst);

		cvReleaseImage(&dst);

		cvReleaseImage(&dst2);

		cvWaitKey(0);

		cvDestroyAllWindows();

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
За библиотеку спасибо, но хотелось бы посмотреть, как работает cvDFT() для обучения.

В книге по OpenCV есть пример, но я его не могу понять как его в реальности применить.

Пытался сделать, как я его понимаю, в результате получил черное пятно в белой рамке. Поэтому

хочу посмотреть живой пример для этой функции.

В папке с примерами есть такой код (opencv\samples\c\dft.c), скорее всего, Вам просто нужно правильно преобразовать шкалы.

#include <cxcore.h>
#include <cv.h>
#include <highgui.h>

// Rearrange the quadrants of Fourier image so that the origin is at
// the image center
// src & dst arrays of equal size & type
void cvShiftDFT(CvArr * src_arr, CvArr * dst_arr )
{
CvMat * tmp;
CvMat q1stub, q2stub;
CvMat q3stub, q4stub;
CvMat d1stub, d2stub;
CvMat d3stub, d4stub;
CvMat * q1, * q2, * q3, * q4;
CvMat * d1, * d2, * d3, * d4;

CvSize size = cvGetSize(src_arr);
CvSize dst_size = cvGetSize(dst_arr);
int cx, cy;

if(dst_size.width != size.width ||
dst_size.height != size.height){
cvError( CV_StsUnmatchedSizes, "cvShiftDFT",
"Source and Destination arrays must have equal sizes", __FILE__, __LINE__ );
}

if(src_arr==dst_arr){
tmp = cvCreateMat(size.height/2, size.width/2, cvGetElemType(src_arr));
}

cx = size.width/2;
cy = size.height/2; // image center

q1 = cvGetSubRect( src_arr, &q1stub, cvRect(0,0,cx, cy) );
q2 = cvGetSubRect( src_arr, &q2stub, cvRect(cx,0,cx,cy) );
q3 = cvGetSubRect( src_arr, &q3stub, cvRect(cx,cy,cx,cy) );
q4 = cvGetSubRect( src_arr, &q4stub, cvRect(0,cy,cx,cy) );
d1 = cvGetSubRect( src_arr, &d1stub, cvRect(0,0,cx,cy) );
d2 = cvGetSubRect( src_arr, &d2stub, cvRect(cx,0,cx,cy) );
d3 = cvGetSubRect( src_arr, &d3stub, cvRect(cx,cy,cx,cy) );
d4 = cvGetSubRect( src_arr, &d4stub, cvRect(0,cy,cx,cy) );

if(src_arr!=dst_arr){
if( !CV_ARE_TYPES_EQ( q1, d1 )){
cvError( CV_StsUnmatchedFormats, "cvShiftDFT",
"Source and Destination arrays must have the same format", __FILE__, __LINE__ );
}
cvCopy(q3, d1, 0);
cvCopy(q4, d2, 0);
cvCopy(q1, d3, 0);
cvCopy(q2, d4, 0);
}
else{
cvCopy(q3, tmp, 0);
cvCopy(q1, q3, 0);
cvCopy(tmp, q1, 0);
cvCopy(q4, tmp, 0);
cvCopy(q2, q4, 0);
cvCopy(tmp, q2, 0);
}
}

int main(int argc, char ** argv)
{
const char* filename = argc >=2 ? argv[1] : "lena.jpg";
IplImage * im;

IplImage * realInput;
IplImage * imaginaryInput;
IplImage * complexInput;
int dft_M, dft_N;
CvMat* dft_A, tmp;
IplImage * image_Re;
IplImage * image_Im;
double m, M;

im = cvLoadImage( filename, CV_LOAD_IMAGE_GRAYSCALE );
if( !im )
return -1;

realInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1);
imaginaryInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1);
complexInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 2);

cvScale(im, realInput, 1.0, 0.0);
cvZero(imaginaryInput);
cvMerge(realInput, imaginaryInput, NULL, NULL, complexInput);

dft_M = cvGetOptimalDFTSize( im->height - 1 );
dft_N = cvGetOptimalDFTSize( im->width - 1 );

dft_A = cvCreateMat( dft_M, dft_N, CV_64FC2 );
image_Re = cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1);
image_Im = cvCreateImage( cvSize(dft_N, dft_M), IPL_DEPTH_64F, 1);

// copy A to dft_A and pad dft_A with zeros
cvGetSubRect( dft_A, &tmp, cvRect(0,0, im->width, im->height));
cvCopy( complexInput, &tmp, NULL );
if( dft_A->cols > im->width )
{
cvGetSubRect( dft_A, &tmp, cvRect(im->width,0, dft_A->cols - im->width, im->height));
cvZero( &tmp );
}

// no need to pad bottom part of dft_A with zeros because of
// use nonzero_rows parameter in cvDFT() call below

cvDFT( dft_A, dft_A, CV_DXT_FORWARD, complexInput->height );

cvNamedWindow("win", 0);
cvNamedWindow("magnitude", 0);
cvShowImage("win", im);

// Split Fourier in real and imaginary parts
cvSplit( dft_A, image_Re, image_Im, 0, 0 );

// Compute the magnitude of the spectrum Mag = sqrt(Re^2 + Im^2)
cvPow( image_Re, image_Re, 2.0);
cvPow( image_Im, image_Im, 2.0);
cvAdd( image_Re, image_Im, image_Re, NULL);
cvPow( image_Re, image_Re, 0.5 );

// Compute log(1 + Mag)
cvAddS( image_Re, cvScalarAll(1.0), image_Re, NULL ); // 1 + Mag
cvLog( image_Re, image_Re ); // log(1 + Mag)


// Rearrange the quadrants of Fourier image so that the origin is at
// the image center
cvShiftDFT( image_Re, image_Re );

cvMinMaxLoc(image_Re, &m, &M, NULL, NULL, NULL);
cvScale(image_Re, image_Re, 1.0/(M-m), 1.0*(-m)/(M-m));
cvShowImage("magnitude", image_Re);

cvWaitKey(-1);
return 0;
}[/code]

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо за инфу, теперь начало доходить что к чему.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А вот еще вопрос по преобразованию фурье:

Тут в примере приведено комплексное преобразование Фурье. (оно осуществляется над комплексным представлением сигнала).

Но есть также возможность осуществлять преобразование над вещественным сигналом с помощью функции cvDFT.

Результаты будут разные или это только вопрос как будут располагаться числа в выходной матрице.

Вопрос возник так ака недавно нашла статью, в которой рассказывается разница между вещественным преобразованием Фурье и комплексным.

Саму статью можно почитать по ссылке:

http://www.google.ru/url?sa=t&source=w...rqXEGbQRhmWMGCA

там глава 31.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Да, разница видимо есть, и она подробно описана начиная со страницы №5 того документа, который Вы прикрепили.

(правда русский перевод немного бредовый :) )

Вообще документик интересный и полезный, надо будет перевести нормально.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

есть ли какой то смысл\возможность использовать cvDFT вместо cvMatchTemplate?(для поиска пересечения 2-х изображений)

есть ли смысл использовать FFTW может будет быстрее?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В детали не вдавался, но cvMatchTemplate внутри себя вызывает функцию icvCrossCorr, которая использует cvDFT.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

ну тут как бы с одной стороны важно понять как это делается математически, а с другой как это быстрее реализовано технически.

cvMatchTemplate использует большое поле на одном изображении и ищет на нем маленький кусок со второго.

http://nashruddin.com/phase-correlation-function-in-opencv.html#results

вот есть еще такая вещь через FFTW, но тут походу смотрится корреляция 2-х изображений целиком.

может возможно ее как то переделать как cvMatchTemplate для кусков изображения? а то я самой математической подоплеки не особо понимаю.

причем в icvCrossCorr еще интересный комментарий

// disable OpenMP in the case of Visual Studio,

// otherwise the performance drops significantly

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

еще возможно у кого то есть идеи насчет http://fly.mpi-cbg.de/~preibisch/software.html

http://pacific.mpi-cbg.de/wiki/index.php/Downloads попробовать можно скачав тут.плагин Stitch2D.

там можно задавать кол-во пиков для нахождения.(вроде бы находит точнее, чем если использовать 1 пик)

я не понимаю как это можно использовать, ибо после использования cvMatchTemplate обычно ищут всего 1 пик.

и что за глобальная оптимизация?

If more than two input images/stacks are used the correct placement of all tiles is determined using a global optimization.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Программа для экспериментов с преобразованием Фурье.

Содержит примеры разложения изображения на действительную и мнимую части спектра, и для разложения изображения на амплитудную и фазовую части спектра, а так-же обратные преобразования для обоих типов разложения.

На картинке я вырезал кольцо из амплитудной и фазовой составляющей спектра разложения. И провел обратное преобразование.

post-1-0-28458900-1303470642_thumb.png

Исходник:

FFT.RAR

  • Like 2

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×