opencv 图片的离散傅里叶变换DFT

时间:2023-02-07 12:15:03

copyMakeBorder(InuptArray src, OutputArray dst, int top , int bottom, int left, int right, int borderType, const Scalar&value=Scalar())  

该函数是用来扩展一个图像的边界

src: 源图像

dst: 目标图像,和源图像有相同的类型

top:表示在上边界扩展多少像素

bottom:表示在下边界扩展多少像素

left:表示在左边界扩展多少像素

right: 表示在右边界扩展多少像素

borderType: 边框类型

value: 当borderType==BORDER_CONSTANT时需要指定该值。

merge()函数是把多个但通道数组连接成1个多通道数组,而split()函数则相反,把1个多通道函数分解成多个但通道函数

#include<iostream>
#include<opencv2\opencv.hpp>
using namespace std;
using namespace cv;

int main(int argc, int **argv) {
Mat src, dst;
src = imread("F:\\img\\game02.jpg",0);
dst = Mat::zeros(src.size(), src.type());
if (!src.data) {
cout << "src image open failed !" << endl;
}
//得到扩展图像的最佳尺寸,当图像的尺寸为2,3,5的整数倍时,计算速度最快
int m = getOptimalDFTSize(src.rows);
int n = getOptimalDFTSize(src.cols);
Mat padded;
//对图像边界进行扩充
copyMakeBorder(src, padded, 0, m - src.rows, 0, n - src.cols, BORDER_CONSTANT, Scalar::all(0));
//为傅里叶变换结果(实部和虚部)分配存储空间
Mat plane[] = {Mat_<float>(padded),Mat::zeros(padded.size(),CV_32F)};
Mat complexI;
merge(plane, 2,complexI);
//傅里叶变换
dft(complexI, complexI);
//将复数转换为幅值
split(complexI,plane);
Mat magnitudeImg;
magnitude(plane[0],plane[1],plane[0]);
magnitudeImg = plane[0];
//进行对数尺度缩放
magnitudeImg += Scalar::all(1);
log(magnitudeImg, magnitudeImg);

//重新分布图像的象限
//若有奇数列或奇数行,进行频谱裁剪
magnitudeImg = magnitudeImg(Rect(0, 0, magnitudeImg.cols &-2, magnitudeImg.rows &-2));
//计算图像的中心
int cx = magnitudeImg.cols / 2;
int cy = magnitudeImg.rows / 2;

Mat p0(magnitudeImg,Rect(0, 0, cx, cy));//ROI左上
Mat p1(magnitudeImg,Rect(cx, 0, cx, cy));//ROI右上
Mat p2(magnitudeImg,Rect(0, cy, cx, cy));//ROI左下
Mat p3(magnitudeImg,Rect(cx, cy, cx, cy));//ROI右下

//左上和右下进行交换
Mat temp1;
p0.copyTo(temp1);
p3.copyTo(p0);
temp1.copyTo(p3);

//右上和左下进行交换
Mat temp2;
p1.copyTo(temp2);
p2.copyTo(p1);
temp2.copyTo(p2);
//归一化
normalize(magnitudeImg, magnitudeImg, 0, 1, NORM_MINMAX);
imshow("原图", src);
imshow("DFT幅值", magnitudeImg);
waitKey(0);

return 0;
}

结果:

opencv 图片的离散傅里叶变换DFT

opencv 图片的离散傅里叶变换DFT