Witam,
piszę program dokonujący przetwarzania w dziedzinie częstotliwości. Znalazłem w internecie kod pokazujący jak przy pomocy funkcji z biblioteki OpenCV wykonać DFT w przód, jak otrzymać widmo, oraz jak powrócić do dziedziny przestrzennej. Spróbowałem na tablicy(przechowującej obraz) otrzymanej w wyniku użycia DFT zastosować filtr. Po podglądzie widma widać, że filtr faktycznie zadziałał, ale niestety wykonując IDFT otrzymuje już obraz, który jest prawie czarny (zaznaczyć trzeba, że bez użycia filtra, IDFT daje prawidłowy obraz, taki jak na wejściu).
Używam do tego Qt 4.7, OpenCV 2.0
void cvShiftDFT(CvArr * src_arr, CvArr * dst_arr ){} // funkcja wykonujaca przesuniecie cwiartek obrazu 'na krzyz'
pozniej w main`ie
IplImage * im;
IplImage * im1;
IplImage * wyswietlaDFT;
IplImage * wyswietlaIDFT;
IplImage * realInput;
IplImage * imaginaryInput;
IplImage * complexInput;
int dft_M, dft_N;
CvMat* dft_A, tmp;
IplImage * image_Re;
IplImage * image_Im;
double m, M;
im1 = cvLoadImage(filenamee );
im = cvLoadImage(filenamee, CV_LOAD_IMAGE_GRAYSCALE);
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);
wyswietlaDFT = cvCreateImage(cvSize(dft_N, dft_M), IPL_DEPTH_8U, 1);
wyswietlaIDFT = cvCreateImage(cvSize(dft_N, dft_M), IPL_DEPTH_8U, 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 );
///////////////PROBNY FILTR
cvShiftDFT( dft_A, dft_A );
CvMat *mask = cvCreateMat( dft_M, dft_N, CV_64FC1 );
int Xmin = -im->width/2;
int Ymin = -im->height/2;
int i, j;
int fc = 50;
// function transferece filter matrix
for(i=0; i<dft_N; i++)
for(j=0; j<dft_M; j++)
{
double dxy = sqrt(pow(Xmin+i,2)+pow(Ymin+j,2));
double H;
if(dxy<=fc){ H=0;}
else
H = 1;
cvSetReal2D(mask, j, i, H);
}
cvScale(mask, mask, 1.0, 0.0);
CvMat *mask2 = cvCreateMat( dft_M, dft_N, CV_64FC2 );
cvMerge(mask, mask, 0,0,mask2);
cvMulSpectrums(dft_A, mask2, dft_A, 1); // mnozenie F-obrazu i maski filtru - mnoznone sa zarowno rzeczywista jak i urojona czesc F-obrazu
cvShiftDFT( dft_A, dft_A );
////////// DO WYSWIETLANIA WIDMA - wyswietlajac widmo widac zastosowany filtr
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("DFT", image_Re);
//ODWROTNA, do wyswietlenia wyniku/////////////////////////////////////////////////////////////////
cvDFT( dft_A, dft_A, CV_DXT_INVERSE_SCALE, dft_N);
// 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
cvMinMaxLoc(image_Re, &m, &M, NULL, NULL, NULL);
cvScale(image_Re, image_Re, 1.0/(M-m), 1.0*(-m)/(M-m));
cvShowImage("Obraz", image_Re);
czy gdzieś występują niepotrzebne, albo błędne przeskalowania? A może wina leży po stronie tworzonego filtru i jego zastosowaniu. Proszę o sugestie. Z góry dziękuję!