Matlab
中的 fftshift
函数将信号频谱的零频分量移动到数组中心. fftshift
函数的本质是分别对调一三象限, 二四象限的数据块.
OpenCV
中没有实现此函数, 以下是我个人编写的基于OpenCV
的fftshift
函数.
/**
* @brief 将零频分量移动到矩阵中心
*
* @param _src 源矩阵
* @param _dst 目标矩阵
*
* @note 源矩阵和目标矩阵相同时, 结果异常. 未找到原因
*/
void fftshift(cv::InputArray _src, cv::OutputArray _dst)
{
cv::Mat src = _src.getMat();
_dst.create(src.size(), src.type());
cv::Mat dst = _dst.getMat();
int x0 = src.cols / 2;
int x1 = src.cols - x0;
int y0 = src.rows / 2;
int y1 = src.rows - y0;
cv::Mat src_b0(src, cv::Rect(0, 0, x1, y1));
cv::Mat src_b1(src, cv::Rect(x1, 0, x0, y0));
cv::Mat src_b2(src, cv::Rect(0, y1, x0, y0));
cv::Mat src_b3(src, cv::Rect(x0, y0, x1, y1));
cv::Mat dst_b0(dst, cv::Rect(0, 0, x1, y1));
cv::Mat dst_b1(dst, cv::Rect(x1, 0, x0, y0));
cv::Mat dst_b2(dst, cv::Rect(0, y1, x0, y0));
cv::Mat dst_b3(dst, cv::Rect(x0, y0, x1, y1));
src_b1.copyTo(dst_b2);
src_b2.copyTo(dst_b1);
src_b0.copyTo(dst_b3);
src_b3.copyTo(dst_b0);
}
以下是示例程序:
void fftshift_test()
{
// (7,8)的全1矩阵
auto img = cv::Mat::ones(7, 8, CV_32FC1);
cv::Mat img_c2;
cv::merge(std::vector<cv::Mat>{img, cv::Mat::zeros(img.size(), CV_32FC1)}, img_c2);
cv::dft(img_c2, img_c2);
cv::Mat temp;
fftshift(img_c2, temp);
cv::Mat plane[2];
cv::split(temp, plane);
std::cout << plane[0];
}
测试结果如下图所示:
与matlab
的结果对比一致: