数字图像处理篇(4)图像增强之平滑操作及opencv实现

目录

一、噪声

1、椒盐噪声

2、高斯噪声

二、平滑

1、引言

2、中值滤波

3、邻域平均法

4、加权法

三、2D卷积

四、边缘样式


        思考一个问题:假如你是灰太狼,你是否愿意吃掉一只满身长满黑点点、脏兮兮的小羊?那么我们将如何处理这只羊,让这只羊更干净一点?                                                                                

一、噪声

        对于一张照片来说,我们会从很多个角度去评判照片的好坏。比如说拍的亮还是暗、图像内容是好还是坏、拍摄角度是偏还是正等等。但是,对下面这张图像来说,我们多半不会觉得特别好看。

         “点点”这么多,谁看了都会觉得不舒服吧(别抬杠啊!个别觉得这图好看的别来沾边),而这种“点点”我们形象的称之为噪点,也称作噪声,它的形成有很多种方式,但是我们并不希望图片会因为噪声的存在而变差。

下面我们将介绍两种噪声及其形成原因:

1、椒盐噪声

        老一辈的人总是对我们年轻人说,“我吃过的盐比你吃过的饭还多”,众所周知,“盐”是一种白色的小颗粒,在噪声中,我们把图片中全是“白点点”的这种噪声形象的称为盐噪声。那么,以此类推,椒噪声应该指的是图片中全是“绿点点”还有“红点点”的这种噪声,毕竟椒嘛,有辣椒还有青椒……,开个玩笑,椒当然指的不是普通的辣椒啦,它指的是黑胡椒。黑胡椒大家应该都吃过吧,我去吃西餐的时候点牛排啥的,总要加黑椒酱调味……真的是,越说越饿,朕的御厨在哪里(此时小编在流口水)。所以我们把图片中全是“黑点点”的这种噪声形象的称为椒噪声。当图片中既含有椒噪声又含有盐噪声的这种噪声时,我们把这两种噪声合称为椒盐噪声。

左图为盐噪声,中图为椒噪声,右图为椒盐噪声,大家可以仔细观察一下:

        盐噪声和椒噪声的形成原因可能是图片受到了强烈干扰而产生或者是图片传输时出错。例如失效的感应器导致像素值为最小值,饱和的感应器导致像素值为最大值等等。

2、高斯噪声

        高斯噪声是指它的概率密度函数服从高斯分布的一种噪声。它的形成原因之一是图像传感器在拍摄时不够明亮、亮度不够均匀。比如说,当你在晚上不开灯的情况下,打开手机的拍照功能,你会很明显的发现,手机里的图片并不是“统一的黑”,而是有一部分白点点的存在。感兴趣的读者可以去尝试观察一下。

二、平滑

        “生存还是死亡,躺平摆烂还是努力去寻找解决问题的方法,这是个问题”。那么问题来了,既然这噪点如此难看,那我们应该如何去消灭这些噪点,亦或者是是躺平摆烂,这图片虽然这么难看,但还能看,算了,不管了,将就着看吧……

        打住!小编可不是爱摆烂的人哦,小编当然是更愿意去找解题方法。其中一种方法就是平滑操作。那么请大家跟紧小编的脚步,让我们好好了解平滑的具体操作吧!

1、引言

        让我们通过现象看看噪声在图像里的本质(我们以灰度图像为例,稍微方便一点):

        截取了图片中某一部分,展现出像素值的数组。我们可以看到,因为椒盐噪声的缘故,这个数组里面出现了不少黑点(0)以及白点(255),讨厌死了!

        我们最容易想到的方法就是,能不能用靠近白点以及黑点的像素值,来代替原有的像素值,比如说噪点左边的值来代替。但是缺点也很明显,小编想到了三个缺点:①我们需要先去写一个if语句判断一下这个点的值是不是0或者255(是不是黑点或者白点),再去对这个点进行处理,如果这样子做会使得计算量大大提升,虽然可行,但过于繁琐了。②随机性太强,也就是说,万一这个点左边的值也是一个噪点,根本达不到消除噪点的目的。③对边缘不利,也就是说,对于最左边的这一列,你没有可以参照的值来修改。

        所以,我们采用了几种更为科学普适的方法:中值滤波、邻域平均法平滑以及加权法平滑!

2、中值滤波

        原理:这是一种非线性滤波法。以3*3的核为例,我们先将这3*3=9个像素值由大到小排成一行,选择最中间的(也就是第5名)像素值代替原有的像素值。如果是5*5的,那就是第13名,7*7的就是第15名,以此类推。

        优点:考虑到了绝大多数的边缘,在边缘扩展一行或者一列,不论其大小,以中值代替的值是边缘扩展的像素值的概率很小。并且具有普适性,依据的是周围一圈的值,而不是单个像素值。

dst=cv2.medianBlur(src, ksize) 

变量与参数的含义:

dst:返回值,即中值滤波后得到的结果

src:需要处理的图像

ksize:滤波核(3*3的核,就写成3

        我们来实战一下,对刚刚的这张懒羊羊的噪点图进行5*5的中值滤波处理

import cv2

#将prey_noise.png改成自己的照片名
img=cv2.imread("grey_noise.png",0)
dst=cv2.medianBlur(img, 5)

cv2.imshow("test",dst)
cv2.imwrite("dispose.png",dst)
cv2.waitKey()
cv2.destroyAllWindows()

        处理后的结果如下图,我们能够很明显的发现,噪点神奇般的消失了,但是图像却在一定程度上变得模糊了,这是它的缺点之一。

3、邻域平均法

        原理:这是一种线性滤波的方法,也称作均值滤波。以3*3的部分为例,我们用这9个值的平均值来代替中间的那个值。也就是说,它的核如下图所示,3*3的部分不断与这个核做互相关运算,也就是不断的平均。

         举个例子,对于下面这部分,我们用(23+15+9+38+255+0+30+28+23)/9=47(向下取整)来代替中间的255的值。

         缺点:“过于平均”了,把“自己”与“邻居”看的同样重要,而使自己太容易被改变。

dst=cv2.blur(src,ksize,[anchor,[borderType]])

变量与参数的含义:

dst:返回值,即滤波后得到的结果

src:需要处理的图像

ksize:滤波核(3*3的核,写成(3,3),与中值滤波不同!

anchor:锚点,默认情况下是(-1,-1),表示当前计算均值的点位于核的中心位置

borderType:边缘样式,这个小编待会会讲解

        实战:用均值滤波对噪点图进行处理,核的大小为3*3

import cv2

#grey_png改成自己图片的名字
img=cv2.imread("grey.png",0)

dst=cv2.blur(img, (3,3))

cv2.imshow("test",dst)
cv2.imwrite("dispose.png",dst)
cv2.waitKey()
cv2.destroyAllWindows()

         你会发现,有一说一,这种滤波方式的效果真不怎么样。

4、加权法

         原理:这是一种线性滤波的方法,也称作高斯滤波。以3*3的部分为例,我们用这9个值个自赋予不同的权重计算,用计算出的结果来代替中间的那个值。它的核有很多种,如下图所示,3*3的部分不断与这个核做互相关运算,也就是不断的加权平均。

         举个相同的例子,同样是对于下面这部分,如果用左边的核计算的话,我们将会用(23+15+9+38+2*255+0+30+28+23)/10=68(向下取整)来代替中间的255的值;而用右边的核计算的话则是用(23+2*15+9+2*38+4*255+2*0+30+2*28+23)/16=79来代替。

dst=cv2.GaussianBlur(src,ksize,sigmaX[sigmaY,[borderType]])

变量与参数的含义:

dst:返回值,即滤波后得到的结果

src:需要处理的图像

ksize:滤波核(3*3的核,写成(3,3),与中值滤波不同!

sigmaX:核在水平方向的标准差,越小代表“自己”越重要,默认为0

sigmaY:核在垂直方向的标准差,越小代表“自己”越重要

borderType:边缘样式,这个小编待会会讲解

实战:用加权滤波对噪点图进行处理,核的大小为3*3

import cv2

#grey_png改成自己图片的名字
img=cv2.imread("grey.png",0)

dst=cv2.GaussianBlur(img, (3,3),0,0)

cv2.imshow("test",dst)
cv2.imwrite("dispose.png",dst)
cv2.waitKey()
cv2.destroyAllWindows()

三、2D卷积

        比如说刚刚的高斯滤波,我们并不满足于它给我们提供的核,什么sigmaX,什么sigmaY,我数学差,根本理解不了,我就是要用自己的核,这个时候该怎么办呢?别急,open-cv里面有一个函数,这是专门用于图像与自己给定的核做计算的函数,我们称之为2D卷积函数。

cv2.fliter2D(src,ddepth,kernel,[anchor,[delta,[borderType]]])

dst:返回值,即2D卷积后得到的结果

src:需要处理的图像

ddepth:图像深度,一般用-1表示与原始图像相同

kernel:卷积核,是个单通道的数组

anchor:锚点,默认情况下是(-1,-1),表示当前计算均值的点位于核的中心位置

delta:修正值,这是可选项

borderType:边缘样式,这个小编待会会讲解

比如说,我们用下面这个核进行高斯滤波,我们可以这样写代码:

import cv2
import numpy as np

img=cv2.imread("grey.png",0)

ker = np.array([[1, 2, 1], [1, 2, 1], [1, 1, 1]])*1/10  #kernel
img1 = cv2.filter2D(img, -1, ker, borderType=cv2.BORDER_REFLECT)
   
cv2.imshow("test",img1)
cv2.imwrite("outcome.png",img1)
cv2.waitKey()
cv2.destroyAllWindows()

 结果如下图,可以看出效果并不好。

四、边缘样式

        由于平滑时我们也需要对边缘的像素进行处理,为了得到良好的数据,我们需要对边缘进行处理。

        有很多种扩展方式,比如说aaaaaa|abcdefgh|hhhhhh,这也是用的最多的方式。它的意思如下图(就是复制边缘的这个值来进行扩展):

        其余borderType的取值如下:

         好啦,本期的文章就到此为止啦!小编创作不易,点个赞再走呗!

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

计算机鬼才~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值