一、概要
图像经过傅里叶变换后,将图像在空域中的信息映射至频域空间中。图像的频域空间包含幅度谱以及相位谱,其中幅度谱反映的是图像的灰度信息,相位谱反应的是图像的位置信息,如轮廓。
本博文将基于傅里叶分析理论演示利用幅度谱与相位谱重构图像的过程,并验证幅度谱与相位谱在图像重构过程中的作用,最后在本文末给出全部代码。
二、图像的傅里叶变换及其可视化
首先将图像进行傅里叶变换得到图像的频谱并使其可视化。在这里应当注意傅里叶变换对是复数,因此需要构建双通道的Mat类存储复数的实部与虚部。
代码的主函数部分:
int main()
{
Mat src = imread("T.jpg");
Mat gray_src;
cvtColor(src, gray_src, CV_BGR2GRAY);
imshow("灰度化输入图像", gray_src);
int m = getOptimalDFTSize(gray_src.rows);
int n = getOptimalDFTSize(gray_src.cols);
Mat padded;
copyMakeBorder(gray_src, padded, 0, m - gray_src.rows, 0, n - gray_src.cols, BORDER_CONSTANT, Scalar::all(0));
padded.convertTo(padded, CV_32FC1);
//中心化
for (int row = 0; row < padded.rows; row++)
{
for (int col = 0; col < padded.cols; col++)
{
padded.at<float>(row, col) *= pow(-1, row + col);
}
}
Mat planes[] = {
Mat_<float>(padded),Mat::zeros(padded.size(),CV_32F) };
Mat complexI;
merge(planes, 2, complexI);
dft(complexI, complexI);
split(complexI, planes);
//显示幅度谱和相位谱
Show_Spectrum(planes[0], planes[1]);
//利用相位谱重构图像
Phase_Spectrum_Reconstruction(planes[0], planes[1]);
//利用幅度谱重构图像
Amplitude_Spectrum_Reconstruction(planes[0], planes[1]);
//利用幅度谱和相位谱重构图像
Amplitude_Phase_Spectrum_Reconstruction(planes[0], planes[1]);
waitKey(0);
system("pause");
return 0;
}
对图像求得傅里叶变换后,将图像的频谱可视化。该部分的子函数如下所示:
//根据幅度谱的定义计算傅里叶变换的幅度谱
Mat Magnitude(Mat Re, Mat Im)
{
Mat rst = Mat::zeros(Re.rows, Re.cols, CV_32F);
for (int row = 0; row < Re.rows; row++)
{
for (int col = 0; col < Re.cols; col++)
{
rst.at<float>(row, col) = sqrt(pow(Re.at<float>(row, col), 2) + pow(Im.at<float>(row, col), 2));
}
}
return rst;
}
//根据相位谱的定义计算傅里叶变换的相位谱
Mat Phase(Mat Re, Mat Im)
{
Mat rst = Mat::zeros(Re.rows, Re.cols, CV_32F);
for (int row = 0; row < Re.rows; row++)
{
for (int col = 0; col < Re.cols; col++)
{
rst.at<float>(row, col) = atan2(Im.at<float>(row, col), Re.at<float>(row, col));
}
}
return rst;
}
//显示图像的相位谱和幅度谱
void Show_Spectrum(Mat Re, Mat Im)
{
Mat amplitude = Magnitude(Re, Im);
Mat angle = Phase(Re, Im);
amplitude += Scalar::