图像的线性滤波/卷积

效果

sobel

  • 左上为y方向滤波,右上为x方向滤波,下图为两种滤波的叠加

原理部分

  • 线性滤波可以说是图像处理最基本的方法,它允许我们对图像进行处理,产生很多不同的效果。
    在这里插入图片描述
卷积
  • 卷积的数学定义:
    卷积公式
    一般称g为作用在f上的filter或kernel

对于滤波器,也有一定的规则要求:

  • 滤波器的大小应该是奇数,这样它才有一个中心,例如3x3,5x5或者7x7。有中心了,也有了半径的称呼,例如5x5大小的核的半径就是2。
  • 滤波器矩阵所有的元素之和应该要等于1,这是为了保证滤波前后图像的亮度保持不变。但这不是硬性要求。
  • 如果滤波器矩阵所有元素之和大于1,那么滤波后的图像就会比原图像更亮,反之,如果小于1,那么得到的图像就会变暗。如果和为0,图像不会变黑,但也会非常暗。
  • 对于滤波后的结构,可能会出现负数或者大于255的数值。对这种情况,我们将他们直接截断到0和255之间即可。对于负数,也可以取绝对值。只针对图像。

在具体应用中,往往有多个卷积核,可以认为,每个卷积核代表了一种图像模式。如果某个图像块与此卷积核卷积出的值大,则认为此图像块十分接近于卷积核。

  • 例如,如果我们设计了6个卷积核,可以理解:我们认为这个图像上有6种底层纹理模式,也就是我们永6种基础模式就能描绘出一幅图像。

  • 用Gx或Gy来卷积下面这张图的话,就会在中间黑白边界获得比较大的值。
    在这里插入图片描述
    在非边界部分,得到结果为0(黑色),在边界部分,得到结果取绝对值并截断为255(白色)

卷积的应用——一个没有任何效果的卷积
  • 将原像素中间像素值乘1,其余全部乘0。
    显然像素值不会发生任何变化。
    在这里插入图片描述
平滑均值滤波
  • 取九个值的平均值代替中间像素值,起到平滑的效果。
    平滑均值滤波
高斯平滑
  • 高斯平滑水平和垂直方向呈现高斯分布,更突出了中心点在像素平滑后的权重,相比于均值滤波而言,有着更好的平滑效果。
    高斯平滑
图像锐化
  • 图像锐化使用的是拉普拉斯变换核函数
    图像锐化
Sobel边缘检测
  • Sobel更强调了和边缘相邻的像素点对边缘的影响。
    Sobel边缘检测
卷积解决的问题
  • 卷积负责提取图像中的局部特征
卷积–步长/Stride

如果用(f, f)的过滤器来卷积一张(h, w)大小的图片,每次移动一个像素的话,那么得出的结果就是(h-f+1, w-f+1)的输出结果。f是过滤器大小,h和w分别是图片的高宽。
如果每次不止移动一个像素,而是s个像素,那么结果就会变为:
在这里插入图片描述
这个s就叫做步长

存在的问题:

  • 只要是f或s的值比1要大的话,那么每次卷积之后结果的长款,要比卷积之前小一些
  • 丢失信息

因此,我们可以在外围补上一圈值为0的像素

padding
有了填充之后,每次卷积之后的图像大小:
在这里插入图片描述
p表示填充的padding圈数,每填充一圈长/宽增加2
此时如果想让高(宽)不变(步长为1时):
在这里插入图片描述
计算得到:
在这里插入图片描述

卷积——三种填充模式

橙色部分为image, 蓝色部分为filter。从左往右分别是:full、same、valid模式
三种填充模式
注意:这里的same还有一个意思,卷积之后输出的feature map尺寸保持不变(相对于输入图片)。当然,same模式不代表完全输入输出尺寸一样,也跟卷积核的步长有关系。same模式也是最常见的模式,因为这种模式可以在卷积过程中让图的大小保持不变。

多通道卷积

在这里插入图片描述

  • 蓝色部分表示原图的三个通道映射图片
  • 红色的两列W0, W1表示对应着两种特征提取。因为这里图像分解为三通道,所以每个特征提取还要再细分为对三个通道的不同卷积
  • 对于一个特征提取(如W0),计算方式为,将三个通道的卷积分别计算后累加,得到Output。绿色部分的两幅图则分别对应W0列,W1列的三个通道卷积累加的计算结果
  • 注意:上述例子的卷积计算中的步长stride = 2
卷积核的确定
  • CNN厉害的地方在于,过滤器的特征并不是人为设定的,而是通过大量图片自己训练出来的

代码部分(以Sobel边缘检测为例)

"""
@author: Hanley-Yang

sobel:边缘检测
"""

import cv2
from matplotlib import pyplot as plt

'''
Sobel函数求完导数后会有负值,还有会大于255的值。
而原图像是uint8,即8位无符号数(范围在[0,255]),所以Sobel建立的图像位数不够,会有截断。
因此要使用16位有符号的数据类型,即cv2.CV_16S
'''
img = cv2.imread('Euphonium.png')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

x = cv2.Sobel(img_gray, cv2.CV_16S, 1, 0)
y = cv2.Sobel(img_gray, cv2.CV_16S, 0, 1)

'''
在经过处理后,别忘了用convertScaleAbs()函数将其转回原来的uint8形式。
否则将无法显示图像,而只是一副灰色的窗口。
dst = cv2.convertScaleAbs(src[, dst[, alpha[, beta]]])  
其中可选参数alpha是伸缩系数,beta是加到结果上的一个值。结果返回uint8类型的图片。
'''

absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)

'''
由于Sobel算子是在两个方向计算的,最后还需要用cv2.addWeighted(...)函数将其组合起来
。其函数原型为:
dst = cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])  
其中alpha是第一幅图片中元素的权重,beta是第二个的权重,
gamma是加到最后结果上的一个值。
'''
dst = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)

rgb_absX = cv2.cvtColor(absX, cv2.COLOR_BGR2RGB)
rgb_absY = cv2.cvtColor(absY, cv2.COLOR_BGR2RGB)
rgb_dst = cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)

plt.subplot(221)
plt.imshow(rgb_absX)

plt.subplot(222)
plt.imshow(rgb_absY)

plt.subplot(223)
plt.imshow(rgb_dst)

plt.show()

  • 输出结果
    在这里插入图片描述
    左上为y方向滤波,右上为x方向滤波,下图为两种滤波的叠加
  • 39
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Hanley_Yeung

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

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

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

打赏作者

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

抵扣说明:

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

余额充值