图像幅度谱与相位谱的代码演示,本例使用泰勒斯威夫特的图像作为图像素材。代码如下所示:
#include<iostream>
#include<opencv2/opencv.hpp>
#include<math.h>
using namespace std;
using namespace cv;
Mat Magnitude(Mat Re, Mat Im);
Mat Phase(Mat Re, Mat Im);
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));//中心化for (int row = 0; row < padded.rows; row++){for (int col = 0; col < padded.cols; col++){padded.at<uchar>(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);Mat amplitude = Magnitude(planes[0], planes[1]);amplitude += Scalar::all(1);log(amplitude, amplitude);normalize(amplitude, amplitude, 0, 1, NORM_MINMAX);imshow("幅度谱", amplitude);Mat angle = Phase(planes[0], planes[1]);normalize(angle, angle, 0, 1, NORM_MINMAX);imshow("angle", angle);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;
}
效果如下所示:
首先将彩色图像转换为灰度图像(单通道)
而后求得的幅度谱如下所示:
相位谱如下所示:
经验证,幅度谱与相位谱的计算结果与opencv提供的magnitude和phase这两个API的运算结果一致。