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

举报
ShaderJoy 发表于 2021/12/31 23:21:35 2021/12/31
【摘要】 原理介绍: 请参考这篇博文——https://blog.csdn.net/panda1234lee/article/details/88016834 代码及详细注释: //#version 120 uniform sampler2D iChannel0;const vec2 iResolution = vec2(512., 512...

原理介绍:

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

代码及详细注释:


  
  1. //#version 120
  2. uniform sampler2D iChannel0;
  3. const vec2 iResolution = vec2(512., 512.);
  4. const vec2 inv_res = vec2(1.) / iResolution.xy;
  5. const int search_radius = 3; // 搜索窗口半径
  6. const int block_radius = 1; // 模板窗口半径
  7. const int search_window = 2 * search_radius + 1; // 搜索窗口大小
  8. const float minus_search_window2_inv = -1.f/(search_window * search_window); // -.5f // opencv-cuda
  9. const int h = 10; // 控制高斯函数衰减的程度
  10. const int block_window = 2 * block_radius + 1; // 模板窗口大小
  11. const float minus_h2_inv = -1.f/(h * h * 4); // 通道数为 4, opencv-cuda
  12. //const float noise_mult = minus_h2_inv / (block_window * block_window); // opencv-cuda
  13. const float noise_mult = minus_h2_inv * 500; // 保留更多细节
  14. //const float noise_mult = -10.f; // 0.f;
  15. // L2 范数
  16. float norm2(const vec4 v)
  17. {
  18. //return v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w;
  19. return pow(v.x, 2) + pow(v.y, 2) + pow(v.z, 2) + pow(v.w, 2);
  20. }
  21. void main(void)
  22. {
  23. vec2 coord_xy = gl_FragCoord.xy;
  24. vec4 sum1 = vec4(0.f);
  25. float sum2 = 0.f;
  26. // 遍历搜索窗口
  27. for(float y = -search_radius; y <= search_radius; ++y)
  28. {
  29. for(float x = -search_radius; x <= search_radius; ++x)
  30. {
  31. // 统计一个搜索窗口内的颜色(所有模板窗口内颜色的) L2 范数之和
  32. float dist2 = 0;
  33. // 遍历模板窗口
  34. for(float ty = -block_radius; ty <= block_radius; ++ty)
  35. {
  36. for(float tx = -block_radius; tx <= block_radius; ++tx)
  37. {
  38. // 搜索窗口邻域
  39. vec2 uv0 = (coord_xy + vec2(x + tx, y + ty)) * inv_res;
  40. vec4 bv = /*clamp(*/ texture2D(iChannel0, uv0)/*, 0., 1. )*/;
  41. // 当前像素邻域
  42. vec2 uv1 = (coord_xy + vec2(tx, ty)) * inv_res;
  43. vec4 av = /*clamp(*/ texture2D(iChannel0, uv1)/*, 0., 1. )*/;
  44. dist2 += norm2(av - bv);
  45. }
  46. }
  47. // 一个搜索窗口下,(所有模板窗口的颜色距离和像素距离计算出的)高斯权重
  48. float w = exp(dist2 * noise_mult + (pow(x, 2) + pow(y, 2)) * minus_search_window2_inv);
  49. vec2 uv2 = (coord_xy + vec2(x, y)) * inv_res;
  50. sum1 += w * /*clamp(*/ texture2D(iChannel0, uv2) /*, 0., 1.)*/; // 高斯权重 * 像素值
  51. sum2 += w; // 累加所有搜索窗口的高斯权重,用于归一化
  52. }
  53. }
  54. gl_FragColor = vec4(sum1 / sum2);
  55. //gl_FragColor = texture2D(iChannel0, coord_xy * inv_res); // test
  56. }

原图:

 

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

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

文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。

原文链接:panda1234lee.blog.csdn.net/article/details/88239678

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。