数字图像滤波的本质

一、说明

        在数字时代,图像是我们交流和表达不可或缺的一部分。从社交媒体到医学成像,图像的质量和内容非常重要。这就是图像过滤和卷积领域介入的地方,为我们提供了一个转换和完善这些视觉叙事的工具包。

        图像过滤不仅仅是让照片看起来更好;这是关于制作图像的故事。无论是降低医学扫描中的噪音,锐化考古文物的复杂细节,还是检测自动驾驶汽车的边缘,图像过滤器都发挥着关键作用。他们通过强调某些特征同时制服其他特征来塑造叙事。

        这个过程的支柱是卷积操作,这是一个数学奇迹,使我们能够用预定义的过滤器覆盖图像以实现不同的效果。

二、卷积的概念

        卷积是一种基本的数学运算,在图像处理中起着举足轻重的作用。它是将滤镜应用于图像的基石技术,可实现模糊、锐化和边缘检测等任务。

        卷积的核心是组合两个函数以产生第三个函数。在图像处理中,其中一个函数是输入图像,另一个是称为内核或过滤器的较小矩阵。内核包含定义筛选器行为的数值。该过程涉及在图像上滑动内核,将其值与图像中的相应像素值相乘,然后对结果求和。然后将此求和放置在输出图像中的特定位置。

2.1 一维卷积

        在一维卷积的上下文中,我们的输入由一维数组组成,通常称为特征向量。

        在最基本的卷积场景中,我们在此数组和数值(称为过滤器或权重)之间执行乘法,以生成称为特征图的输出数组。

        在这种情况下,我们的初始数组具有 12x1 的维度,滤波器的维度为 1x1,因此,生成的输出保持 12x1 的大小。

        此外,下面展示的是一个尺寸为2x1的过滤器。

        在这里,我们将输入的第一个元素乘以过滤器的第一个元素,将输入的第二个元素乘以过滤器的第二个元素,然后将它们相加并将结果写入输出数组的第一个元素中。

在这里,正如我们可以观察到的,我们不能进一步移动过滤器;因此,输出将更小,大小为 11x1。

2.2 填充

填充是指在图像边缘周围添加额外像素的做法。填充的目的是在使用特定内核或过滤器应用卷积操作后影响输出图像的大小。

下面,我们在输入数组的两端添加了零,因此我们最终得到了相同大小的输出。

到目前为止,我们已经将过滤器一个接一个地向右移动,但我们不一定必须继续这样做;例如,我们可以将其移动三。

2.3 一维卷积

Source

Now we have an 8-bit grayscale image with a 5x5 grid. The values range between 0 and 255.

And we have a random 3x3 kernel:

当我们将内核应用于输入时:

(-1*170)+(0*245)+(1*0)+(2*234)+(1*42)+(2*64)+(1*32)+(-2*53)+(0*128)=394

我们将中心像素替换为计算值。然后,我们逐个移动内核(从左上角到右下角)并再次进行数学运算。

我们再次对边缘像素使用填充。

三、过滤 器

        图像滤镜的多功能性通过其一系列操作实现。每个操作都有不同的目的,塑造图像的美感或促进更深入的分析。

  • 平滑过滤器
  • 锐化滤镜
  • 边缘增强滤波器

3.1 平滑过滤器

        平滑滤镜,也称为模糊滤镜,具有通过温和减少噪点、抑制不需要的细节和创造更和谐的视觉体验来提高图像质量的卓越能力。

        从本质上讲,平滑过滤器的工作原理是将图像的像素值与其相邻像素求平均值。这种平均过程对图像具有舒缓效果,使其更具凝聚力和均匀性。生成的图像保留了其主要特征,但清除了可能掩盖其本质的微小波动和不一致。

  • 高斯
  • 中位数

3.2 框模糊

        此过滤器在定义的邻域内执行像素值的简单平均值。邻域的大小称为核大小。内核大小越大,图像就越模糊。

它是一种简单高效的平滑过滤器。它通常用作图像处理算法的第一步,例如边缘检测和降噪。

import cv2
import numpy as np
import matplotlib.pyplot as plt

path = "cath.jpeg"

# read image
image = cv2.imread(path)

# box blur filter
box_blur = cv2.boxFilter(image, -1, (25, 25))

# plot
plt.figure(figsize=(10, 8))
plt.subplot(2, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(2, 2, 2)
plt.imshow(cv2.cvtColor(box_blur, cv2.COLOR_BGR2RGB))
plt.title('Box Blur')
plt.axis('off')

框模糊。图片由作者提供。

我们使用的方法得到一个简单的平均滤波器。boxFiltercv2

cv.boxFilter(src, ddepth, ksize[, dst[, anchor[, normalize[, borderType]]]]) -> dst

  • src是输入图像。
  • ddepth是输出图像的所需深度。将其设置为 -1 以使输出图像具有与输入图像相同的深度。否则,您可以使用 、、、 。cv2.CV_8Ucv2.CV_16Ucv2.CV_32Fcv2.CV_64F
  • ksize是盒子内核的大小。内核越大,平滑效果越强。
  • dst是可选的,输出图像。如果未提供,该函数将创建新的输出图像。
  • anchor是可选的,内核中的锚点。它通常设置为表示内核的中心。更改此设置可能会影响滤波输出的位置。-1, -1
  • normalize是可选的,指示内核是否应按其中的元素数进行规范化的标志。归一化有助于保持图像的亮度相对不变。
  • borderType是可选的,指示如何处理图像边框的标志。

3.3 高斯滤波器

        它采用像素值的加权平均值,权重由高斯分布确定。相邻像素的权重随着它们远离中心像素而减小。

        它是一种比盒子模糊更复杂的平滑过滤器。它更能保留图像中的边缘和细节,同时还能减少噪点。

gaussian_blur = cv2.GaussianBlur(image, (25, 25), 0)

plt.figure(figsize=(10, 8))

plt.subplot(2, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')

plt.subplot(2, 2, 2)
plt.imshow(cv2.cvtColor(gaussian_blur, cv2.COLOR_BGR2RGB))
plt.title('Gaussian Blur')
plt.axis('off')

高斯模糊。图片由作者提供。

cv.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]]) -> dst

  • sigmaX是高斯核在水平方向上的标准偏差。值越大,模糊效果越强。
  • sigmaY是可选的,高斯核在垂直方向上的标准偏差。如果未指定,则默认为与 相同的值。sigmaX

3.4 中值滤波器

中值过滤器将图像中的每个像素值替换为其相邻像素的中值。中位数是排序值列表中的中间值。这意味着中值滤波器不受异常值(如噪声尖峰)的影响。

median_filtered = cv2.medianBlur(image, 25)

plt.figure(figsize=(10, 8))

plt.subplot(2, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title( 'Original Image' )
plt.axis( 'off' )

plt.subplot(2, 2, 2)
plt.imshow(cv2.cvtColor(median_filtered, cv2.COLOR_BGR2RGB))
plt.title( 'Median Filter' )
plt.axis( 'off'  )

中值滤波器。图片由作者提供。

cv.medianBlur(src, ksize[, dst]) -> dst

四、锐化滤镜

        锐化滤镜是一类图像处理技术,用于增强图像中的边缘和精细细节。与平滑图像细节的模糊滤镜不同,锐化滤镜会突出相邻区域之间像素强度的差异,从而增强边缘并使特征更加突出。

        锐化滤镜通过增强图像的高频分量来工作。高频分量对应于像素值的快速变化,这是边缘和精细细节的特征。

        锐化滤镜可以产生视觉上吸引人的效果,但应小心使用。过度锐化会导致噪点放大和引入伪像。对已经质量良好且噪点最小的图像应用锐化滤镜通常是一种很好的做法。

  • 拉普拉斯滤波器
  • 不锐利的遮罩

4.1 拉普拉斯滤波器

拉普拉斯滤波器是一种用于图像处理的边缘检测滤波器。它是一个二阶导数滤波器,这意味着它测量图像强度的变化率。拉普拉斯滤波器通常用于锐化图像和检测边缘。

laplacian = cv2.Laplacian(image, -1, ksize=5, scale=1,delta=0,borderType=cv2.BORDER_DEFAULT)

plt.figure(figsize=(10, 8))
plt.subplot(2, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(2, 2, 2)
plt.imshow(laplacian)
plt.title('Laplacian Filter')
plt.axis('off')

拉普拉斯过滤器。图片由作者提供。

cv.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]]) -> dst

  • ksize是可选的,用于拉普拉斯操作的内核大小。它设置为奇数,例如、、等。如果未提供,则默认值为 ,它对应于 3x3 内核。1351
  • scale是可选的,是应用于计算的拉普拉斯值的比例因子。此参数有助于增强或减少拉普拉斯算子的效果。
  • delta是可选的,是添加到计算的拉普拉斯值的值。它可用于控制输出的整体亮度或对比度。

4.2 不锐利的遮罩

        它涉及创建原始图像的模糊版本(使用低通滤波器),然后从原始图像中减去此模糊版本。结果是突出显示边缘和细节的图像。术语“不锐利”是指创建一个遮罩,突出图像中不锐利的内容。

        锐化量由模糊量和模糊图像的权重控制。模糊通常是高斯模糊,但也可以使用其他类型的模糊。模糊图像的权重通常介于 0 和 1 之间。较高的重量将导致更多的锐化。

blurred = cv2.GaussianBlur(image, (25, 25), 3)
k = 3
unsharp_mask = cv2.addWeighted(image, k-1, blurred, -1.0, 0)

plt.figure(figsize=(10, 8))
plt.subplot(2, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(2, 2, 2)
plt.imshow(cv2.cvtColor(unsharp_mask, cv2.COLOR_BGR2RGB))
plt.title('Unsharp Masking')
plt.axis('off')

不锐利的遮罩。图片由作者提供。

        高升压滤波是非锐化遮罩的一种通用形式。它允许您控制应用于图像细节的增强量。它是通过添加原始图像和图像的模糊版本的加权组合来实现的,其中权重决定了增强程度。

        该函数用于组合两个具有不同权重的图像。在此上下文中,它用于执行高升压筛选操作。cv2.addWeighted

  • image:这是原始图像。
  • k - 1:这是原始图像的重量。从中减去 1 可确保原始图像的贡献根据增强因子进行缩放。值 更强调增强的细节。kk - 1
  • blurred:这是模糊的图像。
  • -0.5:这是模糊图像的权重。负值表示减去模糊图像。
  • 0:这是一个偏移值。在加权加法之后,它被添加到结果中。

五、边缘增强滤波器

        边缘增强滤镜是一种图像滤镜,用于增强图像中的边缘。边缘是图像中不同区域之间的边界,它们对于提供有关图像中对象的结构和形状的信息非常重要。

  • 索贝尔过滤器
  • 普威特过滤器
  • 高斯滤波的拉普拉斯
  • 精明边缘检测器

5.1 索贝尔过滤器

        Sobel 滤镜用于通过计算每个像素处图像强度的梯度来检测边缘。它使用两个单独的卷积核(一个用于水平方向,一个用于垂直方向)来近似梯度。

索贝尔操作员。

        Sobel 滤波器是一种流行的边缘检测滤波器,因为它实现起来相对简单,并且在检测边缘方面非常有效。但是,它也可能对噪声敏感,因此通常与其他滤镜(例如高斯模糊)结合使用,以在应用Sobel滤镜之前减少图像中的噪点。

image = cv2.imread(path, cv2.IMREAD_GRAYSCALE)

# Apply Sobel Filter
sobel_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=25)
sobel_y = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=25)
sobel_edges = np.sqrt(sobel_x**2 + sobel_y**2)

# plot
plt.figure(figsize=(12, 8))
plt.subplot(2, 3, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(2, 3, 2)
plt.imshow(sobel_edges, cmap='gray')
plt.title('Sobel Filter')
plt.axis('off')

索贝尔过滤器。图片由作者提供。

cv.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) -> dst

  • dx和:导数分别在 x 和 y 方向上的顺序。这些值确定计算梯度的方向。例如,设置和计算 x 方向的梯度。dydx=1dy=0
  • ksize(可选):用于计算的 Sobel 内核的大小。它通常设置为奇数,例如、、等。如果未提供,则默认值为 ,它对应于 3x3 内核。1353
  • scale(可选):应用于计算的 Sobel 值的比例因子。此参数有助于增强或减少 Sobel 运算符的效果。
  • delta(可选):添加到计算的 Sobel 值的值。它可用于控制输出的整体亮度或对比度。

5.2 普威特过滤器

与Sobel滤波器类似,Prewitt滤波器还计算图像强度的梯度以检测边缘。它使用的内核比 Sobel 内核更简单,但在突出显示边缘方面仍然有效。

  • 应仔细调整滤镜的强度,以避免过度锐化图像。
  • 如果可能,应将滤镜应用于图像的无噪点版本。
  • 滤镜应与其他图像处理技术(如平滑)结合使用,以提高图像的整体质量。

普威特运算符。

image = cv2.imread(path, cv2.IMREAD_GRAYSCALE)

# Prewitt Filter
kernel_x = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]])
kernel_y = np.array([[-1, -1, -1], [0, 0, 0], [1, 1, 1]])

prewitt_x = cv2.filter2D(image, cv2.CV_64F, kernel_x)
prewitt_y = cv2.filter2D(image, cv2.CV_64F, kernel_y)
prewitt_edges = np.sqrt(prewitt_x**2 + prewitt_y**2)

# plot
plt.figure(figsize=(12, 8))
plt.subplot(2, 3, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(2, 3, 2)
plt.imshow(prewitt_edges, cmap='gray')
plt.title('Prewitt Filter')
plt.axis('off')

普威特过滤器。图片由作者提供。

5.3 高斯滤波的拉普拉斯

        LoG 滤波器结合了模糊和边缘检测的效果。它首先对图像应用高斯模糊,然后计算模糊图像上的拉普拉斯算子。结果是图像的边缘得到增强,噪点被抑制。

高斯滤波器的拉普拉斯。

        LoG 滤波器是一个可分离的滤波器,这意味着它可以通过将图像与单个内核(即 3x3 矩阵)卷积来计算。内核由旨在增强图像边缘的权重组成。

  • 应仔细调整滤镜的强度,以避免过度锐化图像。
  • 如果可能,应将滤镜应用于图像的无噪点版本。
  • 滤镜应与其他图像处理技术(如平滑)结合使用,以提高图像的整体质量。
image = cv2.imread(path, cv2.IMREAD_GRAYSCALE)

# Apply Laplacian of Gaussian (LoG) Filter
log_edges = cv2.Laplacian(image, cv2.CV_64F)
log_edges = cv2.convertScaleAbs(log_edges)

# plot
plt.figure(figsize=(12, 8))
plt.subplot(2, 3, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(2, 3, 2)
plt.imshow(log_edges, cmap='gray')
plt.title('LoG Filter')
plt.axis('off')

LoG 滤波器。图片由作者提供。

拉普拉斯运算可以生成正值和负值,这可能不适合可视化。 函数用于将拉普拉斯运算的输出转换为绝对值,然后转换为更适合图像显示的数据类型 ()。cv2.convertScaleAbs(log_edges)uint8

5.4 精明边缘检测器

        Canny边缘检测器是一种流行的图像处理技术,用于检测图像中的边缘。

精明的边缘检测器。

Canny边缘检测器的工作原理是识别图像中强度快速变化的区域,这些区域通常对应于物体边界或重要特征。

Canny边缘检测器的输出是一个二进制图像,其中边缘像素用白色标记,非边缘像素用黑色标记。该技术用途广泛,可以通过调整参数进行微调,例如高斯模糊的标准偏差和边缘检测阈值。

canny_edges = cv2.Canny(image, 30, 60)

# plot
plt.figure(figsize=(12, 8))
plt.subplot(2, 3, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(2, 3, 2)
plt.imshow(canny_edges, cmap='gray')
plt.title('Canny Edge Filter')
plt.axis('off')

精明的边缘过滤器。图片由作者提供。

cv.Canny(图像, 阈值 1, 阈值 2[, 边缘[, 光圈大小[, L2梯度]]]) -> 边缘

cv.Canny(dx, dy, threshold1, threshold2[, edges[, L2gradient]]) -> edge

  • image:将应用Canny边缘检测的输入图像。它通常是灰度图像。
  • threshold1和:这些是双阈值步骤中使用的下限和上限阈值。Canny 算法将梯度幅度高于的像素标记为强边,将边缘之间的像素标记为弱边。下面的像素被视为非边缘,将被丢弃。threshold2threshold2threshold1threshold2threshold1
  • apertureSize(可选):用于梯度计算的 Sobel 核的大小。它通常设置为 、 或 。如果未提供,则缺省值为 。3573
  • L2gradient(可选):指示是否应使用 L2 范数计算梯度大小的标志。如果 ,则使用欧几里得距离。如果 ,则使用 L1 范数。默认值为 。TrueFalseFalse

        图像过滤的核心是从像素数据中提取隐藏的见解。通过卷积的数学能力,它可以增强边缘,减少噪音,并将原始图像转换为引人入胜的故事。这个过程将目的与技术相结合,巩固了图像过滤揭示看不见和提升视觉感知的强大能力。奥坎·耶尼根

·

猜你喜欢

转载自blog.csdn.net/gongdiwudu/article/details/132790142
今日推荐