#include<cv.h> #include<highgui.h> #include<stdio.h> void fft2shift(IplImage *src, IplImage *dst) { IplImage *image_Re = 0, *image_Im = 0; int nRow, nCol, i, j, cy, cx; double scale, shift, tmp13, tmp24; image_Re = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 1); //Imaginary part image_Im = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 1); cvSplit( src, image_Re, image_Im, 0, 0 ); //具体原理见冈萨雷斯数字图像处理p123 // 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); cvPow( image_Re, image_Re, 0.5 ); //对数变换以增强灰度级细节(这种变换使以窄带低灰度输入图像值映射 //一宽带输出值,具体可见冈萨雷斯数字图像处理p62) // Compute log(1 + Mag); cvAddS( image_Re, cvScalar(1.0), image_Re ); // 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 nRow = src->height; nCol = src->width; cy = nRow/2; // image center cx = nCol/2; //CV_IMAGE_ELEM为OpenCV定义的宏,用来读取图像的像素值,这一部分就是进行中心变换 for( j = 0; j < cy; j++ ){ for( i = 0; i < cx; i++ ){ //中心化,将整体份成四块进行对角交换 tmp13 = CV_IMAGE_ELEM( image_Re, double, j, i); CV_IMAGE_ELEM( image_Re, double, j, i) = CV_IMAGE_ELEM( image_Re, double, j+cy, i+cx); CV_IMAGE_ELEM( image_Re, double, j+cy, i+cx) = tmp13; tmp24 = CV_IMAGE_ELEM( image_Re, double, j, i+cx); CV_IMAGE_ELEM( image_Re, double, j, i+cx) = CV_IMAGE_ELEM( image_Re, double, j+cy, i); CV_IMAGE_ELEM( image_Re, double, j+cy, i) = tmp24; } } //归一化处理将矩阵的元素值归一为[0,255] //[(f(x,y)-minVal)/(maxVal-minVal)]*255 double minVal = 0, maxVal = 0; // Localize minimum and maximum values cvMinMaxLoc( image_Re, &minVal, &maxVal ); // Normalize image (0 - 255) to be observed as an u8 image scale = 255/(maxVal - minVal); shift = -minVal * scale; cvConvertScale(image_Re, dst, scale, shift); cvReleaseImage(&image_Re); cvReleaseImage(&image_Im); } int main(int argc, char* argv[]) { IplImage *src ,*dst,*Invdst,*temp,*Im = 0,*Re,*FourierImage; temp = cvLoadImage("C:\\Users\\Lonely\\Desktop\\lena.jpg",0); //显示原图像 cvNamedWindow("待变换图像",0); cvShowImage("待变换图像",temp); dst = cvCreateImage(cvGetSize(temp),temp->depth,1); FourierImage = cvCreateImage(cvGetSize(temp),temp->depth,1); Invdst = cvCreateImage(cvGetSize(temp),temp->depth,1); src = cvCreateImage(cvGetSize(temp),IPL_DEPTH_64F,2); Im = cvCreateImage(cvGetSize(temp),IPL_DEPTH_64F,1); Re = cvCreateImage(cvGetSize(temp),IPL_DEPTH_64F,1); //利用cvConcertScale转换数据类型 cvConvertScale(temp,Re); //复数通道的灰度值设为0 cvZero(Im); //傅里叶变换在复数域,在opencv中表示为二通道 cvMerge(Re,Im,NULL,NULL,src); IplImage *Fourier = cvCreateImage(cvGetSize(temp),IPL_DEPTH_64F,2); IplImage *InvFourier = cvCreateImage(cvGetSize(temp),IPL_DEPTH_64F,2); //傅里叶变换 cvDFT(src,Fourier,CV_DXT_FORWARD); cvDFT(Fourier,InvFourier,CV_DXT_INV_SCALE); cvSplit(Fourier,Re,Im,NULL,NULL); //利用cvConcertScale转换数据类型 cvConvertScale(Re,dst); //显示傅里叶变换图像 cvNamedWindow("傅里叶变换图像",0); cvShowImage("傅里叶变换图像",dst); //中心化 fft2shift(Fourier,FourierImage); cvNamedWindow("中心化傅里叶变换图像",0); cvShowImage("中心化傅里叶变换图像",FourierImage); cvSplit(InvFourier,Re,Im,NULL,NULL); //利用cvConcertScale转换数据类型 cvConvertScale(Re,Invdst); //显示傅里叶逆变换图像 cvNamedWindow("傅里叶逆变换图像",0); cvShowImage("傅里叶逆变换图像",Invdst); cvWaitKey(0); //释放内存 cvReleaseImage(&src); cvReleaseImage(&dst); cvReleaseImage(&Invdst); cvReleaseImage(&temp); cvReleaseImage(&Im); cvReleaseImage(&Re); cvReleaseImage(&Fourier); cvReleaseImage(&InvFourier); cvDestroyAllWindows(); }
fft2shift来自http://blog.csdn.net/abcjennifer/article/details/7359952
OpenCV版本:2.4.4