图像去噪之自适应维纳滤波

全网讲自适应维纳滤波最清晰的?

基本原理

算法很简单,以下内容来自Matlab官网。
在这里插入图片描述

详细介绍

自适应维纳滤波

大多数去除加性噪声的自适应图像复原算法流程:
在这里插入图片描述

根据噪声图像和先验知识,我们能够使用一些基于滤波图像的局部细节方法。其中一个方法就是局部方差。随空间变化的滤波器h(n1,n2)是由图像局部信息和附加先验知识决定的函数。基于局部图像信息的特殊的方法改进了算法,空变滤波器h(n1,n2)是由图像局部信息和可获得的先验知识决定的函数。在9.2.1节讨论了一种自适应的维纳滤波器。
在这里插入图片描述
在这里插入图片描述

下面很重要,解释从9.26公式如何到Matlab的形式。
在这里插入图片描述

示例演示

我们用OpenCV实现该算法。头文件如下

#pragma once

#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc.hpp>

#include <assert.h>

/** @brief Implementation of the adaptive Wiener filter

This function applies to the src image the adaptive Wiener filter and 
store the result in the dst image. The formula that will be apply is 
the following one: 

dst(x, y) = u + max(0, s^2 - v^2)(src(x, y) - u) / max(s^2, v^2)

where u is the local mean, s^2 is the variance at NxM neighborhood
around each pixel (they depend on block dimension) e v^2 is the noise 
variance calculated as the average of all the local estimated variances
if not given.

@param[in] src input grayscale image (Mat1b)
@param[out] dst output grayscale image (Mat1b)
@param[in] block dimension of the block (width, height) to use in order
			to compute the filtering process, default is 5x5

@return estimated noise variance
*/
double WienerFilter(const cv::Mat& src, cv::Mat& dst, const cv::Size& block = cv::Size(5, 5));

/** @overload 

@param[in] src input grayscale image (Mat1b)
@param[out] dst output grayscale image (Mat1b)
@param[in] noiseVariance noise variance to use in order to calculate Wiener filter (must be positive)
@param[in] block dimension of the block (width, height) to use in order
			to compute the filtering process, default is 5x5

@return estimated noise variance
*/
void WienerFilter(const cv::Mat& src, cv::Mat& dst, double noiseVariance, const cv::Size& block = cv::Size(5, 5));

源文件如下

#include "WienerFilter.h"

using namespace cv;

double WienerFilterImpl(const Mat& src, Mat& dst, double noiseVariance, const Size& block){

	assert(("Invalid block dimensions", block.width % 2 == 1 && block.height % 2 == 1 && block.width > 1 && block.height > 1));
	assert(("src and dst must be one channel grayscale images", src.channels() == 1, dst.channels() == 1));
	
	int h = src.rows;
	int w = src.cols;

	dst = Mat1b(h, w);

	Mat1d means, sqrMeans, variances;
	Mat1d avgVarianceMat; 

	boxFilter(src, means, CV_64F, block, Point(-1, -1), true, BORDER_REPLICATE);
	sqrBoxFilter(src, sqrMeans, CV_64F, block, Point(-1, -1), true, BORDER_REPLICATE);

	Mat1d means2 = means.mul(means);
	variances = sqrMeans - (means.mul(means));

	if (noiseVariance < 0){
		// I have to estimate the noiseVariance
		reduce(variances, avgVarianceMat, 1, REDUCE_SUM, -1);
		reduce(avgVarianceMat, avgVarianceMat, 0, REDUCE_SUM, -1);
		noiseVariance = avgVarianceMat(0, 0) / (h*w);
	}

	for (int r = 0; r < h; ++r){
		// get row pointers
		uchar const * const srcRow = src.ptr<uchar>(r);
		uchar * const dstRow = dst.ptr<uchar>(r);
		double * const varRow = variances.ptr<double>(r);
		double * const meanRow = means.ptr<double>(r);
		for (int c = 0; c < w; ++c) {
			dstRow[c] = saturate_cast<uchar>(
				meanRow[c] + max(0., varRow[c] - noiseVariance) / max(varRow[c], noiseVariance) * (srcRow[c] - meanRow[c])
			);
		}
	}

	return noiseVariance;
}

void WienerFilter(const Mat& src, Mat& dst, double noiseVariance, const Size& block){
	WienerFilterImpl(src, dst, noiseVariance, block);
	return;
}


double WienerFilter(const Mat& src, Mat& dst, const Size& block){
	return WienerFilterImpl(src, dst, -1, block);
}

在这里插入图片描述

滤波后
在这里插入图片描述

参考资料

  • Lim, Jae S. Two-Dimensional Signal and Image Processing. Englewood Cliffs, NJ: Prentice Hall, 1990. pp. 536-540
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值