AI 视觉连载5:传统 CV 之均值滤波

在前 5 节,从最基础的像素开始了介绍,并且着重介绍了 RGB 图片和 YUV 图片以及通道的概念。

其实这几节的内容,很多细节和知识了解即可。

你只需要知道计算机在处理图片时,计算机看到的都是一堆像素,而这一堆像素,都是以数值的形式存放在计算机中的。

为了更好的展示彩色图像,并且处理图像数据,人们为图像设置了几个通道,比如 RGB 通道。

了解这些基本概念和背景就可以了,从本节开始我会介绍一些传统计算机视觉的知识,方便为后面学习基于深度学习的计算机视觉提供知识积累。

在传统计算机视觉中,有一类非常基础的算法,就是对图像进行滤波操作。

什么是滤波?

估计在很多场合你都听说过滤波的概念。

图像滤波是图像处理中最常见的一种操作,它的主要目的是改变图像中的某些特征,比如去除图像中的噪声。

滤波操作的是通过一定的数学算法来完成的,最常见的滤波方式包括均值滤波、中值滤波和高斯滤波。

从名字就可以看出,均值滤波是取一些像素值的平均值作为滤波的输出,中值滤波便是取一些像素的中值作为滤波后的输出。

高斯滤波就稍微复杂一些,人们特意设计了一个符合高斯分布的滤波器,完成对图像像素的高斯滤波运算。

以均值滤波为例,它是取图像中的哪些像素值来计算平均值呢?

为了清楚的表示取哪些像素值,人们设计了一个窗口,称为滤波器的窗口,在AI算法的卷积算法中,这个窗口也可以看做是卷积的卷积核。

(均值滤波示意图,灰色阴影即为窗口)

如上图,均值滤波的运算过程,是每次取灰色阴影中像素的平均值作为输出,然后将窗口往右滑动继续计算下一个窗口,直至全部计算完成。

均值滤波的作用

均值滤波既然是取了窗口内的均值,显而易见它的作用主要有:平滑图像和去除噪点(这是因为一般噪点的像素值和正常像素比会发生突变,要么突然变得很大,要么突然变得很小)。

一取均值的话,噪声点突变的像素值就被平均了,输出就会显得没那么明显了,图片的平滑效果就会好很多。

因此,对于图像中存在畸变噪点的图像,采用均值滤波会有一定的效果。

上图左侧是原图,中间是增加了一些黑色的噪声点,最右侧是对中间含有噪声点的图像做了一次均值滤波。

可以看到,均值滤波之后,噪声点没有那么明显了。

你可以通过调整均值滤波的窗口大小,来获取更好的滤波效果。一般而言,窗口设置的越大,输出图像平滑的越厉害,可能也越模糊,所以需要根据实际需要选择合适的窗口大小。

实现上述滤波的源代码在下方,你可以在这个目录下获取源代码和原始图像来体验滤波的过程。

bash 复制代码
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图像
image = cv2.imread('panda.png')

# 添加椒盐噪声
def add_salt_and_pepper_noise(image, salt_prob, pepper_prob):
    noisy_image = image.copy()
    total_pixels = image.size

    # 添加椒盐噪声
    num_salt = np.ceil(salt_prob * total_pixels)
    salt_coords = [np.random.randint(0, i-1, int(num_salt)) for i in image.shape]
    noisy_image[salt_coords[0], salt_coords[1], :] = 255

    num_pepper = np.ceil(pepper_prob * total_pixels)
    pepper_coords = [np.random.randint(0, i-1, int(num_pepper)) for i in image.shape]
    noisy_image[pepper_coords[0], pepper_coords[1], :] = 0

    return noisy_image

# 生成椒盐噪声
salt_and_pepper_image = add_salt_and_pepper_noise(image, salt_prob=0.02, pepper_prob=0.02)

# 定义均值滤波器的大小
kernel_size = (8, 8)

# 应用均值滤波
filtered_image = cv2.blur(salt_and_pepper_image, kernel_size)

# 使用Matplotlib显示原始图像、椒盐噪声图像和滤波后的图像
fig, axes = plt.subplots(1, 3, figsize=(15, 5))

axes[0].imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
axes[0].set_title('Original Image')
axes[0].axis('off')

axes[1].imshow(cv2.cvtColor(salt_and_pepper_image, cv2.COLOR_BGR2RGB))
axes[1].set_title('Image with Salt and Pepper Noise')
axes[1].axis('off')

axes[2].imshow(cv2.cvtColor(filtered_image, cv2.COLOR_BGR2RGB))
axes[2].set_title('Filtered Image')
axes[2].axis('off')

plt.show()
相关推荐
多恩Stone1 小时前
【3D-AICG 系列-11】Trellis 2 的 Shape VAE 训练流程梳理
人工智能·pytorch·算法·3d·aigc
lintax2 小时前
计算pi值-积分法
python·算法·计算π·积分法
你的冰西瓜3 小时前
C++ STL算法——排序和相关操作
开发语言·c++·算法·stl
今儿敲了吗3 小时前
29| 高考志愿
c++·笔记·学习·算法
识君啊4 小时前
Java 二叉树从入门到精通-遍历与递归详解
java·算法·leetcode·二叉树·深度优先·广度优先
紫陌涵光4 小时前
77. 组合
c++·算法·leetcode·深度优先
小汉堡编程4 小时前
LeekCode第3767题选择K个任务的最大总分:详细思考过程幽默解析 专门为小白准备
算法·leetcode·贪心算法·编程·小白专用教程
小白菜又菜4 小时前
Leetcode 235. Lowest Common Ancestor of a Binary Search Tree
python·算法·leetcode
We་ct5 小时前
LeetCode 222. 完全二叉树的节点个数:两种解法详解(BFS + 二分查找优化)
数据结构·算法·leetcode·typescript