OpenCV实现傅里叶变换

news/2024/7/6 1:51:01 标签: image, dst, fft, 图像处理, im, application
#include <stdio.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>


/**************************************************************************
//傅里叶变换
//src IPL_DEPTH_8U
//dst IPL_DEPTH_64F
/**************************************************************************/


void fft2(IplImage *src, IplImage *dst)
{  
	IplImage *image>image_Re = 0, *image>image_Im = 0, *Fourier = 0; //实部、虚部


	image>image_Re = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 1);  //实部


	image>image_Im = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 1);  //虚部


	Fourier = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 2);//2 channels (image>image_Re, image>image_Im)


	cvConvertScale(src, image>image_Re, 1, 0);// Real part conversion from u8 to 64f (double)


	cvZero(image>image_Im);// Imaginary part (zeros)


	cvMerge(image>image_Re, image>image_Im, 0, 0, Fourier);// Join real and imaginary parts and stock them in Fourier image>image


	cvDFT(Fourier, dst, CV_DXT_FORWARD);// Application of the forward Fourier transform


	cvReleaseImage(&image>image_Re);
	cvReleaseImage(&image>image_Im);
	cvReleaseImage(&Fourier);
}


/**************************************************************************
//中心化
//src IPL_DEPTH_64F
//dst IPL_DEPTH_8U
**************************************************************************/
void fft2shift(IplImage *src, IplImage *dst)
{
	IplImage *image>image_Re = 0, *image>image_Im = 0;
	int nRow, nCol, i, j, cy, cx;
	double scale, shift, tmp13, tmp24;


	image>image_Re = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 1);


	image>image_Im = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 1);
	cvSplit( src, image>image_Re, image>image_Im, 0, 0 );


	//具体原理见冈萨雷斯数字图像处理p123
	// Compute the magnitude of the spectrum Mag = sqrt(Re^2 + Im^2)
	//计算傅里叶谱
	cvPow( image>image_Re, image>image_Re, 2.0);
	cvPow( image>image_Im, image>image_Im, 2.0);
	cvAdd( image>image_Re, image>image_Im, image>image_Re);
	cvPow( image>image_Re, image>image_Re, 0.5 );


	//对数变换以增强灰度级细节(这种变换使以窄带低灰度输入图像值映射一宽带输出值,具体可见冈萨雷斯数字图像处理p62)
	// Compute log(1 + Mag);
	cvAddS( image>image_Re, cvScalar(1.0), image>image_Re ); // 1 + Mag
	cvLog( image>image_Re, image>image_Re ); // log(1 + Mag)


	//Rearrange the quadrants of Fourier image>image so that the origin is at the image>image center
	nRow = src->height; nCol = src->width;
	cx = nCol/2; cy = nRow/2; // image>image center


	//CV_IMAGE_ELEM为OpenCV定义的宏,用来读取图像的像素值,这一部分就是进行中心变换
	for( j = 0; j < cy; j++ ){
		for( i = 0; i < cx; i++ ){
			//中心化,将整体份成四块进行对角交换
			tmp13 = CV_IMAGE_ELEM( image>image_Re, double, j, i);
			CV_IMAGE_ELEM( image>image_Re, double, j, i) = CV_IMAGE_ELEM(image>image_Re, double, j+cy, i+cx);
			CV_IMAGE_ELEM( image>image_Re, double, j+cy, i+cx) = tmp13;


			tmp24 = CV_IMAGE_ELEM( image>image_Re, double, j, i+cx);
			CV_IMAGE_ELEM( image>image_Re, double, j, i+cx) =CV_IMAGE_ELEM( image>image_Re, double, j+cy, i);
			CV_IMAGE_ELEM( image>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>image_Re, &minVal, &maxVal );
	// Normalize image>image (0 - 255) to be observed as an u8 image>image
	scale = 255/(maxVal - minVal);
	shift = -minVal * scale;
	cvConvertScale(image>image_Re, dst, scale, shift);
	cvReleaseImage(&image>image_Re);
	cvReleaseImage(&image>image_Im);


}


/***********************************************************************/
int main()
{
	IplImage *src;          //源图像
	IplImage *Fourier;   //傅里叶系数
	IplImage *dst ;


	IplImage *ImageRe;
	IplImage *ImageIm;


	IplImage *Image;
	IplImage *ImageDst;


	double m,M;
	double scale;
	double shift;
	src = cvLoadImage("C:\\Users\\freeboy1015\\Desktop\\学习资料\\例图\\lena.jpg",0);   //加载源图像,第二个参数表示将输入的图片转为单信道 
	Fourier = cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,2);
	dst = cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,2);
	ImageRe = cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,1);
	ImageIm = cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,1);
	Image = cvCreateImage(cvGetSize(src),src->depth,src->nChannels);
	ImageDst = cvCreateImage(cvGetSize(src),src->depth,src->nChannels);
	fft2(src,Fourier);                  //傅里叶变换
	fft2shift(Fourier, Image);          //中心化
	cvDFT(Fourier,dst,CV_DXT_INV_SCALE);//实现傅里叶逆变换,并对结果进行缩放
	cvSplit(dst,ImageRe,ImageIm,0,0);


	cvNamedWindow("源图像",0);
	cvShowImage("源图像",src);             
	//对数组每个元素平方并存储在第二个参数中
	cvPow(ImageRe,ImageRe,2);               
	cvPow(ImageIm,ImageIm,2);
	cvAdd(ImageRe,ImageIm,ImageRe,NULL);
	cvPow(ImageRe,ImageRe,0.5);
	cvMinMaxLoc(ImageRe,&m,&M,NULL,NULL);
	scale = 255/(M - m);
	shift = -m * scale;
	//将shift加在ImageRe各元素按比例缩放的结果上,存储为ImageDst
	cvConvertScale(ImageRe,ImageDst,scale,shift);


	cvNamedWindow("傅里叶谱",0);
	cvShowImage("傅里叶谱",Image);
	cvNamedWindow("傅里叶逆变换",0);
	cvShowImage("傅里叶逆变换",ImageDst);


	cvWaitKey(0);


	cvReleaseImage(&src);
	cvReleaseImage(&Image);
	cvReleaseImage(&ImageIm);
	cvReleaseImage(&ImageRe);
	cvReleaseImage(&Fourier);
	cvReleaseImage(&dst);
	cvReleaseImage(&ImageDst);
        cvDestroyAllWindows();
	return 0;
}



http://www.niftyadmin.cn/n/790720.html

相关文章

【Visual C++】关于无法打开包括文件:“StdAfx.h”或者意外结尾的错误解决方案

最近有朋友在编译我提供的【Visual C】游戏开发某一节笔记的源代码的时候&#xff0c;提到出现 “fatal error C1083: 无法打开包括文件:“StdAfx.h”这个错误。这里我专门找了点资料&#xff0c;然后部分修改&#xff0c;写成了一篇博文发出来&#xff0c;希望能对出现这个问…

openCV平滑函数----cvSmooth

openCV平滑函数 [cpp] view plaincopyprint? void cvSmooth( const CvArr* src, CvArr* dst, int smooth CV_GAUSSIAN, int param1 3, int param2 0, int param3 0, int param4 0 ); 注解&#xff1a; (1)可能大家啊对CvA…

C++预编译头文件讲解

为什么所有的 cpp 都必须 #include "stdafx.h" 也许请教了别的高手之后&#xff0c;他们会告诉你&#xff0c;这是预编译头&#xff0c;必须包含。可是&#xff0c;这到底是为什么呢&#xff1f;预编译头有什么用呢&#xff1f; 这得从头文件的编译原理讲起。其实头文…

防止头文件重复包含引起的变量重复定义

test-1.0使用#ifndef只是防止了头文件被重复包含(其实本例中只有一个头件&#xff0c;不会存在重复包含的问题)&#xff0c;但是无法防止变量被重复定义。 # vi test.c-------------------------------#include <stdio.h>#include "test.h"extern i;extern voi…

C++函数对象与函数指针不同之处

在C编程语言中&#xff0c;有很多功能都与C语言相通&#xff0c;比如指针的应用等等。在这里我们介绍的则是一种类似于函数指针的C函数对象的相关介绍。C函数对象不是函数指针。但是&#xff0c;在程序代码中&#xff0c;它的调用方式与函数指针一样&#xff0c;后面加个括号就…

开闭架构

在《不过时的经典层架构》里&#xff0c;有朋友留言关于Manager和Engine的概念&#xff0c;虽然朋友留言把概念解释清楚了。为了避免其他人有同样的疑问&#xff0c;这里我还是再解释一下。 以上是经典的四层架构&#xff0c;在这个架构中&#xff0c;Manager和Engine(引擎)都是…

计算机视觉、图像处理学习资料汇总

一、研究群体 http://www-2.cs.cmu.edu/~cil/vision.html 这是卡奈基梅隆大学的计算机视觉研究组的主页&#xff0c;上面提供很全的资料&#xff0c;从发表文章的下载到演示程序、测试图像、常用链接、相关软硬件&#xff0c;甚至还有一个搜索引擎。 http://www.cmis.csiro.a…

揭开私有继承的面纱

什么是私有继承&#xff1f;以前在学校学习的时候&#xff0c;冥冥乎知道有这样一个东西&#xff0c;却没有仔细研究过。后来工作中用到Boost库才开始了解它。如果说保护继承大多是为了语言完整性的话&#xff0c;私有继承还是有一些用途的。 私有继承 vs 公有继承 公有继承继…