OpenCV 第六章 DFT IDFT

来源:互联网 发布:抢票软件 知乎 编辑:程序博客网 时间:2024/06/05 17:24

chap 6     DFT  and IDFT

(一)最简单的方法:

#include<opencv2/opencv.hpp>// chap 6 DFT and IDFTvoid main(){IplImage* src=cvLoadImage("D:\\lxlx\\one.jpg",0);// src 8UC1IplImage* temp=cvCreateImage(cvGetSize(src),8,1);    // 中间变量,用于显示图像CvMat* srcMat=cvCreateMat(src->height,src->width,CV_64FC1);cvConvert(src,srcMat);// 类型转换:图像指针转矩阵cvDFT(srcMat,srcMat,CV_DXT_FORWARD);// DFTcvConvert(srcMat,temp);// 将矩阵转换为图像,方便显示DFT结果cvNamedWindow("DFT");cvShowImage("DFT",temp);cvZero(temp);// 清零,方便下次使用cvDFT(srcMat,srcMat,CV_DXT_INV_SCALE); // IDFTcvConvert(srcMat,temp);// 将 IDFT 结果矩阵转换为图像指针cvNamedWindow("IDFT");cvShowImage("IDFT",temp);// IDFTcvWaitKey(0);}
运行结果:DFT 显示结果类似纹理图像;IDFT 显示原图。

这是由于并没有像冈萨雷斯里那样进行频谱的搬移:将亮度集中于中心。


(二)教材中的方法

此处,还要感谢 彭同学。

#include<opencv2/opencv.hpp>// chap 6 DFT and IDFTvoid main(){IplImage* src=cvLoadImage("D:\\lxlx\\one.jpg",0);// src 8UC1cvNamedWindow("src");cvShowImage("src",src);IplImage* Fourier=cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,2); // Fourier 64FC2IplImage* dst=cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,2); // dst 64FC2IplImage* imgRe=cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,1); // imgRe 64FC1IplImage* imgIm=cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,1); // imgIm 64FC1IplImage* imgDst=cvCreateImage(cvGetSize(src),8,1);   // img 8UC1cvConvertScale(src,imgRe,1.0,0); // 转换实部 8UC1 - 64FC1cvZero(imgIm);// 清零虚部cvMerge(imgRe,imgIm,0,0,Fourier);  //  Fourier 64FC2cvDFT(Fourier,dst,CV_DXT_FORWARD);// DFT 变换,结果为 dstcvSplit(dst,imgRe,imgIm,0,0);cvNamedWindow("DFT");cvShowImage("DFT",imgRe);  // DFT 实部//------------ IDFT -------------//cvZero(Fourier);cvZero(imgRe);cvZero(imgIm);cvDFT(dst,Fourier,CV_DXT_INV_SCALE); // IDFTcvSplit(Fourier,imgRe,imgIm,0,0);cvPow(imgRe,imgRe,2.0);cvPow(imgIm,imgIm,2.0);cvAdd(imgRe,imgIm,imgRe,0);//  imgRe =pow( pow(imgRe,2)+pow(imgIm,2),0.5 )cvAddS(imgRe,cvScalar(1.0),imgRe,0);cvLog(imgRe,imgRe);      // imgRe=log( 1+ imgRe);double min=0;double max=0;cvMinMaxLoc(imgRe,&min,&max,0,0);// 为求缩放量做准备double scale=255/(max-min);double shift=-(1+min)*scale;   // shift 量 有点小问题cvConvertScale(imgRe,imgDst,scale,shift);cvNamedWindow("IDFT");cvShowImage("IDFT",imgDst);//printf("min=%f, max=%f, scale=%f, shift=%f\n",min,max,scale,shift);cvWaitKey(0);}
实部、虚部分别对应imgRe、imgIm,通过将图片src对应于实部,0为虚部,合并为2通道的Fourier。

Fourier 进行 DFT 变换,结果为 dst 。查看 DFT 结果,即为查看 dst 的实部。

为简化,此处也没进行频谱的搬移。


由 dst  进行 IDFT 变换时,根据 冈萨雷斯 提示,进行对比度拉伸。

imgRe = pow( pow(imgRe,2.0) + pow(imgIm,2.0),  0.5  );

imgRe = log( 1+ imgRe );

正是由于进行了对比度的拉伸,在 IDFT 进行缩放时(对应于程序中的cvConvertScale() ),

偏移量 shift 的计算出现了分歧。

(具体 shift 公式,我暂时没搞明白)

(1)该imgRe图像整体偏亮, 则shift 偏小(如由 -20 调到 -40)

(2)该imgRe图像整体偏暗,则shift 偏大(如由 -40 调到 -20)