OpenCV cvDFT 傅里叶变换

#include
#include
#include

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 cvDFT 傅里叶变换_第1张图片

OpenCV版本:2.4.4

你可能感兴趣的:(OpenCV)