傅里叶变换难理解,做了个实验理解傅里叶变换。
具体过程如下:
1)建一个Mat,对于是按照固定频率 横向(沿行)正弦变化图像。
# include <opencv2/core/core.hpp>
# include <opencv2/highgui/highgui.hpp>
# include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include "math.h"
using namespace cv;
using namespace std;
//构造 一副 黑白间隔图像。灰度值按照正弦规律,以列数为输入变量。
cv::Mat blackWhiteTrip = cv::Mat::zeros(96,256,CV_8UC1);
for( int j =0;j< blackWhiteTrip.rows;j++)
{
for(int i=0;i<blackWhiteTrip.cols;i++)
{
double theta;
theta =3.1415926;
theta = theta*2*i/ blackWhiteTrip.cols*16;
theta = sin(theta)/2*255+128;
blackWhiteTrip.at<uchar>(j,i)= uchar(theta);
}
}
imshow("blackWhiteTrip", blackWhiteTrip);
结果图:
2)调用OPENCV的函数 cv::dft(…),可以逐行(对应一维数组)做傅里叶变换。
cv::Mat DFT_1D(cv::Mat srcImage)//输入灰度值Mat,计算傅里叶变换 幅值对数值
{
cv::Mat SignalMat;
srcImage.copyTo(SignalMat);
// 为傅立叶变换的结果(实部和虚部)分配存储空间
cv::Mat planes[] = { cv::Mat_<float>(SignalMat),
cv::Mat::zeros(SignalMat.size(), CV_32F)};
Mat completeI;
// 为延扩后的图像增添一个初始化为0的通道
merge(planes,2,completeI);
// 进行离散傅立叶变换
dft(completeI,completeI);
// 将复数转换为幅度
split(completeI,planes);
cv::magnitude(planes[0],planes[1],planes[0]);//计算复数的向量值(幅值)
cv::Mat dftResultImage = planes[0]; //幅值
// 对数尺度(logarithmic scale)缩放
dftResultImage += 1;
log(dftResultImage,dftResultImage);
//cout<<dftResultImage;
return dftResultImage;
}
3)将输入图像转为灰度图,逐行做傅里叶变换。
cv::Mat srcGray;
//cvtColor(srcImage,srcGray,CV_RGB2GRAY);
blackWhiteTrip.copyTo(srcGray);// 第一步 代码产生的特殊图像
//srcGray = srcGray.t();// 矩阵转置操作
imshow("srcImage", srcGray);
static int channels = srcGray.channels();
static int types = srcGray.type();
//数组转Mat
cv::Mat resultImg = cv::Mat::zeros(srcGray.rows,srcGray.cols, CV_32FC1) ;//放傅里叶幅值结果
for(int i = 0;i<srcGray.rows;i++)
{
// 提取1维向量作 傅里叶变换
cv::Mat SM = cv::Mat::zeros(1,srcGray.cols, CV_8UC1) ;//定义一个 行向量
for(int j=0;j<srcGray.cols;j++)
{
SM.at<uchar>(0,j)= srcGray.at<uchar>(i,j);//取行向量
}
cv::Mat tempImage;
tempImage = DFT_1D( SM);//该行向量做傅里叶变换,调用第二步函数
for(int j=0;j<srcGray.cols;j++)
{
resultImg.at<float>(i,j) = tempImage.at<float>(0,j);//按行存储 傅里叶变换结果
}
}
cv::normalize(resultImg,resultImg,0,1,CV_MINMAX);// 归一化处理
结果如图: