关于C++ FFT相关代码
这里是一些对应于MATLAB的OpenCV代码:
FFT2:
cv::Mat fft2(const cv::Mat &src)
{
using namespace cv;
using namespace std;
cv::Mat Fourier;
int mat_type = src.type();
assert(mat_type<15); //不支持的数据格式
if (mat_type < 7)
{
Mat planes[] = { Mat_<double>(src), Mat::zeros(src.size(),CV_64F) };
merge(planes, 2, Fourier);
dft(Fourier, Fourier);
}
else // 7<mat_type<15
{
Mat tmp;
dft(src, tmp);
vector<Mat> planes;
split(tmp, planes);
magnitude(planes[0], planes[1], planes[0]); //将复数转化为幅值
Fourier = planes[0];
}
return Fourier;
}
IFFT2
cv::Mat ifft2(const cv::Mat &src)
{
using namespace cv;
using namespace std;
cv::Mat Fourier;
int mat_type = src.type();
assert(mat_type<15); //不支持的数据格式
if (mat_type < 7)
{
Mat planes[] = { Mat_<double>(src), Mat::zeros(src.size(),CV_64F) };
merge(planes, 2, Fourier);
dft(Fourier, Fourier, DFT_INVERSE + DFT_SCALE, 0);
}
else // 7<mat_type<15
{
Mat tmp;
dft(src, tmp, DFT_INVERSE + DFT_SCALE, 0);
vector<Mat> planes;
split(tmp, planes);
//magnitude(planes[0], planes[1], planes[0]); //将复数转化为幅值
Fourier = planes[0];
}
return Fourier;
}
两个复数矩阵相乘
void divSpectrums(cv::InputArray _srcA, cv::InputArray _srcB, cv::OutputArray _dst, int flags, bool conjB);
conjB这个参数代表将b矩阵先计算复数共轭之后,再相乘
两个复数矩阵相除
void mulSpectrums(InputArray a, InputArray b, OutputArray c,
int flags, bool conjB = false);
circShift
static void circRowShift(cv::Mat &src, int shift_m_rows)
{
using namespace cv;
int m = shift_m_rows;
int rows = src.rows;
//‘行’循环移动
if (m%rows == 0)
{
return;
}
Mat mrows(abs(m), src.cols, src.type());//用于暂时保存末尾的m行数据
if (m>0)
{
src(Range(rows - m, rows), Range::all()).copyTo(mrows);
src(Range(0, rows - m), Range::all()).copyTo(src(Range(m, rows), Range::all()));
mrows.copyTo(src(Range(0, m), Range::all()));
}
else
{
src(Range(0, -m), Range::all()).copyTo(mrows);
src(Range(-m, rows), Range::all()).copyTo(src(Range(0, rows + m), Range::all()));
mrows.copyTo(src(Range(rows + m, rows), Range::all()));
}
}
static void circColShift(cv::Mat& src, int shift_n_cols)
{
using namespace cv;
int n = shift_n_cols;
int cols = src.cols;
int rows = src.rows;
if (n%cols == 0)
{
return;
}
///ncols,如果n>0,用于暂时保存末尾的n列数据
///ncols,如果n<0,用于暂时保存起始的n列数据
Mat ncols(rows, abs(n), src.type());
if (n>0)
{
src(Range::all(), Range(cols - n, cols)).copyTo(ncols);
src(Range::all(), Range(0, cols - n)).copyTo(src(Range::all(), Range(n, cols)));
ncols.copyTo(src(Range::all(), Range(0, n)));
}
else
{
src(Range::all(), Range(0, -n)).copyTo(ncols);
src(Range::all(), Range(-n, cols)).copyTo(src(Range::all(), Range(0, cols + n)));
ncols.copyTo(src(Range::all(), Range(cols + n, cols)));
}
}
void circShift(cv::Mat &src, int shift_m_rows, int shift_n_cols)
{
int m = shift_m_rows;
int n = shift_n_cols;
//‘行’循环移动
circRowShift(src, m);
//‘列’循环移动
circColShift(src, n);
}
复数乘实数
复数乘法
cv::Mat Complex_Mul(cv::Mat& input1, cv::Mat& input2)
{
using namespace cv;
//将二维矩阵input2复制成双通道的三维数据
cv::Mat repeated_input2(input2.size(), CV_64FC2);
cv::Mat planes[] = { input2, input2 };
cv::merge(planes, 2, repeated_input2);
//矩阵相乘
cv::Mat out = input1.mul(repeated_input2);
return out;
}