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

基本原理

算法很简单,以下内容来自Matlab官网。
图像去噪之自适应维纳滤波_第1张图片

详细介绍

自适应维纳滤波

大多数去除加性噪声的自适应图像复原算法流程:
图像去噪之自适应维纳滤波_第2张图片

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

下面很重要,解释从9.26公式如何到Matlab的形式。
图像去噪之自适应维纳滤波_第5张图片

示例演示

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

#pragma once

#include  
#include 
#include 

#include 

/** @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);
}

图像去噪之自适应维纳滤波_第6张图片

滤波后
图像去噪之自适应维纳滤波_第7张图片

参考资料

  • Lim, Jae S. Two-Dimensional Signal and Image Processing. Englewood Cliffs, NJ: Prentice Hall, 1990. pp. 536-540

你可能感兴趣的:(OpenCV实例,matlab,计算机视觉,图像处理)