利用维纳滤波对运动模糊图像进行复原

一、概要
本文首先给出图像的维纳滤波器的推导过程用以补充书中缺失的证明,而后在C++的编译环境下,利用opencv构造维纳滤波器实现运动模糊图像的复原,并结合代码给出算法流程,最后在本文末给出全部代码。
二、图像的维纳滤波原理
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
三、构造退化函数
这部分冈萨雷斯所著的数字信号处理第三版已经给出了建模过程,因此这里直接引用书本上给出的运动模糊函数的推导过程。如下所示:
在这里插入图片描述
在这里插入图片描述
在这里应当注意:实际操作中往往会将图像的频谱中心化,因此进行图像模拟退化时所使用的退化函数也应当中心化。设原始图像大小为M·N,经过扩充后的大小为(2M)·(2N)。此时退化函数的尺寸也应当为(2M)·(2N),且退化函数应当改写成(中心化):
在这里插入图片描述
四、算法流程
1、对原始图像进行傅里叶变换,计算出原始图像f(x,y)的幅度谱和相位谱。即:
在这里插入图片描述
该部分代码如下所示:

	Mat src = imread("T.jpg");
	Mat gray_src;
	cvtColor(src, gray_src, CV_BGR2GRAY);
	Mat padded = Mat::zeros(2 * gray_src.rows, 2 * gray_src.cols, CV_32FC1);
	//图像扩充
	for (int row = 0; row < gray_src.rows; row++)
	{
   
		for (int col = 0; col < gray_src.cols; col++)
		{
   
			padded.at<float>(row, col) = gray_src.at<uchar>(row, col);
		}
	}
	//中心化
	for (int row = 0; row < padded.rows; row++)
	{
   
		for (int col = 0; col < padded.cols; col++)
		{
   
			padded.at<float>(row, col) *= pow(-1, row + col);
		}
	}
	//傅里叶变换
	Mat planes[] = {
    Mat_<float>(padded),Mat::zeros(padded.size(),CV_32FC1) };
	Mat complexImg;
	merge(planes, 2, complexImg);
	dft(complexImg, complexImg);
	//求原始图像的幅度谱和相位谱
	Mat temp1[] = {
    Mat_<float>(padded),Mat::zeros(padded.size(),CV_32FC1) };
	split(complexImg, temp1);
	Mat amplitude1, angle1;
	amplitude1 = Magnitude(temp1[0], temp1[1]);
	angle1 = Phase(temp1[0], temp1[1]);

2、构造退化函数h(x,y),并计算其幅度谱和相位谱,即:
在这里插入图片描述
该部分代码如下所示:

	//定义退化函数
	Mat degenerate[] = {
    Mat_<float>(padded),Mat::zeros(padded.size(),CV_32FC1) };
	for (int row = 0; row < degenerate[0].rows; row++)
	{
   
		for (int col = 0; col < degenerate[0].cols; col++)
		{
   
			float v = pi*(0.1*(row - 262) + 0.1*(col - 175));
			if (v == 0)
			{
   
				degenerate[0].at<float>(row, col) = 1;
				degenerate[1].at<float>(row, col) = 0;
			}
			else
			{
   
				degenerate[0].at<float>(row, col) = sin(v) / v*cos(v);
				degenerate[1].at<float>(row, col) = -sin(v) / v*sin(v);
			}
		}
	}
	//求退化函数的幅度谱和相位谱
	Mat amplitude2, angle2;
	amplitude2 = Magnitude(degenerate[0], degenerate[1]);
	angle2 = Phase(degenerate[0], degenerate[1]);

3、实现图像的退化
代码实现的原理为:
在这里插入图片描述
随后将上式分离出来的实部与虚部分别赋予两个通道,在这里是用photo[0]存储实部,photo[1]存储虚部。
代码如下所示:

	//图像退化
	Mat photo[] = {
    Mat_<float>(padded),Mat::zeros(padded.size(),CV_32FC1) };
	for (int row = 0; row < padded.rows; row++)
	{
   
		for (int col = 0; col < padded.cols; col++)
		{
   
			photo[0].at<float>(row, col) = amplitude1.at<float>(row, col)*amplitude2.at<float>(row, col)*cos(angle1.at<float>(row, col) + angle2.at<float>(row, col));
			photo[1].at<float>(row, col) = amplitude1.at<float>(row, col)*amplitude2.at<float>(row, col)*sin(angle1.at<float>(row, col) + angle2.at<float>(row, col));
		}
	}

4、得到运动模糊图像
以上都是在频域中进行操作,现将上一步得到的结果进行傅里叶逆变换,然后进行显示。运动模糊的效果如下:
在这里插入图片描述
该部分代码如下:

	//空域中显示退化图像
	Mat complex;
	merge(photo, 2, complex);
	idft(complex, complex);
	Mat temp2[] = {
    Mat_<float>(padded),Mat::zeros(padded.size(),CV_32FC1) };
	split(complex, temp2);
	for (int row = 0; row < temp2[0].rows; row++)
	{
   
		for (int col = 0; col < temp2[0].cols; col++)
		{
   
			temp2[0].at<float>(row, col) *= pow(-1, row + col);
		}
	}
	for (int row = 0; row < temp2[0].rows; row++)
	{
   
		
  • 17
    点赞
  • 116
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值