【OpenCV学习】DFT变换
作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/
- #include "cv.h"
- #include "highgui.h"
- #include "cxcore.h"
- void cvShiftDFT(CvArr *src_arr,CvArr *dst_arr)
- {
- CvMat * tmp;
- CvMat q1stub,q2stub;
- CvMat q3stub,q4stub;
- CvMat d1stub,d2stub;
- CvMat d3stub,d4stub;
- CvMat *q1,*q2,*q3,*q4;
- CvMat *d1,*d2,*d3,*d4;
- CvSize size = cvGetSize(src_arr);
- CvSize dst_size = cvGetSize(dst_arr);
- int cx,cy;
- if ((dst_size.width!= size.width)||(dst_size.height!=size.height))
- {
- cvError(CV_StsUnmatchedSizes,"cvShiftDFT",
- "Source and Destination arrays must have the same sizes",
- __FILE__,__LINE__);
- }
- if (src_arr == dst_arr)
- {
- tmp = cvCreateMat(size.height/2,size.width/2,cvGetElemType(src_arr));
- }
- cx=size.width/2;//取出图像的原点
- cy=size.height/2;
- q1=cvGetSubRect(src_arr,&q1stub,cvRect(0,0,cx,cy));
- //取出图像的第一象限,由q1指针指向它
- q2=cvGetSubRect(src_arr,&q2stub,cvRect(cx,0,cx,cy));
- //取出图像的第二象限,由q2指针指向它
- q3=cvGetSubRect(src_arr,&q3stub,cvRect(cx,cy,cx,cy));
- //取出图像的第三象限,由q3指针指向它
- q4=cvGetSubRect(src_arr,&q4stub,cvRect(0,cy,cx,cy));
- //取出图像的第四象限,由q4指针指向它
- d1=cvGetSubRect(src_arr,&d1stub,cvRect(0,0,cx,cy));
- d2=cvGetSubRect(src_arr,&d2stub,cvRect(cx,0,cx,cy));
- d3=cvGetSubRect(src_arr,&d3stub,cvRect(cy,cy,cx,cy));
- d4=cvGetSubRect(src_arr,&d4stub,cvRect(0,cy,cx,cy));
- if (src_arr!=dst_arr)
- {
- if (!CV_ARE_TYPES_EQ(q1,d1))
- {
- cvError(CV_StsUnmatchedSizes,"cvShiftDFT",
- "Source and Destination arrays must have the same sizes",
- __FILE__,__LINE__);
- }
- //以图像中心为原点,调整傅里叶变换图像的四个象限区,
- //即第一与第三象限交换,第二与第四象限交换
- cvCopy(q3,d1,0);
- cvCopy(q4,d2,0);
- cvCopy(q1,d3,0);
- cvCopy(q2,d4,0);
- }
- else
- {//若源矩阵和目的矩阵相同则直接在源矩阵中进行操作
- cvCopy(q3,tmp,0);
- cvCopy(q1,q3,0);
- cvCopy(tmp,q1,0);
- cvCopy(q4,tmp,0);
- cvCopy(q2,q4,0);
- cvCopy(tmp,q2,0);
- }
- }
- int main(int argc,char ** argv)
- {
- const char* filename =(argc>=2?argv[1]:"lena.jpg");
- IplImage *im;
- IplImage *realInput,*imaginaryInput,*complexInput;
- IplImage *image_Re,*image_Im;
- int dft_M,dft_N;
- CvMat *dft_A;
- CvMat tmp;
- double m,M;
- im = cvLoadImage(filename, CV_LOAD_IMAGE_GRAYSCALE );//加载图像
- if (!im)
- {
- return -1;
- }
- //分配空间
- realInput = cvCreateImage(cvGetSize(im),IPL_DEPTH_64F,1);//单通道
- imaginaryInput =cvCreateImage(cvGetSize(im),IPL_DEPTH_64F,1);//单通道
- complexInput = cvCreateImage(cvGetSize(im),IPL_DEPTH_64F,2);//双通道
- cvScale(im,realInput,1.0,0.0);
- //#define cvScale cvConvertScale=>readInput=im
- cvZero(imaginaryInput);
- //清空这个图像的内容
- cvMerge(realInput,imaginaryInput,NULL,NULL,complexInput);
- //混合这两个图像作为complexInput的两个通道
- /*得到最优DFT尺寸 */
- dft_M = cvGetOptimalDFTSize(im->height-1);
- dft_N = cvGetOptimalDFTSize(im->width-1);
- dft_A = cvCreateMat(dft_M,dft_N,CV_64FC2);
- image_Re = cvCreateImage(cvSize(dft_N,dft_M),IPL_DEPTH_64F,1);//实部
- image_Im = cvCreateImage(cvSize(dft_N,dft_M),IPL_DEPTH_64F,1);//虚部
- cvGetSubRect(dft_A,&tmp,cvRect(0,0,im->width,im->height));
- cvCopy(complexInput,&tmp,NULL);
- if( dft_A->cols > im->width )//若得到的最优DFT尺寸在宽度上大于原图,则重新取
- {
- cvGetSubRect(dft_A,&tmp,cvRect(im->width,0,dft_A->cols-im->width,im->height));
- cvZero(&tmp);
- }
- cvDFT(dft_A,dft_A,CV_DXT_FORWARD,complexInput->height);
- cvNamedWindow("win",0);
- cvNamedWindow("magnitude",0);
- cvShowImage("win",im);
- //分割出实部和虚部
- cvSplit(dft_A,image_Re,image_Im,0,0);
- //计算功率谱 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,NULL);//image_Re<=image_Re+image_Im
- cvPow(image_Re,image_Re,0.5);
- //计算log(1+Mag)
- cvAddS(image_Re,cvScalarAll(1.0),image_Re,NULL);
- cvLog(image_Re,image_Re);
- cvShiftDFT(image_Re,image_Re);
- cvMinMaxLoc(image_Re,&m,&M,NULL,NULL,NULL);
- cvScale(image_Re,image_Re,1.0/(M-m),1.0*(-m)/(M-m));
- cvShowImage("magnitude",image_Re);
- cvWaitKey(-1);
- return 0;
- }