最详细的图像傅里叶变换

1. 傅里叶变换理论层面理解

数学意义:傅里叶变换将一个任意的周期函数分解成为无穷个正弦函数的和的形式
物理效果:傅里叶变换实现了将信号从空间域到频率域的转换
信号分析: 一维傅里叶变换(将杂乱的信号由时域转化到频域中)一维傅里叶变化是将信号分解为正弦波的和的形式

时域
横轴是时间,纵轴是振幅
在这里插入图片描述

频域
横轴是频率,纵轴是振幅
在这里插入图片描述
对一个信号做时域到频域的变换,能够清除看到该信号主要由两个正弦波以及一些噪声混合,如下图所示:

在这里插入图片描述
将有效的信号频率提取并分离拟合出信号信息,然后将噪声过滤掉,得到滤波结果
在这里插入图片描述
频谱图: 二维傅里叶变换 (原图中的像素值是x,y坐标轴下的(即空间域),而傅立叶变换后的像素值是u,v坐标轴下的(即频域)),二维傅里叶变换可以将一个二维信号(图像)分解为三角平面波之和的形式
在这里插入图片描述

二维信号的离散傅里叶变换所得到的结果的频率成分的分布如下所示:
在经过频谱居中后的频谱中,中间最亮的点是最低频率,属于直流分量(DC分量)。越往边外走,频率越高。所以,频谱图中的四个角和X,Y轴的尽头都是高频(未经过频谱居中的相反)
在这里插入图片描述
二维离散傅里叶变换的作用:可以将空间域(二维灰度数表)的图像转换到频域(频率数表),使得更直观地观察和处理图像,也更有利于进行频域滤波等操作。

一副图像(不论是灰度的图像还是彩色图像)所提供的信息都是显而易见的(排除一些本身就很抽象的图片,不搞艺术哈哈哈)。然而,一副图像的傅里叶频谱图,却常常让人难以理解,满脸问号,一脸蒙B。

2. 常见频谱图

单色图
只有一种颜色
在这里插入图片描述

正弦波
在这里插入图片描述
分析:频率越低对称的频点越靠近频谱中心,随着频率增加远离中心(因为中心是低频,两端为高频)

灰度变化
在这里插入图片描述
分析:图像灰度变化方向体现在频谱图的方向中

根据上面两个信息可以得到下面结果:
在这里插入图片描述
常见几何形状
在这里插入图片描述
分析:还是和上面讲解的一样,频谱图的绘制规律是朝着梯度变化的方向改变的

这边可以这样理解傅里叶变换:
第一种理解: 二维图像进行傅里叶变化得到的频谱图(图像梯度的分布图),当然频谱图上的各点与原图像各点并不存在一一对应关系,即使在不移频的情况下也不对应。傅里叶频谱图上看到的明亮不一的亮点,实际上图像上某一点的像素灰度值与它的邻域点差异的强弱,即梯度的大小,也即该点的频率的大小(也可以这么理解,低频部分指低梯度的点,高频部分指高梯度的点)。
另一种理解:图像二维频谱图通过对输入图像进行水平和竖直两个方向的所有扫描线的一维傅立叶变换进行叠加得到,用来表示输入图像的频率分布。
频谱图以图像的中心为圆心,圆的相位对应原图中频率分量的相位,半径对应频率高低。低频部分半径小,高频对应的半径较大,中心为直流分量(图像灰度的平均值),某点的灰度值对应该频率的能量高低。

3. 傅里叶变换在图像中的应用

Opencv中的傅里叶变换实现
实现步骤:

  • getOptimalDFTSize()函数得到DFT变换后结果的最优尺寸大小
  • 根据得到的尺寸大小,使用copyMakeBorder()函数填充图像,得到填充后的Mat
  • 根据新生成的Mat,使用merge()函数得到一个双通道的Mat,命名为planes
  • 使用dft()函数进行傅里叶变换,得到通道1为实部,通道2为虚部

实现代码如下所示:

image.convertTo(image, CV_32F);
	vector<Mat> channels;
	split(image, channels);  //分离RGB通道
	Mat image_B = channels[0];
	//选取最适合做fft的宽和高
	int m1 = getOptimalDFTSize(image_B.rows);
	int n1 = getOptimalDFTSize(image_B.cols);
	Mat padded;
	//填充
	copyMakeBorder(image_B, padded, 0, m1 - image_B.rows, 0, n1 - image_B.cols, BORDER_CONSTANT, Scalar::all(0));
	Mat planes[] = {
    
     Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };
	Mat complexI;
	merge(planes, 2, complexI);  //planes[0], planes[1]是实部和虚部

	dft(complexI, complexI, DFT_SCALE | DFT_COMPLEX_OUTPUT);
	split(complexI, planes);

	//定义幅度谱和相位谱
	Mat ph, mag, idft;
	phase(planes[0], planes[1], ph);
	magnitude(planes[0], planes[1], mag);  //由实部planes[0]和虚部planes[1]得到幅度谱mag和相位谱ph

	//重新排列傅里叶图像中的象限,使得原点位于图像中心
	int cx = mag.cols / 2;
	int cy = mag.rows / 2;
	Mat q0(mag, Rect(0, 0, cx, cy));       //左上角图像划定ROI区域
	Mat q1(mag, Rect(cx, 0, cx, cy));      //右上角图像
	Mat q2(mag, Rect(0, cy, cx, cy));      //左下角图像
	Mat q3(mag, Rect(cx, cy, cx, cy));     //右下角图像

	//变换左上角和右下角象限
	Mat tmp;
	q0.copyTo(tmp);
	q3.copyTo(q0);
	tmp.copyTo(q3);

	//变换右上角和左下角象限
	q1.copyTo(tmp);
	q2.copyTo(q1);
	tmp.copyTo(q2);

	imshow("mag", mag);

实现结果如下所示:
在这里插入图片描述
傅里叶逆变换:

//傅里叶逆变换
	polarToCart(mag, ph, planes[0], planes[1]);  //由幅度谱mag和相位谱ph恢复实部planes[0]和虚部planes[1]
	merge(planes, 2, idft);
	dft(idft, idft, DFT_INVERSE | DFT_REAL_OUTPUT);
	image_B = idft(Rect(0, 0, image.cols & -2, image.rows & -2));
	image_B.copyTo(channels[0]);

	merge(channels, image);
	image.convertTo(image, CV_8U);

傅里叶逆变换实现结果:
在这里插入图片描述
低通滤波
实现机制:将高频的信号舍去;(通低频,阻高频)

	//低通滤波
 	for (int i = 0; i < mag.cols; i++){
    
    
 		for (int j = 0; j < mag.rows; j++){
    
    
 			if (abs(i - mag.cols / 2) > mag.cols / 10 || abs(j - mag.rows / 2) > mag.rows / 10)
 				mag.at<float>(j, i) = 0;
 		}
 	}

低通滤波实现结果:
在这里插入图片描述
高通滤波
实现机制:将低频的信号舍去;(通高频,阻低频)

	//高通滤波
 	for (int i = 0; i < mag.cols; i++){
    
    
 		for (int j = 0; j < mag.rows; j++){
    
    
 			if (abs(i - mag.cols / 2) < mag.cols / 30 && abs(j - mag.rows / 2) < mag.rows / 30)
 				mag.at<float>(j, i) = 0;
 		}
 	}

高通滤波实现结果
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44478077/article/details/124567210