人类的世界就是一个信号传输的世界,所以噪声无处不在,图像作为一种信号传输的方式当然也无法幸免。为了尽量减少噪声对图像质量的影响,还原物体的本来状态就提出了一系列降噪的方法,本文就简单介绍几种常见的降噪滤波算法。

图像噪声产生的原因

矫正方法

我将图像去噪的算法大致分位这么几类,包括硬件去噪,从源头降低噪声,常见的方式有CDS(cor related double sampling),但是这种硬件的方式不是ISP涉及的范围所以不做过多介绍。然后就大致分位空域滤波、变换域滤波和时域滤波,当然还有一些其他方式比如空域和变换域相结合的方式,但是个人觉得大致这么分也可以。然后后面的算法会逐步更新,这篇主要几种讲解的是空域中的均值滤波相关的算法。

均值滤波

算法原理

如图是一个信号和噪声的分布图像,黑色曲线是真实信号,彩色的是多次采集的信号,会发现采集的信号是在真实信号上下波动,这个波动就是噪声对信号带来的影响。最早为了消除这种噪声有人就提出采用多张同一场景的图片求和取平均来消除,因为噪声是随机的,每张图中的噪声使得信号的偏移是不固定的,多次求平均后就能使得信号接近真实信号。就像上图中,对彩色的信号求平均相当于黑色曲线上下的值求平均,结果自然就接近黑色曲线从而达到去噪的效果。从多张叠加求平均的想法中有人就提出了从一张图里求平均来到达降噪的效果,也就是这里提到的均值滤波。其实整个算法的思想很简单,就是假设图像在一个很小的邻域范围内像素的变化不会太大,那么就可以在一个很小的邻域范围内求一个平均值来取代当前的像素值从而达到降噪的效果。典型的应用就是在图像中取一个3X3的邻域,然后每个像素给权重1,最后求和取平均。然后让这个邻域遍历整个图像。

用数学公式表示就是f(i,j)=19∗[f(i−1,j−1)+f(i−1,j)+f(i−1,j+1)+f(i,j−1)+f(i,j)+f(i,j+1)+f(i+1,j−1)+f(i+1,j)+f(i+1,j+1))]f(i, j) = \frac{1}{9} * [f(i-1, j-1)+f(i-1, j)+f(i-1, j+1)+f(i, j-1)+f(i, j)+f(i, j+1)+f(i+1, j-1)+f(i+1, j)+f(i+1, j+1))]f(i,j)=91​∗[f(i−1,j−1)+f(i−1,j)+f(i−1,j+1)+f(i,j−1)+f(i,j)+f(i,j+1)+f(i+1,j−1)+f(i+1,j)+f(i+1,j+1))]

算法实现

%% --------------------------------
%% author:wtzhu
%% email:wtzhu_13@163.com
%% date:
%% fuction: 均值滤波
%% --------------------------------
clear;
clc;
close all;
img = imread('./images/test_pattern_blurring_orig.tif');
[m, n] = size(img);
figure;subplot(221);imshow(img);title('original image');%% 运算的时候需要对边缘进行扩展
% 需要特殊处理四周最外圈的行和列,本算法中将其向外扩展一圈,用最外圈的值填充
headRowMat = img(1,:);%取f的第1行
tailRowMat = img(m,:);%取f的第m行
% 行扩展后,列扩展时需要注意四个角需要单独扩展进去,不然就成了十字架形的
headColumnMat = [img(1,1), img(:,1)', img(m,1)];
tailColumnMat = [img(1,n), img(:,n)', img(m,n)];
expandImage = [headRowMat; img; tailRowMat];
expandImage = [headColumnMat; expandImage'; tailColumnMat];
expandImage = uint8(expandImage');
subplot(222);imshow(expandImage);title('expand image');% 创建新的图像
newImg = zeros(m, n);
% 定义模板
meanKernal = uint8([1 1 1;1 1 11 1 1]);
% 遍历图像进行均值滤波
% 1.首先提取图像中待操作的ROI
% 2.利用模板对提取的ROI进行运算并赋值给新的图像
for i =2: m+1for j =2: n+1imgRoi = [expandImage(i-1, j-1) expandImage(i-1, j) expandImage(i-1, j+1);expandImage(i  , j-1) expandImage(i  , j) expandImage(i  , j+1);expandImage(i+1, j-1) expandImage(i+1, j) expandImage(i+1, j+1)];newImg(i-1, j-1) = uint8(sum(sum(imgRoi.*meanKernal))/9);end
end
newImg = uint8(newImg);
subplot(223);imshow(newImg);title('new image');
subplot(224);imshow(img-newImg);title('newImg-img');

如图所示,第三幅图就是经过均值滤波处理后的效果,和第一幅图比起来变得更模糊。通过原始图像和新图像最差就能得到最后的图像,新清晰的看到边缘和部分噪点是被滤除掉了。所以这种降噪的方法有个致命的缺点就是会损失图像的边缘细节。

高斯滤波

算法原理

为了更好的保留边缘信息,就提出了加权平均的方法,就是平均之前每每个数的权重不一样。其实在图形中更好理解,某一个点的值肯定和本身的像素值关系最大,所以对应的本身哪个点的权重就会更大些,我么通过以下公式计算
f(i,j)=116∗[f(i−1,j−1)∗1+f(i−1,j)∗2+f(i−1,j+1)∗1+f(i,j−1)∗2+f(i,j)∗4+f(i,j+1)∗2+f(i+1,j−1)∗1+f(i+1,j)∗2+f(i+1,j+1)∗1)]\begin{aligned} f(i, j)& = \frac{1}{16} * [f(i-1, j-1) *1 +f(i-1, j) * 2+f(i-1, j+1)*1+\\ & f(i, j-1)*2+f(i, j)*4+f(i, j+1)*2+f(i+1, j-1)*1+f(i+1, j)*2+f(i+1, j+1)*1)] \end{aligned} f(i,j)​=161​∗[f(i−1,j−1)∗1+f(i−1,j)∗2+f(i−1,j+1)∗1+f(i,j−1)∗2+f(i,j)∗4+f(i,j+1)∗2+f(i+1,j−1)∗1+f(i+1,j)∗2+f(i+1,j+1)∗1)]​

上面这幅图就是典型的高斯分布的图像,自然中很多分布都是满足高斯分布的,那么如果噪声也是高斯分布我们就可以通过高斯分布来进行加权。高斯滤波的具体思路如下:

  • 使用与中心像素的距离,通过高斯函数来计算该点的权重;
  • 将所有点的权重求出来后对权重进行归一化处理;
  • 利用加权平均的方式计算滤波后的像素值;
  • 邻域窗口遍历图像,重复上述操作。

整体思路和均值滤波没有太大区别,这里代码实现就不做过多叙述。

双边滤波

算法原理

虽然高斯滤波相对于普通均值滤波而言性能有所提升,但是依然对边缘随时严重,为了进一步保留边缘信息,就需要对边缘做进一步处理。于是就有人提出在高斯分布的基础上再加一个权重,这个权重和像素值的差别挂上联系,这个算法就是双边滤波算法。

如图是原始论文中的公式,从中可以看出双边滤波有两个高斯权重叠加而来。前面||p-q||就是高斯滤波中使用的距离权重,后面的|Ip-Iq|就是像素值的高斯分布的权重。其实也很好理解,去噪的时候肯定需要相似的区域有更大的贡献,不相同的给小的权重,而对于边缘而言,那么两侧的像素值的差距肯定很大,也就会导致离边缘另一侧不同的会分配一个小权重,而同侧相差小就会有一个很大的权重,这样就不会由于取平均的时候将边缘两侧的大差异变小导致边缘变弱了,从而起到保留边缘的目的。

如图是双边滤波的示意图,当对白点位置进行滤波操作的时候,同侧像素差别较小会有一个大权重,而另一侧差别很大权重也就很小,二者结合后就相当于高斯滤波取一侧,然后利用这个核进行滤波操作。

算法实现

如图有很明显的边缘,我需要对红点处进行滤波

%% --------------------------------
%% author:wtzhu
%% email:wtzhu_13@163.com
%% date: 20211011
%% fuction: 双边滤波
%% --------------------------------
clc;clear;close all;% gaussian filter
% the weight is only related to distance
x = 1:200;
y = 1:200;
[X, Y] = meshgrid(x, y);
D = (X-100).^2+(Y-100).^2;
z1 = exp(-D/2000);
figure();
mesh(x, y, z1)
title('高斯模型')% add pixel value weight;
a = ones(200)*220;
a(:,1:100) = 20;
a(1:100,:) = 20;
figure();
imshow(uint8(a));
title('图像')
z2 = zeros(200);
for i=1:200for j=1:200z2(i, j) = exp(-(a(i, j)-220)^2/1800);end
end
figure();
mesh(x, y, z2);
title('像素权重');
z = z1.*z2;
figure();
mesh(x, y, z)
title('双边模型')

那么很容易就能得到一个高斯滤波的图形

然后根据像素差异通过高斯分布也很容易得到一个分布图像

因为我的图像中同侧像素是一样的,那么相当于权重都是1,另一侧相差接近最大位数控制,所以权重就很小接近0,所以才边缘的时候权重就会有一个阶跃的效果,然后把这两个权重相结合就可以得到一完整的滤波器

相当于我只对同一侧的像素进行一个高斯滤波,而另一侧则保留为原来的值,这样就能起到很好的保边效果。

NLM(non-local mean)

算法原理

前面的几种都是在邻域范围内对局部图像进行平均滤波,NLM则是利用整个图像的信息来进行降噪滤波处理。

如图是论文中的实例,对于p点而言,q1和q2点所在的邻域和p所在的邻域更相似,那么就给q1和a2较大的权重,而q3邻域和p邻域差别较大,就赋予一个较小的权重。具体权重的赋予方式其实也是高斯的一种方式,只不过e的对数是通过邻域简单欧拉距离来计算。

相当于求了几邻域中对应位置像素差的平方和来当作分配权重的依据。当邻域相似时,这个方差就小,权重也就大,而差异很大时方差就很大,权重也就很小,满足了算法的需求。理论上每一个点进行去噪的时候会利用整个图像的信息来计算,但是为了降低运算量,一般不会用整个图像的信息来计算,而是在整个图像中先选择一个大的范围,然后用这个范围内的点的信息进行降噪处理。

具体算法思路如下:

  1. 遍历整幅图像;
  2. 针对每一个点定义一个滑动窗口,降噪的时候利用该窗口中的所有点的信息计算;
  3. 定义一个邻域范围,用来计算像素块的差异;
  4. 遍历滑动窗口中的点,求每个点的邻域范围和当前点的邻域范围的像素差值的平方和,并利用该值计算一个权重;
  5. 遍历完滑动窗口中的所有点后,滑动窗口中的每个点都有一个权重,对权重进行归一化处理;
  6. 得到归一化处理后的权重通过加权平均的方式计算出当前点的新的像素值;

简化为图形就是如图的方式,最中间的黑色框的范围就是实际图像大小,外面蓝色范围时昨晚扩充的图像(为了处理边缘领域不够的问题)。计算黑色点的时候,就是定义一个红色框,然后黄色点在黄色框中遍历,每次都计算出两个小黑色框对应位置像素的差值的平方从而求出一个权重,当红色框遍历完了之后对权重机型归一化,然后加权平均就能求出黑色点的值。接着黑色点在图像中遍历,同事红色框随着黑点移动,然后黄色点又在红色框中移动,以此循环即可完成整幅图像的去噪操作。

算法实现

%% --------------------------------
%% author:wtzhu
%% email:wtzhu_13@163.com
%% date: 20211012
%% fuction: Non-Local Means
%% --------------------------------
close all;
clear all;
clc
img = imread('./images/lena.bmp');
I = double(img);
% I = double(imresize(img, [64, 64]));
figure();
imshow(uint8(I));
I_noise = I + 10 * randn(size(I));
figure();
imshow(uint8(I_noise));% -----------------------------------
ds = 2;
Ds = 5;
h = 10;
% -----------------------------------[m,n] = size(I_noise);
DenoisedImg = zeros(m,n);
PaddedImg = padarray(I,[ds+Ds,ds+Ds],'symmetric','both');kernel = ones(2*ds+1,2*ds+1);
kernel = kernel./((2*ds+1)*(2*ds+1));
h2=h*h;tic
for i=1:mfor j=1:nnum = 0;i1=i+ds+Ds;j1=j+ds+Ds;W1=PaddedImg(i1-ds:i1+ds,j1-ds:j1+ds);  % current windowfprintf('=======current point: (%d, %d)\n', i, j);wmax=0;average=0;sweight=0;% search window% This window is not a fixed size, % it shrinks when it's in the corner or borderswmin = i1 - Ds;swmax = i1 + Ds;shmin = j1 - Ds;shmax = j1 + Ds;for r = swmin: swmaxfor s = shmin: shmaxif(r==i1 && s==j1)continue;endW2 = PaddedImg(r-ds:r+ds,s-ds:s+ds); % the window is to be compared with current windownum = num + 1;% Use the mean directly in order to simplify the calculateDist2 = sum(sum(kernel.*(W1-W2).*(W1-W2)));    w = exp(-Dist2/h2);   % the weight of the compared windowif(w > wmax)wmax = w;endsweight = sweight + w;  % sum the weight to normalizeaverage = average + w*PaddedImg(r,s);endendfprintf('num of win: %d\n', num);average = average + wmax*PaddedImg(i1,j1);sweight = sweight+wmax;DenoisedImg(i,j) = average/sweight;end
end
figure();
imshow(uint8(DenoisedImg));
toc

我这里的带啊实现和算法原理和原始论文的代码有些许出入,主要时为了方便理解。原始代码中没有对图像进行扩充操作,而是在边界的时候,会做一个判断,通过改变滑动窗口的大小和邻域的半径来处理,初次看代码的时候可能不太好理解,所以我这里就没加这个,直接扩充后每个点的窗口和邻域大小都时一样的。

相关链接

  • zhihu: ISP图像处理 - 知乎 (zhihu.com)
  • CSDN:ISP图像处理_wtzhu_13的博客-CSDN博客
  • Bilibili:食鱼者的个人空间_哔哩哔哩_Bilibili
  • Gitee:ISPAlgorithmStudy: ISP算法学习汇总,主要是论文总结 (gitee.com)

NR基础篇上——均值滤波、高斯滤波、双边滤波、NLM相关推荐

  1. 中值滤波,均值滤波,高斯滤波,双边滤波,联合双边滤波介绍

    看GAMES202相关课程发现闫老师讲的太好了,所以记录一下.当然文中涉及的PPT也来自闫老师的课程PPT,欢迎交流. 首先这几种都是空域的滤波方式,用于抑制图像中的噪声.它们采用的原理基本都是通过滤 ...

  2. OpenCV(十一)图像滤波(平滑处理)(平均、中值、高斯、双边滤波)

    目录 一.基础理论 1.图像噪声 1-1.椒盐噪声 1-2.高斯噪声 2.滤波 3.线性滤波 1.概述 2.线性滤波原理: 二.均值滤波(cv::blur())(简单滤波) 1.原理 2.API 三. ...

  3. 《CSS蝉意花园读书精记》(基础篇---------上.资料篇1)

    这一篇文章主要是翻译书中提到的国际化的一篇文章,并让大家了解软件开发中字符编码的众多问题,被翻译的文章写得比较早,可能从技术的角度来看不是很有意义的,作者在文中是概括主流的字符编码,并不能让大家深入的 ...

  4. SpringBoot图文教程「概念+案例 思维导图」「基础篇上」

    有天上飞的概念,就要有落地的实现 概念+代码实现是本文的特点,教程将涵盖完整的图文教程,代码案例 每个知识点配套自测面试题,学完技术自我测试 本文初学向,所以希望文中所有的代码案例都能敲一遍 大哥大姐 ...

  5. 三种经典图像滤波方法介绍——双边滤波(Bilateral filter)、导向滤波(Guided Fliter)、滚动导向滤波(RollingGuidedFilter)

    文章目录 一.前言 二.双边滤波(Bilateral filter) 2.1 双边滤波的理论介绍及公式推导 2.2 双边滤波的matlab程序实现 三.导向滤波(Guided Fliter) 3.1 ...

  6. java 滤波算法_双边滤波算法

    1.原理 高斯滤波是以距离为权重,设计滤波模板作为滤波系数,只考虑了像素间的空间位置上的关系,因此滤波的结果会丢失边缘的信息. 高斯滤波的缺陷如下图所示:平坦区域正常滤波,图像细节没有变化,而在突变的 ...

  7. 图像处理-双边滤波和联合双边滤波

    图像处理-双边滤波和联合双边滤波 双边滤波原理 ​ 双边滤波(Bilateral Filter)是一种非线性滤波器,可以达到保持边缘,降噪平滑的效果.其算法最早由C. Tomasi和R. Manduc ...

  8. 双边滤波和交叉双边滤波

    什么是双边滤波 双边滤波是一种局部的.非线性的.非迭代的滤波技术,它将经典的低通滤波器与边缘停止函数相结合,当像素之间的强度差较大时,边缘停止函数会衰减滤波器的核心.由于同时考虑了相邻像素的灰度相似度 ...

  9. Opencv之图像滤波:6.双边滤波(cv2.bilateralFilter)

    前面我们介绍的滤波方法都会对图像造成模糊,使得边缘信息变弱或者消失,因此需要一种能够对图像边缘信息进行保留的滤波算法,双边滤波是综合考虑空间信息和色彩信息的滤波方式,在滤波过程中能够有效地保护 图像内 ...

最新文章

  1. 人脸识别引擎SeetaFaceEngine中Detection模块使用的测试代码
  2. 以太坊挖矿源码:clique算法
  3. LINUX的20练习题
  4. java pathinfo,nginx下支持PATH_INFO的方法实例详解
  5. Linux服务器上配置Tomcat的docBase路径映射时遇到的坑
  6. 【Java】字符串转Unicode字符串
  7. h5 表单居中_3分钟学会易企秀H5操作(基础篇)
  8. SQL Server: create table sql script
  9. 记录sqoop同步失败问题解决过程,过程真的是很崎岖。(1月6日解决)
  10. python指定目录_python生成指定文件夹目录树
  11. Mac电脑疑似中毒该怎么应对处理?
  12. mysql 23000_mysql – SQLSTATE [23000]:完整性约束违规:1452无法添加或更新子行:外键约束失败...
  13. linux异步io底层原理,异步IO简析
  14. 使用网易云api、Vue 和swiper实现轮播图 (音乐app项目-第2步)
  15. 使用selenium + pytest + allure做WBE UI自动化
  16. 防火墙端口大全(转)
  17. 「干货」Linux 应急响应日志分析命令「详细总结」
  18. 【UE】初识Slate编辑器-理解一个最基础的编辑器界面
  19. winSCP:无权访问。 错误码:3 服务器返回的错误消息:Permission denied解决方案
  20. Appium 解决不能输入中文字符问题

热门文章

  1. 2020春招 / 2021秋招阿里、腾讯、字节、快手、美团 JAVA 开发岗面试高频问题总结
  2. 狄利克雷卷积_算法学习笔记(35): 狄利克雷卷积
  3. 波士顿房价数据集——预测房价
  4. 淘宝新手开店怎么做才能破零
  5. vivox6android版本5.1,vivo X6的手机系统是什么?vivo X6能升级安卓5.0吗?
  6. wPDF v5支持并改进旋转文本的逻辑
  7. 别人花了几万元学的英语,我帮你们免费弄来了
  8. 2.Nacos 服务注册的原理
  9. 安卓手机微信数据导出方法 -- adb备份(无需root)
  10. iOS 直播专题1-直播流程原理