OpenCV cvDFT 傅里叶变换

来源:互联网 发布:吉力贝怪味糖 知乎 编辑:程序博客网 时间:2024/05/21 09:36
#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 partimage_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 + MagcvLog( image_Re, image_Re ); // log(1 + Mag)//Rearrange the quadrants of Fourier image so that the origin is at the image centernRow = src->height;nCol = src->width;cy = nRow/2; // image centercx = 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)]*255double minVal = 0, maxVal = 0;// Localize minimum and maximum valuescvMinMaxLoc( image_Re, &minVal, &maxVal );// Normalize image (0 - 255) to be observed as an u8 imagescale = 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);//复数通道的灰度值设为0cvZero(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

0 0