当前位置: 首页 > news >正文

【图像处理】图像滤波

参考文章:OpenCV基础应用2.图像滤波

一、图像滤波

图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。

图像滤波既可以在时域进行,也可以在频域进行。图像滤波可以更改或者增强图像。通过滤波,可以强调一些特征或者去除图像中一些不需要的部分。滤波是一个邻域操作算子,利用给定像素周围的像素的值决定此像素的最终的输出值。

1.1 均值滤波

1.1.1 均值滤波核

用周围像素的平均值代替原像素值,均值滤波的核定义为:

1 ksize.width ∗ ksize.height [ 1 1 ⋯ 1 1 1 ⋯ 1 ⋮ ⋮ ⋱ ⋮ 1 1 ⋯ 1 ] \frac{1}{\text{ksize.width} * \text{ksize.height}} \begin{bmatrix} 1 & 1 & \cdots & 1 \\ 1 & 1 & \cdots & 1 \\ \vdots & \vdots & \ddots & \vdots \\ 1 & 1 & \cdots & 1 \\ \end{bmatrix} ksize.widthksize.height1 111111111

对于图像中的像素,滤波后的像素为:

g ( x , y ) = 1 M ∑ f ∈ S f ( x , y ) g(x,y) = \frac{1}{M} \sum_{f \in S} f(x,y) g(x,y)=M1fSf(x,y)

计算示例如下图:边框保留不变,遍历图像所有像素,计算像素周围像素的均值并替代值。

均值滤波计算示例

均值滤波不能保护图像的细节,在图像去燥的同时也破坏了图像的细节部分。

1.1.2 OpenCV实现

blur()函数实现了均值滤波。该函数定义如下:

void blur( InputArray src, OutputArray dst,Size ksize, Point anchor=Point(-1,-1),int borderType=BORDER_DEFAULT );

参数说明:

  • src: 输入的图像。
  • dst: 输出处理后的图像。
  • ksize:核大小。
  • anchor:表示锚点,即被平滑的点。如果是负值则表示取核的中心为锚点。
  • borderType:处理边界的模式,BORDER_DEFAULT为无处理。

代码处理演示:

#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
using namespace std;
using namespace cv;
#define IMAGE_PATH	"../ImageSet/wgj_5.jpg"
void AverageFilter(Mat img)
{Mat dstImage;Mat img_resize;resize(img, img_resize, cv::Size(img.cols/4, img.rows/4),0.0,0.0, cv::INTER_LINEAR);imshow("Org Image", img_resize);blur(img_resize, dstImage, Size(5,5));imshow("Average Filter", dstImage);
}
int main()
{Mat img = imread(IMAGE_PATH);if(img.empty()){cout<<"Read image failed"<<endl;return 0;}AverageFilter(img);waitKey(0);
}

对比结果如下:

均值滤波效果对比

核越大,处理后的图像越模糊。

1.2 中值滤波

1.2.1 中值滤波核

中值滤波是一种非线性滤波器,以3*3大小的核为中值滤波核,则取9个像素的中值像素替换原像素。核定义如下:

$$

\text{mid} \begin{bmatrix}
1 & 1 & \cdots & 1 \
1 & 1 & \cdots & 1 \
\vdots & \vdots & \ddots & \vdots \
1 & 1 & \cdots & 1 \
\end{bmatrix}
$$

计算方法如下:

g ( x , y ) = median { f ( x − 1 , y − 1 ) , f ( x , y − 1 ) , f ( x + 1 , y − 1 ) , f ( x − 1 , y ) , f ( x , y ) , f ( x + 1 , y ) , f ( x − 1 , y + 1 ) , f ( x , y + 1 ) , f ( x + 1 , y + 1 ) } g(x,y) = \text{median} \left\{ \begin{aligned} &f(x-1,y-1), f(x,y-1), f(x+1,y-1), \\ &f(x-1,y), f(x,y), f(x+1,y), \\ &f(x-1,y+1), f(x,y+1), f(x+1,y+1) \end{aligned} \right\} g(x,y)=median f(x1,y1),f(x,y1),f(x+1,y1),f(x1,y),f(x,y),f(x+1,y),f(x1,y+1),f(x,y+1),f(x+1,y+1)

计算示例如下图所示:

中值滤波计算示例

中值滤波对脉冲噪声有良好的滤除作用,可以保留图像的边缘信息。

1.2.2 OpenCV实现

OpenCV将均值滤波封装在medianBlur()函数中,定义如下:

void medianBlur( InputArray src, OutputArray dst, int ksize );
  • 参数src:输入原始图像。
  • 参数dst:输出处理后的图像。
  • 参数ksize:中值滤波核的大小,必须设置为奇数。

代码处理演示:

#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
using namespace std;
using namespace cv;
#define IMAGE_PATH	"../ImageSet/wgj_3.jpg"
void MedianFilter(Mat img)
{Mat dstImage;medianBlur(img, dstImage, 3);imshow("medianFilter", dstImage);
}
int main()
{Mat img = imread(IMAGE_PATH);if(img.empty()){cout<<"Read image failed"<<endl;return 0;}Mat img_resize;resize(img, img_resize, cv::Size(img.cols/4, img.rows/4),0.0,0.0, cv::INTER_LINEAR);imshow("Raw Image", img_resize);MedianFilter(img_resize);waitKey(0);
}

处理效果如下图,可以发现一些小颗粒都会被滤除,但线条不会模糊。

中值滤波效果

1.3 高斯滤波

高斯滤波是一种线性滤波器,能够有效抑制噪声,平滑图像。其作用原理和均值滤波类似,都是取滤波器窗口内的像素均值作为输出,只是窗口模板的系数不同,均值滤波模块系数全部为1,而高斯滤波器的系数随着距离模板中心的增大而减小。所以高斯滤波器相比于均值滤波器对图像的模糊程度较小。

1.3.1 高斯分布

一维的高斯分布定义如下:

一维高斯分布

二维的高斯分布:

二维高斯分布

对于窗口大小为(2k+1)*(2k+1)的模板,高斯核计算公式如下:

H i , j = 1 2 π σ 2 e − ( i − k − 1 ) 2 + ( j − k − 1 ) 2 2 σ 2 H_{i,j} = \frac{1}{2\pi\sigma^2} e^{-\frac{(i - k - 1)^2 + (j - k - 1)^2}{2\sigma^2}} Hi,j=2πσ21e2σ2(ik1)2+(jk1)2

高斯核有小数形式和整数形式,如果是整数形式则需对其归一化处理,将左上角的数值归一化为1,例如33和55的高斯滤波器核:

高斯滤波器核示例

1.3.2 OpenCV实现

OpenCV将高斯滤波封装在GaussianBlur()函数中,定义如下:

void GaussianBlur(InputArray src,OutputArray dst, Size ksize,double sigmaX, double sigmaY = 0,int borderType = BORDER_DEFAULT);
  • 参数src:输入图像。
  • 参数dst:输出图像。
  • 参数ksize:高斯核大小,一般用Size(w,h)表示核的大小,w为像素宽度,h为像素高度,w与h可以不同,但必须是奇数或者0。
  • 参数sigmaX:表示高斯核函数在X方向的标准差。
  • 参数sigmaY:表示高斯核函数在Y方向的标准差。
  • 参数borderType:用于推断图像外部像素的某种边界模式,一般忽略。

代码实现:

#include <iostream>
#include <vector>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
using namespace std;
using namespace cv;
#define IMAGE_PATH	"../ImageSet/wgj_4.png"
void Gaussian(Mat img)
{Mat dstImage;Mat img_ori;img_ori = img(Rect(0,0, img.cols, img.rows/2));GaussianBlur(img_ori, dstImage, cv::Size(5,5), 0,0);dstImage.copyTo(img_ori);imshow("GaussianFilter", img);
}
int main()
{Mat img = imread(IMAGE_PATH);if(img.empty()){cout<<"Read image failed"<<endl;return 0;}Mat img_resize;resize(img, img_resize, cv::Size(img.cols/4, img.rows/4),0.0,0.0, cv::INTER_LINEAR);imshow("Raw Image", img_resize);Gaussian(img_resize);waitKey(0);
}

处理效果如下图:图像上半部分模糊处理了,下半部分未处理。

高斯滤波效果

1.4 双边滤波

双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。

1.4.1 算法原理

双边滤波的改进就在于在采样时不仅考虑像素在空间距离上的关系,同时加入了像素间的相似程度考虑。双边滤波器比高斯滤波多了一个高斯方差sigma-d,它是基于空间分布的高斯滤波函数,所以在边缘附近,离的较远的像素不会太多影响到边缘上的像素值,这样就保证了边缘附近像素值的保存。但是由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤波。对于脉冲噪声,双边滤波会把它当成边缘从而不能去除。

双边滤波器输出像素的值依赖于领域像素值的加权值组合,定义如下:

H i , j = 1 2 π σ 2 e − ( i − k − 1 ) 2 + ( j − k − 1 ) 2 2 σ 2 H_{i,j} = \frac{1}{2\pi\sigma^2} e^{-\frac{(i - k - 1)^2 + (j - k - 1)^2}{2\sigma^2}} Hi,j=2πσ21e2σ2(ik1)2+(jk1)2

加权系数w(i, j, k, l)取决于定义域核和值域核的乘积。其中定义域核表示如下:

d ( i , j , k , l ) = exp ⁡ ( − ( i − k ) 2 + ( j − l ) 2 2 σ d 2 ) d(i,j,k,l) = \exp\left(-\frac{(i - k)^2 + (j - l)^2}{2\sigma_d^2}\right) d(i,j,k,l)=exp(2σd2(ik)2+(jl)2)

定义域核模板如图所示:

定义域核模板

值域核定义:

d ( i , j , k , l ) = exp ⁡ ( − ( i − k ) 2 + ( j − l ) 2 2 σ d 2 ) d(i,j,k,l) = \exp\left(-\frac{(i - k)^2 + (j - l)^2}{2\sigma_d^2}\right) d(i,j,k,l)=exp(2σd2(ik)2+(jl)2)

值域核模板:

值域核模板

则它们的乘积为:

w ( i , j , k , l ) = exp ⁡ ( − ( i − k ) 2 + ( j − l ) 2 2 σ d 2 − ∥ f ( i , j ) − f ( k , l ) ∥ 2 2 σ r 2 ) w(i,j,k,l) = \exp\left(-\frac{(i - k)^2 + (j - l)^2}{2\sigma_d^2} - \frac{\|f(i,j) - f(k,l)\|^2}{2\sigma_r^2}\right) w(i,j,k,l)=exp(2σd2(ik)2+(jl)22σr2f(i,j)f(k,l)2)

1.4.2 OpenCV实现

OpenCV将双边滤波封装在bilateralFilter()函数中,定义如下:

void bilateralFilter( InputArray src, OutputArray dst, int d,double sigmaColor, double sigmaSpace,int borderType=BORDER_DEFAULT );
  • 参数src:输入图像。
  • 参数dst:输出图像。
  • 参数d:表示在滤波过程中每个像素邻域的直径。
  • 参数sigmaColor:表示颜色空间滤波器的sigma值,这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
  • 参数sigmaSpace:坐标空间的标准差。它的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。
  • 参数borderType:处理边界像素的模式。

代码实现:

void bilateralFilter( InputArray src, OutputArray dst, int d,double sigmaColor, double sigmaSpace,int borderType=BORDER_DEFAULT );

效果如图所示。

双边滤波效果

1.5 导向滤波

均值滤波、中值滤波、高斯滤波等简单的滤波,都有一个共同的弱点,即他们都属于各向同性滤波。一幅图像可以被看成是有区域(过渡平缓,也就是梯度较小)和边缘(图像的纹理、细节等)共同组成。噪声的特点通常是以其为中心的各个方向上的梯度都比较大而且相差不多。边缘则不同,边缘只有在其法向方向上才会出现较大的梯度,而在切线方向上梯度较小。

导向滤波能保边平滑,抠图,可应用在图像增强、HDR压缩、图像抠图以及图像去雾等场景。

1.5.1 算法原理

导向滤波之所以叫这个名字,是因为在算法框架中,要对图像p进行滤波得到图像q,还需要一个引导图像I。滤波输出定义为:

q i = ∑ j ∈ w i W i , j ( I ) ⋅ p j q_i = \sum_{j \in w_i} W_{i,j}(I) \cdot p_j qi=jwiWi,j(I)pj

引导图像I可以是单独的一幅图像也可以是输入图像p本身。

导向滤波的示意图如下图所示。

导向滤波示意图

该模型认为,在导向图像与滤波输出之间的一个二维窗口内是一个局部线性模型,即:

q i ​ = a i ​ I i ​ + b i ​ , ∀ i ∈ w k ​ qi​=ai​Ii​+bi​,∀i∈wk​ qi=aiIi+bi,iwk

导引图像与q之间存在线性关系,这样设定是因为我们希望导引图像提供的是信息主要用于指示哪些是边缘哪些是区域,所以在滤波时,如果导引图告诉我们这里是区域,那么就将其磨平。如果导引图告诉我们这里是边缘,这在最终的滤波结果里就要设法保留这些边缘信息。只有当I和q之间是线性关系的这种引导关系才有意义。

两边同时取梯度可以得到:

∇ q = a ∇ I ∇q=a∇I q=aI

即输入图像与输出图像有类似的梯度,也就是导向滤波有边缘保持特性。

现在已知I和p,要求出q。如果能求的参数a和b,显然能通过I和q之间的线性关系求出q。由于p是q受到噪声污染而产生的退化图像,假设噪声是n,则有:

q i ​ = p i ​ − n i ​ qi​=pi​−ni​ qi=pini

我们希望求出q与真实p之间的差距最小,于是转化为最优化问题,即计算:

a r g m i n ∑ i ∈ ω k ​​ ( a k ​ I i ​ + b k ​ − p i ​ ) 2 argmin∑i∈ωk​​(ak​Ii​+bk​−pi​)2 argminiωk​​(akIi+bkpi)2

于是便得到了最小二乘问题。即求解下式对应的参数a和b。

a ‾ i = 1 ∣ ω ∣ ∑ k ∈ ω i a k \overline{a}_i = \frac{1}{|\omega|} \sum_{k \in \omega_i} a_k ai=ω1kωiak
b ‾ i = 1 ∣ ω ∣ ∑ k ∈ ω i b k \overline{b}_i = \frac{1}{|\omega|} \sum_{k \in \omega_i} b_k bi=ω1kωibk

其中ε为防止a过大的归一化参数,可以求得:

a k = 1 ∣ ω ∣ ∑ i ∈ ω k I i p i − μ k p ‾ k σ k 2 + ϵ a_k = \frac{\frac{1}{|\omega|} \sum_{i \in \omega_k} I_i p_i - \mu_k \overline{p}_k}{\sigma_k^2 + \epsilon} ak=σk2+ϵω1iωkIipiμkpk
b k = p ‾ k − a k μ k b_k = \overline{p}_k - a_k \mu_k bk=pkakμk

其中μk是图像I在窗口ωk中的平均值,Pk是待滤波图像p在窗口ωk中的均值,σk是I在窗口ωk中的标准差|ω|是窗口ωk中像素的数量。

在计算每个窗口的线性系数时,我们可以发现一个像素会被多个窗口包含,也就是说,每个像素都由多个线性函数所描述。因此,如之前所说,要具体求某一点的输出值时,只需将所有包含该点的线性函数值平均即可,如下:

q i = 1 ∣ ω ∣ ∑ k : i ∈ ω k ( a k I i + b k ) = a ‾ i I i + b ‾ i q_i = \frac{1}{|\omega|} \sum_{k: i \in \omega_k} (a_k I_i + b_k) = \overline{a}_i I_i + \overline{b}_i qi=ω1k:iωk(akIi+bk)=aiIi+bi

其中:

a ‾ i = 1 ∣ ω ∣ ∑ k ∈ ω i a k \overline{a}_i = \frac{1}{|\omega|} \sum_{k \in \omega_i} a_k ai=ω1kωiak
b ‾ i = 1 ∣ ω ∣ ∑ k ∈ ω i b k \overline{b}_i = \frac{1}{|\omega|} \sum_{k \in \omega_i} b_k bi=ω1kωibk

一些特殊情况:

  • 当引导图为输入图像时,引导滤波就成为一个保边滤波操作。
  • 如果ε=0,则a=1,b=0,这是滤波器没有任何作用,输出与输入一致。
  • 如果ε>0,在像素强度变化小的区域,a近似为0,而b近似pk,即加权滤波。在变化大的区域,a近似为1,b近似为0,对图像的滤波效果很弱,有助于保持边缘。

1.5.2 OpenCV实现

OpenCV中将导向滤波封装在cv::ximgproc::guidedFilter()函数中,该函数定义如下:

void guidedFilter(InputArray guide, InputArray src, OutputArray dst, int radius, double eps, int dDepth = -1);
  • 参数guide:导向图。
  • 参数src:输入图像。
  • 参数dst:输出图像。
  • 参数radius:窗口半径。
  • 参数eps: 归一化的ε参数。
  • 参数dDepth:输出图像的深度。

代码实现:

#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/ximgproc.hpp"using namespace std;
using namespace cv;#define IMAGE_PATH	"../ImageSet/葵花.png"
void GuideFilter(Mat img)
{Mat dstImage;cv::ximgproc::guidedFilter(img,img, dstImage, 5, 0.06f*255*255, -1);imshow("guide filter", dstImage);
}
int main()
{Mat img = imread(IMAGE_PATH);if(img.empty()){cout<<"Read image failed"<<endl;return 0;}Mat img_resize;resize(img, img_resize, cv::Size(img.cols/2, img.rows/2),0.0,0.0, cv::INTER_LINEAR);imshow("Raw Image", img_resize);GuideFilter(img_resize);waitKey(0);
}

效果对比:

导向滤波效果

更多资料:https://github.com/0voice

http://www.dtcms.com/a/515117.html

相关文章:

  • CSS 列表详解
  • 建设工程规范下载网站商城网站开发的完整流程
  • 同德县网站建设公司海南网站建设及维护
  • 广西送变电建设公司网站深圳市建设工程造价站官网
  • 网站获取访问者qq号码专业的网页设计和网站制作公司
  • 网站建设费账务处理a站下载
  • 哈尔滨网站建设丿薇建立短语
  • 徐州seo网站推广网站开发 页面功能布局
  • 用extjs做的网站wps如何做网站
  • 青羊区建设局网站怎样入驻微信小程序
  • 网站标题几个字合适学生个人网页制作html代码
  • 网站设计规划信息技术教案枣庄三合一网站开发
  • 提升网站流量电子邮件免费注册
  • 广东住房和城乡建设厅官方网站运维工程师累吗
  • 宁波江北区建设局网站如何用wordpress上传根目录
  • 建设实业公司网站设计模板哪家网站做民宿好
  • 网站质量需求页面设计的网站
  • 有经验的南昌网站制作小白 宝塔 wordpress
  • 网站建设引入谷歌地图wordpress淘宝内容
  • 国外网站做网上生意哪个好创可贴网页设计网站
  • 福田附近做网站公司线上销售平台都有哪些
  • app网站开发成本哈尔滨seo优化客户
  • 建设网站的项目策划书网站建设毕业设计模板
  • 微网站自己怎么做的大连旅游网站建设
  • 玉林市建设工程交易中心网站怎样创建自己的公众号
  • 企业网站内使用了哪些网络营销方式线上编程课推荐哪一个
  • 我的世界做神器指令网站wordpress sso插件开发
  • 网站建设应遵循哪几项原则tomcat安装wordpress
  • 手机网站开发语言微分销平台登陆
  • 网站开发什么语言比较好怎样重新安装电脑wordpress