Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

TRANSFORMÉE DE FOURIER RAPIDE 2D POUR LES IMAGES


Information sur la source

Description

Très utile en traitement d'image et analyse d'image


Utiliser avec la classe CxImage que vous pouvez trouver au :


http://www.xdp.it/
 

Source

  • bool CxImage::FFT2(CxImage* srcReal, CxImage* srcImag, CxImage* dstReal, CxImage* dstImag,
  • long direction, bool bForceFFT, bool bMagnitude)
  • {
  • //check if there is something to convert
  • if (srcReal==NULL && srcImag==NULL) return false;
  • long w,h;
  • //get width and height
  • if (srcReal) {
  • w=srcReal->GetWidth();
  • h=srcReal->GetHeight();
  • } else {
  • w=srcImag->GetWidth();
  • h=srcImag->GetHeight();
  • }
  • bool bXpow2 = IsPowerof2(w);
  • bool bYpow2 = IsPowerof2(h);
  • //if bForceFFT, width AND height must be powers of 2
  • if (bForceFFT && !(bXpow2 && bYpow2)) {
  • long i;
  • i=0;
  • while((1<<i)<w) i++;
  • w=1<<i;
  • bXpow2=true;
  • i=0;
  • while((1<<i)<h) i++;
  • h=1<<i;
  • bYpow2=true;
  • }
  • // I/O images for FFT
  • CxImage *tmpReal,*tmpImag;
  • // select output
  • tmpReal = (dstReal) ? dstReal : srcReal;
  • tmpImag = (dstImag) ? dstImag : srcImag;
  • // src!=dst -> copy the image
  • if (srcReal && dstReal) tmpReal->Copy(*srcReal,true,false,false);
  • if (srcImag && dstImag) tmpImag->Copy(*srcImag,true,false,false);
  • // dst&&src are empty -> create new one, else turn to GrayScale
  • if (srcReal==0 && dstReal==0){
  • tmpReal = new CxImage(w,h,8);
  • tmpReal->Clear(0);
  • tmpReal->SetGrayPalette();
  • } else {
  • if (!tmpReal->IsGrayScale()) tmpReal->GrayScale();
  • }
  • if (srcImag==0 && dstImag==0){
  • tmpImag = new CxImage(w,h,8);
  • tmpImag->Clear(0);
  • tmpImag->SetGrayPalette();
  • } else {
  • if (!tmpImag->IsGrayScale()) tmpImag->GrayScale();
  • }
  • if (!(tmpReal->IsValid() && tmpImag->IsValid())){
  • if (srcReal==0 && dstReal==0) delete tmpReal;
  • if (srcImag==0 && dstImag==0) delete tmpImag;
  • return false;
  • }
  • //resample for FFT, if necessary
  • tmpReal->Resample(w,h,0);
  • tmpImag->Resample(w,h,0);
  • //ok, here we have 2 (w x h), grayscale images ready for a FFT
  • double* real;
  • double* imag;
  • long j,k,m;
  • _complex **grid;
  • //double mean = tmpReal->Mean();
  • /* Allocate memory for the grid */
  • grid = (_complex **)malloc(w * sizeof(_complex));
  • for (k=0;k<w;k++) {
  • grid[k] = (_complex *)malloc(h * sizeof(_complex));
  • }
  • for (j=0;j<h;j++) {
  • for (k=0;k<w;k++) {
  • grid[k][j].x = tmpReal->GetPixelIndex(k,j)-128;
  • grid[k][j].y = tmpImag->GetPixelIndex(k,j)-128;
  • }
  • }
  • //DFT buffers
  • double *real2,*imag2;
  • real2 = (double*)malloc(max(w,h) * sizeof(double));
  • imag2 = (double*)malloc(max(w,h) * sizeof(double));
  • /* Transform the rows */
  • real = (double *)malloc(w * sizeof(double));
  • imag = (double *)malloc(w * sizeof(double));
  • m=0;
  • while((1<<m)<w) m++;
  • for (j=0;j<h;j++) {
  • for (k=0;k<w;k++) {
  • real[k] = grid[k][j].x;
  • imag[k] = grid[k][j].y;
  • }
  • if (bXpow2) FFT(direction,m,real,imag);
  • else DFT(direction,w,real,imag,real2,imag2);
  • for (k=0;k<w;k++) {
  • grid[k][j].x = real[k];
  • grid[k][j].y = imag[k];
  • }
  • }
  • free(real);
  • free(imag);
  • /* Transform the columns */
  • real = (double *)malloc(h * sizeof(double));
  • imag = (double *)malloc(h * sizeof(double));
  • m=0;
  • while((1<<m)<h) m++;
  • for (k=0;k<w;k++) {
  • for (j=0;j<h;j++) {
  • real[j] = grid[k][j].x;
  • imag[j] = grid[k][j].y;
  • }
  • if (bYpow2) FFT(direction,m,real,imag);
  • else DFT(direction,h,real,imag,real2,imag2);
  • for (j=0;j<h;j++) {
  • grid[k][j].x = real[j];
  • grid[k][j].y = imag[j];
  • }
  • }
  • free(real);
  • free(imag);
  • free(real2);
  • free(imag2);
  • /* converting from double to byte, there is a HUGE loss in the dynamics
  • "nn" tries to keep an acceptable SNR, but 8bit=48dB: don't ask more */
  • double nn=pow((double)2,(double)log((double)max(w,h))/(double)log((double)2)-4);
  • //reversed gain for reversed transform
  • if (direction==-1) nn=1/nn;
  • //bMagnitude : just to see it on the screen
  • if (bMagnitude) nn*=4;
  • for (j=0;j<h;j++) {
  • for (k=0;k<w;k++) {
  • if (bMagnitude){
  • tmpReal->SetPixelIndex(k,j,(BYTE)max(0,min(255,(nn*(3+log(_cabs(grid[k][j])))))));
  • if (grid[k][j].x==0){
  • tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128+(atan(grid[k][j].y/0.0000000001)*nn)))));
  • } else {
  • tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128+(atan(grid[k][j].y/grid[k][j].x)*nn)))));
  • }
  • } else {
  • tmpReal->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128 + grid[k][j].x*nn))));
  • tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128 + grid[k][j].y*nn))));
  • }
  • }
  • }
  • for (k=0;k<w;k++) free (grid[k]);
  • free (grid);
  • if (srcReal==0 && dstReal==0) delete tmpReal;
  • if (srcImag==0 && dstImag==0) delete tmpImag;
  • return true;
  • }
bool CxImage::FFT2(CxImage* srcReal, CxImage* srcImag, CxImage* dstReal, CxImage* dstImag,
				   long direction, bool bForceFFT, bool bMagnitude)
{
	//check if there is something to convert
	if (srcReal==NULL && srcImag==NULL) return false;

	long w,h;
	//get width and height
	if (srcReal) {
		w=srcReal->GetWidth();
		h=srcReal->GetHeight();
	} else {
		w=srcImag->GetWidth();
		h=srcImag->GetHeight();
	}

	bool bXpow2 = IsPowerof2(w);
	bool bYpow2 = IsPowerof2(h);
	//if bForceFFT, width AND height must be powers of 2
	if (bForceFFT && !(bXpow2 && bYpow2)) {
		long i;
		
		i=0;
		while((1<<i)<w) i++;
		w=1<<i;
		bXpow2=true;

		i=0;
		while((1<<i)<h) i++;
		h=1<<i;
		bYpow2=true;
	}

	// I/O images for FFT
	CxImage *tmpReal,*tmpImag;

	// select output
	tmpReal = (dstReal) ? dstReal : srcReal;
	tmpImag = (dstImag) ? dstImag : srcImag;

	// src!=dst -> copy the image
	if (srcReal && dstReal) tmpReal->Copy(*srcReal,true,false,false);
	if (srcImag && dstImag) tmpImag->Copy(*srcImag,true,false,false);

	// dst&&src are empty -> create new one, else turn to GrayScale
	if (srcReal==0 && dstReal==0){
		tmpReal = new CxImage(w,h,8);
		tmpReal->Clear(0);
		tmpReal->SetGrayPalette();
	} else {
		if (!tmpReal->IsGrayScale()) tmpReal->GrayScale();
	}
	if (srcImag==0 && dstImag==0){
		tmpImag = new CxImage(w,h,8);
		tmpImag->Clear(0);
		tmpImag->SetGrayPalette();
	} else {
		if (!tmpImag->IsGrayScale()) tmpImag->GrayScale();
	}

	if (!(tmpReal->IsValid() && tmpImag->IsValid())){
		if (srcReal==0 && dstReal==0) delete tmpReal;
		if (srcImag==0 && dstImag==0) delete tmpImag;
		return false;
	}

	//resample for FFT, if necessary 
	tmpReal->Resample(w,h,0);
	tmpImag->Resample(w,h,0);

	//ok, here we have 2 (w x h), grayscale images ready for a FFT

	double* real;
	double* imag;
	long j,k,m;

	_complex **grid;
	//double mean = tmpReal->Mean();
	/* Allocate memory for the grid */
	grid = (_complex **)malloc(w * sizeof(_complex));
	for (k=0;k<w;k++) {
		grid[k] = (_complex *)malloc(h * sizeof(_complex));
	}
	for (j=0;j<h;j++) {
		for (k=0;k<w;k++) {
			grid[k][j].x = tmpReal->GetPixelIndex(k,j)-128;
			grid[k][j].y = tmpImag->GetPixelIndex(k,j)-128;
		}
	}

	//DFT buffers
	double *real2,*imag2;
	real2 = (double*)malloc(max(w,h) * sizeof(double));
	imag2 = (double*)malloc(max(w,h) * sizeof(double));

	/* Transform the rows */
	real = (double *)malloc(w * sizeof(double));
	imag = (double *)malloc(w * sizeof(double));

	m=0;
	while((1<<m)<w) m++;

	for (j=0;j<h;j++) {
		for (k=0;k<w;k++) {
			real[k] = grid[k][j].x;
			imag[k] = grid[k][j].y;
		}

		if (bXpow2) FFT(direction,m,real,imag);
		else		DFT(direction,w,real,imag,real2,imag2);

		for (k=0;k<w;k++) {
			grid[k][j].x = real[k];
			grid[k][j].y = imag[k];
		}
	}
	free(real);
	free(imag);

	/* Transform the columns */
	real = (double *)malloc(h * sizeof(double));
	imag = (double *)malloc(h * sizeof(double));

	m=0;
	while((1<<m)<h) m++;

	for (k=0;k<w;k++) {
		for (j=0;j<h;j++) {
			real[j] = grid[k][j].x;
			imag[j] = grid[k][j].y;
		}

		if (bYpow2) FFT(direction,m,real,imag);
		else		DFT(direction,h,real,imag,real2,imag2);

		for (j=0;j<h;j++) {
			grid[k][j].x = real[j];
			grid[k][j].y = imag[j];
		}
	}
	free(real);
	free(imag);

	free(real2);
	free(imag2);

	/* converting from double to byte, there is a HUGE loss in the dynamics
	  "nn" tries to keep an acceptable SNR, but 8bit=48dB: don't ask more */
	double nn=pow((double)2,(double)log((double)max(w,h))/(double)log((double)2)-4);
	//reversed gain for reversed transform
	if (direction==-1) nn=1/nn;
	//bMagnitude : just to see it on the screen
	if (bMagnitude) nn*=4;

	for (j=0;j<h;j++) {
		for (k=0;k<w;k++) {
			if (bMagnitude){
				tmpReal->SetPixelIndex(k,j,(BYTE)max(0,min(255,(nn*(3+log(_cabs(grid[k][j])))))));
				if (grid[k][j].x==0){
					tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128+(atan(grid[k][j].y/0.0000000001)*nn)))));
				} else {
					tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128+(atan(grid[k][j].y/grid[k][j].x)*nn)))));
				}
			} else {
				tmpReal->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128 + grid[k][j].x*nn))));
				tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128 + grid[k][j].y*nn))));
			}
		}
	}

	for (k=0;k<w;k++) free (grid[k]);
	free (grid);

	if (srcReal==0 && dstReal==0) delete tmpReal;
	if (srcImag==0 && dstImag==0) delete tmpImag;

	return true;
}

Commentaires et avis

signaler à un administrateur
Commentaire de mekhea le 26/02/2008 18:52:07

le code soutrce incomplet

Ajouter un commentaire



Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,374 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.