转载一个描述(来理解傅里叶变换):
在频域里,对于一副图像,高频部分代表了图像的细节,纹理信息,;低频信息代表了图像的轮廓信息。如果对一个图像使用低通滤波器,那么滤波后就只剩下轮廓了。。
因此,傅里叶变换在图像处理中可以做到图像增强与图像去噪,图像分割之边缘检测、图像特征提取,图像压缩等。
效果图
C++版本
源码:
#include <iostream>
#include <opencv/cv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
//主函数
int main(void)
{
//读取原始图像
Mat srcImage=imread("/home/liuxin/桌面/opencv/dog.jpeg",0);//灰度
imshow("original",srcImage);
//将输入图像延扩至最佳尺寸,边界用0填充
int m=getOptimalDFTSize(srcImage.rows);
int n=getOptimalDFTSize(srcImage.cols);
Mat padded;//定义填充后的图像
copyMakeBorder(srcImage,padded,0,m-srcImage.rows,0,n-srcImage.cols,BORDER_CONSTANT,Scalar::all(0));
imshow("padded image",padded);
//为傅里叶变换的结果分配存储空间
Mat planes[]={Mat_<float>(padded),Mat::zeros(padded.size(),CV_32F)};
Mat complexI;//将planes数组组合合并成一个多通道的数组complexI
merge(planes,2,complexI);
//进行离散傅里叶变换
dft(complexI,complexI);
//将复数转换为幅值magitude
split(complexI,planes);//将多通道数组complexI分离为几个单通道数组,planes[0]=Re(DFT(I),planes[1]=Im(DFT(I)));re是实数,Im是复数吧
magnitude(planes[0],planes[1],planes[0]);
Mat magnitudeImage=planes[0];
//进行对数尺度缩放
magnitudeImage+=Scalar::all(1);
log(magnitudeImage,magnitudeImage);//求自然对数
//剪切和重分布幅度图象限(若有奇数行或奇数列,进行频谱裁剪)
magnitudeImage=magnitudeImage(Rect(0,0,magnitudeImage.cols&-2,magnitudeImage.rows&-2));
//重新排列傅里叶图像中的象限,使得原点位于图像中心
int cx=magnitudeImage.cols/2;
int cy=magnitudeImage.rows/2;
Mat q0(magnitudeImage,Rect(0,0,cx,cy));//ROI区域的左上
Mat q1(magnitudeImage,Rect(cx,0,cx,cy));//ROI区域的右上
Mat q2(magnitudeImage,Rect(0,cy,cx,cy));//ROI区域的左下
Mat q3(magnitudeImage,Rect(cx,cy,cx,cy));//ROI区域的左上
Mat tmp;//交换象限(左上与右下进行交换)
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
q1.copyTo(tmp);//右上与左下进行交换
q2.copyTo(q1);
tmp.copyTo(q2);
//归一化,用0到1之间的浮点值,将矩阵变幻为可视的图像格式
normalize(magnitudeImage,magnitudeImage,0,1,NORM_MINMAX);
imshow("MAGNITUDE",magnitudeImage);
while(1)
{
int key=cvWaitKey(10);
if (key==27)
{
break;
}
}
return(0);
}