五、使用OpenCV实现:通过傅里叶变化平滑锐化(理想、巴特沃斯、高斯)

点击链接→【数字图像处理】简单实践汇总

原图进行傅里叶变换,用频域图片还原原图:

原图进行傅里叶变换,用频域图片还原原图

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 高斯高通

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_34451909/article/details/107610708