全网讲自适应维纳滤波最清晰的?
基本原理
算法很简单,以下内容来自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
版权声明:本文为webzhuce原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。