非局部均值滤波算法(NL-means)

今天来学习一下另一类滤波算法:非局部均值滤波算法(NL-means)。非局部均值滤波算法最早于2005年由Buades等人发表在CVPR上,论文原文:A non-local algorithm for image denoising,还有一篇2011年的论文:Non-Local Means Denoising。之后还会继续介绍DCT(离散余弦变换滤波)、TV(全变分滤波)、BM3D(3维块匹配滤波)等算法。

上一篇文章介绍了均值滤波、中值滤波、高斯滤波、双边滤波和引导滤波,均为局部滤波,即对周围邻域的点加权生成当前点,加权因子反应出周围点对当前点的影响。非局部滤波就意味着它使用图像中的所有像素,这些像素根据某种相似度进行加权平均。滤波后图像清晰度高,而且不丢失细节。

与上述算法思路不同,前者根据像素点之间的距离计算权重,后者根据块之间的相似度计算权重。其核心思路与高斯滤波很相似:计算矩形窗口内所有像素点的像素值加权和,权重服从高斯分布。区别在于:高斯滤波使用当前滤波点与矩形窗口内其它点的空间欧式距离来计算权重,距离越近权重越大;而非局部均值滤波则使用当前滤波点的邻域块与矩形窗口内其它点的邻域块的相似度来计算权重,相似度越大则权重越大。
左边是高斯滤波空间距离d,右边是非NLMeans相似度MSE。要衡量两个邻域块的相似度,有多种指标,均方误差(MSE)是最常用的相似度衡量指标之一。非局部均值滤波算法就是使用MSE来计算两个邻域块的相似度。邻域块的行列相同,假设均为m行n列,那么MSE的计算如下式,其中A(i,j)为点A邻域块中的点(i,j)的像素值,B(i,j)为点B邻域块中的相同位置点的像素值。

代码实现计算两个区域A,B的MSE:

//计算0~255的平方查找表
float table1[256];
static void cal_lookup_table1(void)
{for (int i = 0; i < 256; i++){table1[i] = (float)(i*i);}
}//计算两个0~255的数的绝对差值的查找表
uchar table2[256][256];
static void cal_lookup_table2(void)
{for (int i = 0; i < 256; i++){for (int j = i; j < 256; j++){table2[i][j] = abs(i - j);table2[j][i] = table2[i][j];}}
}float MSE_block(Mat A, Mat B)
{float sum = 0.0;for (int j = 0; j < A.rows; j++){uchar *data1 = A.ptr<uchar>(j);uchar *data2 = B.ptr<uchar>(j);for (int i = 0; i < A.cols; i++){sum += table1[table2[data1[i]][data2[i]]];}}sum = sum / (A.rows*B.cols);return sum;
}

理论上,该算法需要在整个图像范围内判断像素间的相似度,也就是说,每处理一个像素点时,都要计算它与图像中所有像素点间的相似度。但是考虑到效率问题,实现的时候,会设定两个固定大小的窗口:搜索窗(2half_ssize+1)(2half_ssize+1)和邻域窗口(2half_ksize+1)(2half_ksize+1)。邻域窗口在搜索窗口中滑动,根据邻域间的相似性确定像素的权值。

点A的滤波值由搜索窗口内所有点的像素值加权平均得到:

上式中,w(A,B)为点A与搜索窗口中任意一点B的高斯权重,由两点各自邻域块的MSE相似度计算而得。如下式,w(A,B)需要除以搜索窗口内所有点的高斯系数之和,以实现归一化的目的。其中h也是一个重要的参数,h越大去噪效果越好,但是图像越模糊,反之h越小去噪效果越差,但去噪之后的失真度越小。

代码实现类似均值+高斯滤波过程,即非局部均值滤波算法:

//sigma越大越平滑
//halfKernelSize邻域窗
//halfSearchSize搜索窗
void NL_mean(Mat src, Mat &dst, double sigma, int halfKernelSize, int halfSearchSize)
{Mat boardSrc;dst.create(src.rows, src.cols, CV_8UC1);int boardSize = halfKernelSize + halfSearchSize;copyMakeBorder(src, boardSrc, boardSize, boardSize, boardSize, boardSize, BORDER_REFLECT);   //边界扩展double sigma_square = sigma*sigma;int rows = src.rows;int cols = src.cols;cal_lookup_table1();cal_lookup_table2();for (int j = boardSize; j < boardSize + rows; j++){uchar *dst_p = dst.ptr<uchar>(j - boardSize);for (int i = boardSize; i < boardSize + cols; i++){Mat patchA = boardSrc(Range(j - halfKernelSize, j + halfKernelSize), Range(i - halfKernelSize, i + halfKernelSize));double w = 0;double p = 0;double sumw = 0;for (int sr = -halfSearchSize; sr <= halfSearchSize; sr++)   //在搜索框内滑动{uchar *boardSrc_p = boardSrc.ptr<uchar>(j + sr);for (int sc = -halfSearchSize; sc <= halfSearchSize; sc++){Mat patchB = boardSrc(Range(j + sr - halfKernelSize, j + sr + halfKernelSize), Range(i + sc - halfKernelSize, i + sc + halfKernelSize));float d2 = MSE_block(patchA, patchB);w = exp(-d2 / sigma_square);p += boardSrc_p[i + sc] * w;sumw += w;}}dst_p[i - boardSize] = saturate_cast<uchar>(p / sumw);}}
}

主函数
参数设置:标准差25,邻域窗2X2,搜索窗10X10

void main()
{Mat src = imread("原图.jpg", CV_LOAD_IMAGE_GRAYSCALE);Mat dst;NL_mean(src, dst, 25, 2, 10);   //NL-meansimshow("原图", src);imshow("非局部均值滤波", dst);waitKey(0);
}

NL_means算法效果很好,但是运行速度较慢,需要对算法进行加速,下面还看到一种积分图加速的方法:
积分图加速本质是,将图像的所有点,计算某一偏离坐标点方向的权重,一次性计算出来,而不是单次计算某一点的所有偏离点。具体,计算当前图像与一定偏移后的图像的diff并平方,继而计算与原图像同等尺寸的积分图,则每一个点与偏离它在一定偏移的坐标点的距离,通过积分图就可以计算出来了。积分图的作用体现在使用线性计算,减少重复计算,即存储换时间。

MATLAB代码实现:

clc;
clear all;
close all;%---------------------------%
%       input
%---------------------------%
src=imread('lena.jpg');
src=rgb2gray(src);
src=double(src);
figure,imshow(src,[]),title('src image')%---------------------------%
%       parameter
%---------------------------%
[m,n]=size(src);
ds=2;% block size for calculate weight
Ds=5;% search block
h=10;% decay factor
offset=ds+Ds;
PaddedImg = padarray(src,[ds+Ds,ds+Ds],'symmetric','both');% 扩展图像,便于处理%---------------------------%
%  Non-Local Means Denoising
%---------------------------%
sumimage=zeros(m,n);
sumweight=zeros(m,n);
maxweight=zeros(m,n);
image=PaddedImg(1+Ds:Ds+m+ds,1+Ds:Ds+n+ds);
[M,N]=size(image);
for r=-Ds:Dsfor s=-Ds:Ds%跳过当前点偏移if(r==0&&s==0)continue;end%求得差值积分图wimage=PaddedImg(1+Ds+r:Ds+m+ds+r,1+Ds+s:Ds+n+ds+s);diff=image-wimage;diff=diff.^2;J=cumsum(diff,1);J=cumsum(J,2);%计算距离distance=J(M-m+1:M,N-n+1:N)+J(1:m,1:n)-J(M-m+1:M,1:n)-J(1:m,N-n+1:N);distance=distance/((2*ds+1).^2);%计算权重并获得单个偏移下的加权图像weight=exp(-distance./(h*h));sumimage=sumimage+weight.*wimage(ds+1:ds+m,ds+1:ds+n);sumweight=sumweight+weight;maxweight=max(maxweight,weight);end
end
sumimage=sumimage+maxweight.*image(ds+1:ds+m,ds+1:ds+n);
sumweight=sumweight+maxweight;
dst=sumimage./sumweight;%---------------------------%
%       output
%---------------------------%
figure,imshow(dst,[]),title('dst');

效果图如下:

非局部均值滤波算法(NL-means)相关推荐

  1. 非局部相似性 matlab,非局部均值滤波(NLM)和MATLAB程序详解视频教程保持图像细节...

    [内容简介]<非局部均值滤波与应用和MATLAB程序详解视频>共6章28节视频,总学时698分钟,合11.6小时.主要内容包括:非局部均值滤波类算法入门,基于滤波参数自适应的非局部均值滤波 ...

  2. 详解非局部均值滤波原理以及用MATLAB源码实现

    详解非局部均值滤波原理以及用MATLAB源码实现 序言 均值滤波.中值滤波.高斯滤波在滤除噪声的过程中,无可避免的使图像的边缘细节和纹理信息所被滤除.针对此问题,Buades[1]等人提出了非局部均值 ...

  3. 经典非局部均值滤波(NLM)算法python实现(1)

    经典非局部均值滤波(NLM)算法python实现(单通道图像版本) 概述:非局部均值(NL-means)是近年来提出的一项新型的去噪技术.该方法充分利用了图像中的冗余信息,在去噪的同时能最大程度地保持 ...

  4. 经典非局部均值滤波(NLM)算法python实现(2)

    经典非局部均值滤波(NLM)算法python实现(三通道图像版本) 单通道图像版本已发布: https://blog.csdn.net/yy0722a/article/details/11392408 ...

  5. 非线性邻域滤波(NNFs)在MR-FBP图像重建算法中的应用(基于astra-toolbox开发, 实现双边滤波,非局部均值滤波(NLM)的惩戒项的改进,并进行MAE,MAR分析)

    本科荒废了两年,大三终于开始好好学习了,,,,但是跟无头苍蝇,只知道上课,大四即将找工作,心理慌得一批,由于自己太辣鸡,,,只能找到3,4000的,,,终于还是决定步入研究生大抗,,,上了后发现他娘的 ...

  6. 图像降噪算法——非局部均值降噪算法

    图像降噪算法--非局部均值降噪算法 图像降噪算法--非局部均值降噪算法 1. 基本原理 2. C++代码实现 3. 结论 图像降噪算法--非局部均值降噪算法 1. 基本原理 非局部均值降噪算法(Non ...

  7. 高斯滤波、双边滤波、邻域滤波、非局部均值滤波(NL-means) 笔记

    1.高斯滤波以及高斯噪声 高斯滤波作为一种平滑线性滤波器,可以抑制图像的"尖锐"变化,对于抑制服从正态分布的噪声效果非常好,但同时会损失大量的边缘信息.学习高斯滤波首先要了解高斯核 ...

  8. Python,OpenCV中的非局部均值去噪(Non-Local Means Denoising)

    Python,OpenCV中的非局部均值去噪(Non-Local Means Denoising) 1. 效果图 2. 原理 3. 源码 2.1 单彩色图去噪 2.2 多连续彩色帧去噪 参考 这篇博客 ...

  9. 浅谈NLM非局部均值滤波

    参考文献:<A non-local algorithm for image denoising> 非局部均值滤波,顾名思义,与高斯滤波等只利用待滤波点周围像素的局部滤波不同,非局部体现在利 ...

最新文章

  1. asp创建mysql表_asp创建数据库表
  2. 经典C语言程序100例之七四
  3. 马云马化腾,过的哪个冬
  4. ArcGIS实验教程——实验十八:叠置分析(Overlay Analysis)
  5. SpringBoot聚合项目总结
  6. UnicodeDecodeError: 'gb2312' codec can't decode bytes in position 723269-723270: illegal multibyte s
  7. (转)基于MVC4+EasyUI的Web开发框架形成之旅--MVC控制器的设计
  8. 有点香!苹果首次参加天猫618 iPhone/iPad全线降价
  9. Regionals 2014 Asia - Dhaka H 暴力
  10. Open XML之我见
  11. Vue + Canvas 实现头像截图上传功能
  12. 人在职场,身不由己?
  13. 如何将多个.TXT文本文件合并到一个excel表中
  14. 通过拉勾网分析数据分析职位现状
  15. ArcGIS 线简化算法的使用及两种方法的比较
  16. JavaMail 使用POP3/SMTP服务发送QQ邮件
  17. 不要嫌我啰嗦~继续话痨python
  18. erick recommendation:慕容晓晓《爱情买卖》MV欣赏
  19. C#把文字放到图片上
  20. 不可不知道的SEO与SEM术语大全

热门文章

  1. 计算机技术为什么更新快,为什么电脑更新换代的速度那么快?
  2. [AAuto]液晶显示器坏点检测
  3. Python模拟Ajax请求爬取微博
  4. AndroidStudio的几个个性的配置和个人笔记
  5. intrinsics information是什么
  6. wps之excel学习(三)
  7. 听力训练方法(转自普特英语听力论坛 )
  8. # [读书笔记1]:工业互联网边缘计算在离散制造业应用展望
  9. 如何用Visio画venn(维恩)图
  10. 快趣拼系统介绍 快趣拼系统开发