版权声明:本文为博主原创文章,转载请标明出处 https://blog.csdn.net/C2681595858/article/details/84487617
一、实验设计
1、滤波前的准备
- 进行傅里叶逆变换需要知道原复数的实部和虚部,但是傅里叶变换后的图像显示的是幅度谱,也就是说要从显示在屏幕上的频域图像直接变回空域是做不到的(因为不知道它的实部和虚部)。
- 所以为了能够进行傅里叶逆变换,我们必须保存傅里叶正向变换的中间值,就是实部和虚部分开存储的那个值。
- 但是直接用官方示例中的方法的话,是行不通的,因为他是先计算幅度谱,然后再移中的。但是我们进行高通或者低通滤波,更习惯使用移中后的图像(但是官方示例中移中后的图像已经没有实部虚部之说了),所以我们要先分别对实部和虚部进行移中,然后进行滤波。
- 函数设计:由于对实部和虚部进行移中的方法是相同的,但是需要用到两次,所以可以设计一个函数,直接传参调用即可。
- 为了让程序不那么混乱,我们在进行变换的时候始终遵循一个原则,就是一旦complexI被赋值,不在改变complexI的值。同时imat[2]从被赋值开始要保持已经移中,如果破坏了移中要及时换过来,直到它不再被使用。
2、函数设计
class FDF {
public:
/*
构造函数,可以直接传入文件名来创建
*/
FDF(string image_spa_in);
/*
如果创建对象时没有穿入文件名,可以后期设置文件名
*/
void setImage(string image_spa_in);
/*
*返回空域图像
每次滤波时不会保存上次滤波的结果
所以在每次滤波以后要及时调用该函数取得空域图像
*/
Mat getImageSpa();
/*
*返回频域图像
每次滤波时不会保存上次滤波的结果
所以在每次滤波以后要及时调用该函数取得频域图像
*/
Mat getImageFre();
/*
傅里叶变换,只需一开始调用一次,得到频域图像后结果会长期保存,无需多次调用
*/
void dft_();
/*
*傅里叶反变换
每次对图像滤波结束以后可以用它来得到滤波后空域的图像
*/
void idft_();
/*
*下面是几种低通滤波器
*/
void ILPF(float d0);
void BLPF(int n, float d0);
void GLPF(float d0);
/*
*拉普拉斯滤波器
*/
void Laplacian();
/*
*这个函数用来设置频域图像
*由于滤波操作是在复数(2通道Mat)上进行的,所以要显示频域图像的话首先要进行一些处理
*/
void setFreImg();//这个函数用来将各种滤波后的中间结果转变为频域图像存储在Image_fre中
/*
*添加噪音
*/
void addNoise();
private:
Mat image_spa;//存放原始空域图像
Mat complexI;//存放复数形式的图像
Mat imat[2];//这个是提供给各种滤波的,是将complexI分开并移中后的结果
Mat Image_fre;//存放滤波后频域的图像
void splitAndCenter();//将complexI分开并移中后的存储到imat2[]中
void center(Mat& imag);//移中
};
float dist(const float& a, const float& b, const float& c, const float& d);
二、实验过程
- 设计两个私有函数:
void center(Mat& imag);void splitAndCenter();
第一个负责将传进来的imag进行裁剪并移中,当然也可以用于在逆变换时取消移中。第二个负责将私有成员complexI进行分割并调用center进行移中,将结果存储在imat[2]中,方便后续进行的各种滤波操作。 void dft_();
进行傅里叶变换,同时将中间结果,就是傅里叶变换后还未进行分割的2通道形式的结果存储在私有变量complexI中,方便后续滤波操作。void idft_();
傅里叶逆变换,负责将imat[2]从频域转换到空域并将结果存储在私有变量image_spa中。- 其他的函数都是对应的滤波器,由于高通滤波和低通滤波刚好相反,所以只做了低通滤波,高通滤波制作了Laplacian滤波器。
三、结果分析
- 原始图像
- 理想低通滤波
- Butterworth滤波器
- Gaussian滤波器
- Laplacian滤波器
- 添加噪声