非局部均值(Non Local Mean)【GLSL】

简介: 非局部均值(Non Local Mean)【GLSL】

原理介绍:

请参考这篇博文——https://blog.csdn.net/panda1234lee/article/details/88016834

代码及详细注释:

//#version 120
uniform sampler2D iChannel0;
const vec2 iResolution = vec2(512., 512.);
const vec2 inv_res = vec2(1.) / iResolution.xy;
const int search_radius = 3; // 搜索窗口半径
const int block_radius = 1; // 模板窗口半径
const int search_window = 2 * search_radius + 1; // 搜索窗口大小
const float minus_search_window2_inv = -1.f/(search_window * search_window);  // -.5f // opencv-cuda
const int h = 10; // 控制高斯函数衰减的程度
const int block_window = 2 * block_radius + 1; // 模板窗口大小
const float minus_h2_inv = -1.f/(h * h * 4); // 通道数为 4, opencv-cuda
//const float noise_mult = minus_h2_inv / (block_window * block_window); // opencv-cuda
const float noise_mult = minus_h2_inv * 500;  // 保留更多细节
//const float noise_mult = -10.f; // 0.f;
// L2 范数
float norm2(const vec4 v) 
{ 
   //return v.x*v.x + v.y*v.y + v.z*v.z  + v.w*v.w; 
   return pow(v.x, 2) + pow(v.y, 2) + pow(v.z, 2) + pow(v.w, 2);
}
void main(void)
{
   vec2 coord_xy = gl_FragCoord.xy;
   vec4 sum1 = vec4(0.f);
   float sum2 = 0.f;
   // 遍历搜索窗口
   for(float y = -search_radius; y <= search_radius; ++y)
   {
      for(float x = -search_radius; x <= search_radius; ++x)
      {
          // 统计一个搜索窗口内的颜色(所有模板窗口内颜色的) L2 范数之和
          float dist2 = 0;
          // 遍历模板窗口
          for(float ty = -block_radius; ty <= block_radius; ++ty)
          {
             for(float tx = -block_radius; tx <= block_radius; ++tx)
             {
                // 搜索窗口邻域
                vec2 uv0 = (coord_xy + vec2(x + tx, y + ty)) * inv_res;
                vec4 bv = /*clamp(*/ texture2D(iChannel0, uv0)/*, 0., 1. )*/;
                // 当前像素邻域
                vec2 uv1 = (coord_xy + vec2(tx, ty)) * inv_res;
                vec4 av = /*clamp(*/ texture2D(iChannel0, uv1)/*, 0., 1. )*/;
                dist2 += norm2(av - bv);
             }
          }
          // 一个搜索窗口下,(所有模板窗口的颜色距离和像素距离计算出的)高斯权重
          float w = exp(dist2 * noise_mult + (pow(x, 2) + pow(y, 2)) * minus_search_window2_inv);
          vec2 uv2 = (coord_xy + vec2(x, y)) * inv_res;
          sum1 +=  w * /*clamp(*/ texture2D(iChannel0, uv2) /*, 0., 1.)*/;  // 高斯权重 * 像素值
          sum2 += w; // 累加所有搜索窗口的高斯权重,用于归一化
      }
   }
   gl_FragColor = vec4(sum1 / sum2);
   //gl_FragColor = texture2D(iChannel0, coord_xy * inv_res); // test
}

原图:

image.png

滤波效果图(在我机器上瞬时的 fps 达到了 205 左右):

image.png

NLM 去噪效果是挺不错,但是它的最大缺点就是计算复杂度太高,程序非常耗时,一旦增加 block_radius,FPS 就 “嗖嗖” 得下降了。 -_-b

目录
相关文章
|
27天前
|
数据可视化
R语言非参数模型厘定保险费率:局部回归、广义相加模型GAM、样条回归
R语言非参数模型厘定保险费率:局部回归、广义相加模型GAM、样条回归
|
28天前
R语言中广义线性模型(GLM)中的分布和连接函数分析
R语言中广义线性模型(GLM)中的分布和连接函数分析
|
9月前
|
机器学习/深度学习 算法
Lecture 6:值函数近似
Lecture 6:值函数近似
|
6月前
|
数据挖掘
12 正态分布的定义
12 正态分布的定义
27 0
|
10月前
|
算法
ENVI_IDL:使用反距离权重法选取最近n个点插值(底层实现)并输出为Geotiff格式(效果等价于Arcgis中反距离权重插值)
ENVI_IDL:使用反距离权重法选取最近n个点插值(底层实现)并输出为Geotiff格式(效果等价于Arcgis中反距离权重插值)
256 0
|
存储 算法 计算机视觉
非局部均值滤波算法(NL-means)下
非局部均值滤波算法(NL-means)。非局部均值滤波算法最早于2005年由Buades等人发表在CVPR上,论文原文:A non-local algorithm for image denoising,还有一篇2011年的论文:Non-Local Means Denoising。之后还会继续介绍DCT(离散余弦变换滤波)、TV(全变分滤波)、BM3D(3维块匹配滤波)等算法。
276 0
非局部均值滤波算法(NL-means)下
|
人工智能 算法 BI
非局部均值滤波算法(NL-means)上
非局部均值滤波算法(NL-means)。非局部均值滤波算法最早于2005年由Buades等人发表在CVPR上,论文原文:A non-local algorithm for image denoising,还有一篇2011年的论文:Non-Local Means Denoising。之后还会继续介绍DCT(离散余弦变换滤波)、TV(全变分滤波)、BM3D(3维块匹配滤波)等算法。
188 0
非局部均值滤波算法(NL-means)上
|
算法 计算机视觉 Python
最邻近插值算法(Python源码示例)
最邻近插值算法(Python源码示例)
230 0
最邻近插值算法(Python源码示例)
|
算法 异构计算 Python
【Python】向量叉积和凸包 | 引射线法 | 判断点是否在多边形内部 | 葛立恒扫描法 | Cross Product and Convex Hul
这个系列似乎反响不错, 所以我继续水下去 (bushi)。本篇博客是关于经典的 Cross Product and Convex Hull (向量叉积和凸包)的,我们将介绍引射线法,葛立恒扫描法。在讲解之前我会对前置知识做一个简单的介绍,比如向量叉积,如何确定直线是在顺时针上还是逆时针上等。算法讲解部分是为后面练习题做准备的,比如如何判断内点是否在多边形内,如何计算多边形面积等,还将简单介绍一下葛立恒扫描法,在提供的练习题中就能碰到.
658 0
【Python】向量叉积和凸包 | 引射线法 | 判断点是否在多边形内部 | 葛立恒扫描法 | Cross Product and Convex Hul
|
Go Python
CSP 202104-2 邻域均值 python 二维前缀和
CSP 202104-2 邻域均值 python 二维前缀和
CSP 202104-2 邻域均值 python 二维前缀和