Jump to content
Compvision.ru
Sign in to follow this  
Vicul

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

Recommended Posts

Всем привет,

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

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

Share this post


Link to post
Share on other sites
Всем привет,

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

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

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

Share this post


Link to post
Share on other sites

За библиотеку спасибо, но хотелось бы посмотреть, как работает 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();

Share this post


Link to post
Share on other sites
За библиотеку спасибо, но хотелось бы посмотреть, как работает 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]

Share this post


Link to post
Share on other sites

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

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

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

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

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

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

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

там глава 31.

Share this post


Link to post
Share on other sites

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

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

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

еще возможно у кого то есть идеи насчет 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.

Share this post


Link to post
Share on other sites

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

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

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

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

Исходник:

FFT.RAR

  • Like 2

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×