本节为图像空域增强的第三篇,介绍重要的图像空域增强技术:邻域处理。
通过本节的学习,读者将了解邻域处理的基本概念,包括邻域的概念,以及相关和卷积运算,在此基础之上,重点介绍两类用于图像增强的邻域处理技术:平滑和锐化。本节将主要介绍邻域处理中的相关和卷积 运算,进而引出其线性平滑滤波的内容。
与其他章节不同,本节将主要使用Skimage的兄弟库,SciPy的ndimage模块中的部分函数。
目录
5.4 邻域处理
邻域处理是由邻域和定义的操作两个因素构成,其中邻域因素主要包括邻域的尺寸和形状,邻域操作指的是对该邻域内各像素点的处理方法。
在信号处理领域,一般又将邻域处理称为“空域滤波”处理,所用到的算子称为“滤波器(Filter)”。滤波器也被称为 “核(Kernel)”、“窗口(Window)”、“掩模/模板(Mask)”、“算子(Operator)”。它们的名称不同,但基本含义是一致的。一般而言,在信号处理中称为 “滤波器(Filter)”,在数学领域称为 “核”。
线性滤波器就是指基于线性核的滤波,最常见的两种线性运算是相关运算和卷积运算。
5.4.1 相关与卷积
(a)相关运算
相关运算 (Correlation operation)是利用模板对图像进行邻域操作:将滤波器模板的中心移动到待处理的像素点,对模板区域的各点加权相乘后求和。
大小为(2𝑚+1)×(2𝑛+1)的核(模板)𝑤与图像𝑓(𝑥,𝑦)的相关运算(𝑤⊙𝑓)(𝑥,𝑦) 定义为:
相关运算的计算步骤一般包括平移、计算和赋值三个步骤,具体如下:
- 平移:将模板在图像中逐点移动,模板中心移动到被处理的像素点上;
- 计算:将模板区域中的各点的系数(权值)与图像的像素值相乘,对乘积求和,即加权求和;
- 赋值:将加权求和结果赋值给模板中心的像素。
(相关运算过程图示,来自互联网)
(b)卷积运算
卷积运算 (Convolution operation)也是利用模板对图像进行邻域操作,只是把相关运算的模板进行水平和垂直方向上的翻转处理,等效为将模板旋转180。
大小为(2𝑚+1)×(2𝑛+1)的核(模板)𝑤与图像𝑓(𝑥,𝑦)的相关运算(𝑤∗𝑓)(𝑥,𝑦) 定义为:
卷积运算的计算步骤包括旋转(翻转)、平移、计算、赋值四个步骤,具体如下:
- 旋转:将模板沿中心点旋转180°;
- 平移:将模板在图像中逐点移动,模板中心移动到被处理的像素点上;
- 计算:将模板区域中的各点的系数(权值)与图像的像素值相乘,对乘积求和,即加权求和;
- 赋值:将加权求和结果赋值给模板中心的像素。
下图所示是相关运算和卷积运算的一个实例。对照相关运算的过程不难发现,卷积运算完成第一步旋转操作之后,剩下的步骤和相关运算完全一致。
(c)相关和卷积的实现
Skimage并没有提供单独实现相关和卷积操作的函数,而是直接调用它的父类SciPy中的另外一个子库ndimage模块(你可以认为是调用它兄弟的函数)完成相关和卷积操作。
给出SciPy中的ndimage模块的链接,便于大家参考。该模块提供了若干个针对图像处理底层操作的函数,主要包括了Filters、Fourier filters、Interpolation、Measurements、Morphology五个子模块,本节将用到Filters子模块中的部分函数。
在ndimage中使用correlate函数完成2D相关运算。对于1D相关运算,ndimage使用correlate1d完成,在图像处理领域较少使用,不再单独介绍,读者可自行查阅官网。
correlation函数完成相关处理。
看一下correlation函数的声明:
ndimage.correlate(input, weights, output, mode, cval, origin)
部分参数说明:
- input:输入数据,可以是任意维数。
- weights:加权系数矩阵,维数与输入数据相同。
- output:输出数据,与输入数据维数相同。
- mode:边界延拓方式,类型包括‘reflect’, ‘constant’, ‘nearest’, ‘mirror’, ‘wrap’。各种填充方式的说明,见下表。
- cval:如果边界延拓方式设置为常数值填充时对应的数值,默认值为0。
- origin:模板参考点对齐位置,默认值为0,对应于模板的中心点。
序号 | 延拓方式名称 | 关键字 | 说明 |
---|---|---|---|
1 | 反射延拓(默认值) | ‘reflect’ | (d c b a | a b c d | d c b a) |
2 | 常值延拓 | ‘constant’ | (k k k k | a b c d | k k k k) |
3 | 最近邻延拓 | ‘nearest’ | (a a a a | a b c d | d d d d) |
4 | 镜像延拓 | ‘mirror’ | (d c b | a b c d | c b a) |
5 | 环绕延拓 | ‘wrap’ | (a b c d | a b c d | a b c d) |
以下是一段计算并显示用一个3*3模板对扩展后的5*5数据块进行相关运算的过程示例。
from scipy.ndimage import correlate
import numpy as np
input_img = np.arange(25).reshape(5,5)
weights = [[0, 1, 0], [1, 1, 1], [0, 1, 0]]
correlate(input_img, weights)
输出为:
array([[ 6, 10, 15, 20, 24],
[ 26, 30, 35, 40, 44],
[ 51, 55, 60, 65, 69],
[ 76, 80, 85, 90, 94],
[ 96, 100, 105, 110, 114]])
具体计算过程请自行验证。
在ndimage中使用convolve函数完成2D卷积运算。 ndimage使用convolve1d函数完成1D卷积运算,但1D卷积在图像处理领域较少使用,不再单独介绍,读者可自行查阅官网。
convolve函数完成卷积运算
看一下convolve函数的声明:
ndimage.convolve(input, weights, output, mode, cval, origin)
部分参数说明:(与卷积运算的内容完全相同,不再重复)
以下是一段计算并显示用一个3*3模板对边界采用0值填充的4*4数据块进行卷积运算的过程示例。
import numpy as np
from scipy import ndimage
img = np.array([[1, 2, 0, 0],
[5, 3, 0, 4],
[0, 0, 0, 7],
[9, 3, 0, 0]])
m = np.array([[1,1,1],[1,1,0],[1,0,0]])
ndimage.convolve(img, m, mode='constant', cval=0.0)
输出为:
array([[11, 10, 7, 4],
[10, 3, 11, 11],
[15, 12, 14, 7],
[12, 3, 7, 0]])
具体计算过程请自行验证。
5.4.2 线性平滑滤波器
平滑滤波 (Smooth filtering)也称为低通平滑滤波,可用于抑制图像中的灰度突变,使图像变得模糊,是低频增强的空间域滤波技术。
平滑滤波常用于:
- 模糊图像和图像降噪;
- 在图像重取样前平滑图像以减少混淆;
- 减少图像中无关的细节;
- 平滑因灰度级不足所导致的图像的伪轮廓。
线性空间滤波是指图像与滤波器核(卷积核)进行卷积计算。平滑卷积核与图像的卷积类似于积分运算,对图像的邻域进行加权求和,可以实现空间域平滑滤波。本节主要介绍两种线性平滑滤波器器:盒滤波器和高斯滤波器。
(a) 盒滤波器
盒式核(Box filter)是一种简单的可分离低通滤波器核。盒式核的模板区域通常取正方形,且模板内各点的权重值相同,且总和为1。比如 ,常用的一种3*3盒滤波器,各点的加权值为1/9。
有两种方式实现盒滤波器。一种是调用前面提到的convolve函数,这种方式需要人工指定盒滤波器的模板。另一种是调用ndimage中提供的uniform_filter函数。
uniform_filter函数完成相关处理。
看一下uniform_filter函数的声明:
ndimage.uniform_filter(input, size, output, mode, cval, origin, axes)
部分参数说明:
- input:输入数据,可以是任意维数。
- size:模板大小,正方形模板,默认值为3。
- output:输出数据,与输入数据维数相同。
- mode:边界延拓方式,类型包括‘reflect’, ‘constant’, ‘nearest’, ‘mirror’, ‘wrap’。
- cval:如果边界延拓方式设置为常数值填充时对应的数值,默认值为0。
- origin:模板参考点对齐位置,默认值为0,对应于模板的中心点。
- axes:标志位,如果设为None,则表示在各个轴上进行滤波;否则,在特定轴上进行滤波。
返回值:
- uniform_filter:滤波后的图像,与输入图像维数相同。
有关盒滤波器的性能讨论,可参考下面内容。
(b) 高斯滤波器
实际应用中要求卷积核是各向同性的(圆对称),其响应与方向无关。高斯核是唯一可分离的圆对称核,因此非常适合图像处理,对于去除图像中的随机噪声非常有效。
高斯核的数学表达式为:
式中,𝜎值决定了函数衰减的速度,进而影响滤波器的平滑效果,𝜎值越大,所需模板尺寸越大,平滑效果越明显,当然,计算量也就越大。
有两种实现高斯滤波器的方式,一种是调用Skimage中的filter.gaussian函数,另一种是调用ndimage中的gaussian_filter函数。以下是两个函数的声明,经对比不难发现,两者功能几乎完全相同。
ndimage.gaussian_filter(input, sigma, order, output, mode, cval, truncate, radius, axes)
filters.gaussian(image, sigma, output, mode, cval, preserve_range, truncate, channel_axis)
部分参数说明:
- input / image:输入数据,可以是任意维数。
- sigma:所用高斯核的方差值,可以是一列数(每个值代表各方向轴上方差大小,)。
- output:输出数据,与输入数据维数相同。
- order:ndimage.gaussian特有参数,默认为0,表示一般的高斯滤波;如果设为正整数,表示与高阶高斯函数进行卷积(此处有个疑问,高斯函数的导数,仍然是高斯函数,为何要专门设置该参数?)。
- mode:边界延拓方式,类型包括‘reflect’, ‘constant’, ‘nearest’, ‘mirror’, ‘wrap’。
- cval:如果边界延拓方式设置为常数值填充时对应的数值,默认值为0。
- preserve_range:与图像数据格式有关的设置,Skimage.filter.gaussian特有参数。
- origin:截断设置,在特定倍数的方差处进行截断,默认值是4.0。
- axes / channel_axis:标志位,如果设为None,则表示在各个轴上进行滤波;否则,在特定轴上进行滤波。
返回值:
- gaussian_filter:滤波后的图像,与输入图像维数相同。
上述两个函数功能非常接近,但还是略有差异,比如:
- skimage.filter.gaussian函数边界延拓默认方式是'nearest'(最近邻),ndimage.gaussian_filter函数边界延拓默认方式是'reflect'(反射)。
- skimage.filter.gaussian函数会自动将数据转换为实型数据
(c) 综合实例
以下一段代码是分别使用盒滤波器和高斯平滑滤波器对图像进行平滑处理的代码。有关两类平滑滤波器平滑性能的分析与比较,可查阅参考文献1。
from scipy import ndimage, datasets
import matplotlib.pyplot as plt
ascent = datasets.ascent()
result1 = ndimage.uniform_filter(ascent, size=5)
result2 = ndimage.gaussian_filter(ascent, sigma=5)
fig = plt.figure()
plt.gray() # show the filtered result in grayscale
ax1 = fig.add_subplot(131)
ax2 = fig.add_subplot(132)
ax3 = fig.add_subplot(133)
ax1.imshow(ascent)
ax2.imshow(result1)
ax3.imshow(result2)
plt.show()
(本节初稿完成时间:2024-02-14)
(欢迎对DIP+python算法开发感兴趣的初学者,尤其是相关专业本科和低年级研究生关注,本专栏完将持续更新,总篇数不会少于50篇,每篇不会少于5000字,专栏完成之前(差不多到2024年5月份)完全免费阅读,敬请关注)