点击链接→【数字图像处理】简单实践汇总
原图进行傅里叶变换,用频域图片还原原图:
1. 自制调用接口
- HILPF 理想低通
- HIHPF 理想高通
- HBLPF 巴特沃斯低通
- HBHPF 巴特沃斯高通
- HGLPF 高斯低通
- HGHPF 高斯高通
//理想
my_DFT(srcImage, "D_理想低D=5", "iD_理想低D=5", HILPF, D_2(5));
my_DFT(srcImage, "D_理想低D=50", "iD_理想低D=50", HILPF, D_2(50));
my_DFT(srcImage, "D_理想低D=150", "iD_理想低D=150", HILPF, D_2(150));
my_DFT(srcImage, "D_理想高D=5", "iD_理想高D=5", HIHPF, D_2(5));
my_DFT(srcImage, "D_理想高D=50", "iD_理想高D=50", HIHPF, D_2(50));
my_DFT(srcImage, "D_理想高D=150", "iD_理想高D=150", HIHPF, D_2(150));
//巴特沃斯
my_DFT(srcImage, "D_巴特低D=5", "iD_巴特低D=5", HBLPF, D_2(5));
my_DFT(srcImage, "D_巴特低D=50", "iD_巴特低D=50", HBLPF, D_2(50));
my_DFT(srcImage, "D_巴特低D=150", "iD_巴特低D=150", HBLPF, D_2(150));
my_DFT(srcImage, "D_巴特高D=5", "iD_巴特高D=5", HBHPF, D_2(5));
my_DFT(srcImage, "D_巴特高D=50", "iD_巴特高D=50", HBHPF, D_2(50));
my_DFT(srcImage, "D_巴特高D=150", "iD_巴特高D=150", HBHPF, D_2(150));
//高斯
my_DFT(srcImage, "D_高斯低D=5", "iD_高斯低D=5", HGLPF, D_2(5));
my_DFT(srcImage, "D_高斯低D=50", "iD_高斯低D=50", HGLPF, D_2(50));
my_DFT(srcImage, "D_高斯低D=150", "iD_高斯低D=150", HGLPF, D_2(150));
my_DFT(srcImage, "D_高斯高D=5", "iD_高斯高D=5", HGHPF, D_2(5));
my_DFT(srcImage, "D_高斯高D=50", "iD_高斯高D=50", HGHPF, D_2(50));
my_DFT(srcImage, "D_高斯高D=150", "iD_高斯高D=150", HGHPF, D_2(150));
效果图在最后!
2. 傅里叶变换接口
- 第二个参数:D指的是DFT傅里叶变换后频域效果图的窗口名;
- 第三个参数:iD指的是iDFT傅里叶逆变换后空间域,处理效果图的窗口名;
- 第四个参数:这个函数分别调用理想、巴特沃斯、高斯;
- 第五个参数:不同的截止频率,高通、低通,都可以,这里用的5,50,150;
void my_DFT(Mat srcImage, string window_name1, string window_name2, double fun(int, int, int), double d0_2)
{
Mat src = srcImage.clone();
//dft
int r = getOptimalDFTSize(src.rows);
int c = getOptimalDFTSize(src.cols);
Mat padded;
copyMakeBorder(src, padded, 0, r - src.rows, 0, c - src.cols, BORDER_CONSTANT, Scalar::all(0));
Mat dst1[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };
Mat dst2;
merge(dst1, 2, dst2);
dft(dst2, dst2);
split(dst2, dst1);
//copy the REAL and log it
Mat dst_0 = dst1[0].clone();
magnitude(dst_0, dst1[1], dst_0);
dst_0 = dst_0(Rect(0, 0, dst_0.cols & -2, dst_0.rows & -2));
log(dst_0, dst_0);
normalize(dst_0, dst_0, 0, 1, NORM_MINMAX);
//exchange
my_exchange(dst_0);
my_exchange(dst1[0]);
my_exchange(dst1[1]);
//smooth & sharp
for (int i = 0; i < src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
dst_0.at<float>(i, j) = dst_0.at<float>(i, j) * fun(i, j, d0_2);
dst1[0].at<float>(i, j) = dst1[0].at<float>(i, j) * fun(i, j, d0_2);
dst1[1].at<float>(i, j) = dst1[1].at<float>(i, j) * fun(i, j, d0_2);
}
}
imshow(window_name1, dst_0);
//exchange
my_exchange(dst1[0]);
my_exchange(dst1[1]);
//idft
merge(dst1, 2, dst2);
Mat complexim = dst2.clone();
Mat iDft[] = { Mat::zeros(dst1[0].size(),CV_32F),Mat::zeros(dst1[0].size(),CV_32F) };
idft(complexim, complexim);
split(complexim, iDft);
magnitude(iDft[0], iDft[1], iDft[0]);
normalize(iDft[0], iDft[0], 1, 0, NORM_MINMAX);
imshow(window_name2, iDft[0]);
}
3. 其他接口
注意: 傅里叶变换可以不用对角线交换,在空域填个负号可以有一样的效果,但是如果这样的话,还原的时候就会出问题,所以选择交换。这里也花了不少时间才调试对的。
void my_exchange(Mat& src)
{
int cx = src.cols / 2;
int cy = src.rows / 2;
Mat temp;
Mat part1(src, Rect(0, 0, cx, cy));
Mat part2(src, Rect(cx, 0, cx, cy));
Mat part3(src, Rect(0, cy, cx, cy));
Mat part4(src, Rect(cx, cy, cx, cy));
part1.copyTo(temp);
part4.copyTo(part1);
temp.copyTo(part4);
part2.copyTo(temp);
part3.copyTo(part2);
temp.copyTo(part3);
}
//return D_2
double D_2(int d)
{
return d * d;
}
理想低通,高通
//HILPF
double HILPF(int u, int v, int d0_2)
{
if (D_square(u, v) <= d0_2)
{
return 1;
}
else
{
return 0;
}
}
//HIHPF
double HIHPF(int u, int v, int d0_2)
{
return 1 - HILPF(u, v, d0_2);
}
巴特沃斯低通,高通
//HBLPF
double HBLPF(int u, int v, int d0_2)
{
return 1 / (1 + D_square(u, v) / d0_2);
}
//HBHPF
double HBHPF(int u, int v, int d0_2)
{
return 1 - HBLPF(u, v, d0_2);
}
高斯低通,高通
//HGLPF
double HGLPF(int u, int v, int d0_2)
{
return pow(exp(1), -0.5 * D_square(u, v) / d0_2);
}
//HGHPF
double HGHPF(int u, int v, int d0_2)
{
return 1 - HGLPF(u, v, d0_2);
}
4. 效果展示
-
HILPF 理想低通
-
HIHPF 理想高通
-
HBLPF 巴特沃斯低通
- HBHPF 巴特沃斯高通
- HGLPF 高斯低通
- HGHPF 高斯高通