数字图像处理:空间域滤波

news2024/11/18 7:32:30

1.数字图像处理:空间域滤波

1.1 滤波器核(相关核)与卷积

图像上的邻域计算

线性空间滤波的原理

滤波器核(相关核)是如何得到的?


空间域的卷积




卷积:滤波器核与window中的对应值相乘后所有值相加得到一个像素值,滑动窗口遍历整个图像




滤波器核(相关核)与卷积的区别



截图来源:【小动画】彻底理解卷积【超形象】卷的由来,小元老师



滤波器核对称时,翻转与不翻转没有影响,所以卷积等于相关性


卷积的物理实质可以通过以下几个方面进行理解,这些方面涉及到信号处理、系统响应和图像处理等领域

1.2 图像加噪

噪声点的判定标准

由灰度直方图得到概率密度函数的方法





从含噪图像中确定具体噪声模型的系统化方法?

选取实验用的实验图像,完成图像读取和显示,给图像加上高斯噪声

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

# 打开图片并转换为灰度图像
img_dir = r'D:\Document\Experiment\data\image1.jpg'
# 读取图像并转换为灰度
gray = cv.imread(img_dir, 0)
image_array = np.array(gray)

# 定义高斯噪声的参数
mean = 0  # 均值
sigma = 80  # 标准差(调整噪声强度)

# 生成高斯噪声
gaussian_noise = np.random.normal(mean, sigma, image_array.shape)

# 将噪声加入图像
noisy_image = image_array + gaussian_noise

# 将噪声后的图像剪裁到0-255范围内,并转换为uint8
noisy_image_clipped = np.clip(noisy_image, 0, 255).astype(np.uint8)

# 显示原图和加入噪声后的图像
plt.figure(figsize=(10,5))
plt.subplot(1,2,1)
plt.title('Original Image')
plt.imshow(image_array, cmap='gray')

plt.subplot(1,2,2)
plt.title('Noisy Image')
plt.imshow(noisy_image_clipped, cmap='gray')
plt.show()

1.3 均值滤波、高斯滤波、中值滤波

均值滤波

高斯滤波



中值滤波


为了使得卷积能够正常进行,对原图像外围进行填充(padding)

用自己编写的滤波函数分别对实验图像进行滤波;

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

# 读取图像并转换为灰度
img_dir = r'D:\Document\Experiment\data\image1.jpg'  # 图像路径
gray = cv.imread(img_dir, 0)  # 读取图像,并将其转换为灰度图像

# 定义高斯噪声的参数
mean = 0  # 高斯噪声的均值
sigma = 80  # 高斯噪声的标准差,用于控制噪声强度

# 生成高斯噪声并添加到图像
gaussian_noise = np.random.normal(mean, sigma, gray.shape)  # 生成与图像相同大小的高斯噪声
noisy_image = gray + gaussian_noise  # 将生成的噪声添加到图像
noisy_image_clipped = np.clip(noisy_image, 0, 255).astype(np.uint8)  # 将噪声叠加后的图像值限制在0到255,并转换为uint8类型

# 均值滤波实现
# 其中,均值滤波一般的具体实现步骤是:
# .选择一个(2n+l) x (2n+l)的窗口(通常为3 x 3或5 x 5),并用该窗口沿图像数据进行行或列的滑动;
# .读取窗口下各对应像素的灰度值;
# .求取这些像素的灰度平均值替代窗口中心位置的原始像素灰度值。
def mean_filter(image, kernel_size=3):
    # 填充大小
    # 根据传入的窗口大小 kernel_size 计算需要的填充尺寸
    # 因为均值滤波会涉及到窗口的滑动,所以为了保持输出图像的尺寸与输入图像相同,需要在图像的边缘进行填充。对于 3x3 的窗口,pad_size 为 1;对于 5x5 的窗口,pad_size 为 2
    pad_size = kernel_size // 2  # 根据核大小计算需要的填充尺寸
    # 使用 np.pad 函数将原始图像进行填充,pad_size 为填充的边界大小,mode='constant' 指定使用常数值填充,constant_values=0 表示用 0 填充。这使得在处理图像边缘时能够避免索引超出边界的错误。
    padded_image = np.pad(image, pad_size, mode='constant', constant_values=0)  # 用常数0填充图像边缘
    # 创建一个与输入图像 image 形状相同的全零数组 output_image,用于存储均值滤波后的结果。
    output_image = np.zeros_like(image)  # 初始化输出图像,大小与原图一致
    
    # 滑动窗口进行均值滤波
    # 外层循环:通过 for 循环遍历填充后的图像的行,从 pad_size 开始到 padded_image.shape[0] - pad_size 结束。这样做是为了避免在处理图像边缘时出现越界
    for i in range(pad_size, padded_image.shape[0] - pad_size):
        # 内层循环:同样通过 for 循环遍历填充后的图像的列,范围与行的处理相同。这两个嵌套循环用于对图像的每一个像素进行处理
        for j in range(pad_size, padded_image.shape[1] - pad_size):
        	# 获取窗口内的像素:通过切片操作从填充后的图像中获取当前窗口的像素值。窗口的大小为 (kernel_size, kernel_size),即从 (i-pad_size, j-pad_size) 到 (i+pad_size, j+pad_size) 的区域
            window = padded_image[i-pad_size:i+pad_size+1, j-pad_size:j+pad_size+1]  # 获取窗口内的像素
            # 使用 np.mean(window) 计算窗口中像素值的平均值,并将结果赋值给输出图像 output_image 的对应位置。为了保持位置一致性,索引使用 i-pad_size 和 j-pad_size
            output_image[i-pad_size, j-pad_size] = np.mean(window)  # 计算窗口像素的平均值,并赋给输出图像的对应位置
    
    return output_image  # 返回滤波后的图像

# 高斯滤波实现
# 高斯滤波一般的具体实现步骤是:
# .选择一个(2n+l) x (2n+l)的窗口(通常为3 x 3或5 x 5),生成二维高斯模板,并用该窗口沿图像数据进行行或列的滑动;
# .读取窗口下各对应像素的灰度值;
# .求取这些像素与二维高斯模板对应位置元素的乘积再求和,用该值替代窗口中心位置的原始像素灰度值。
def gaussian_kernel(kernel_size=3, sigma=1.0):
    k = kernel_size // 2  # 计算高斯核中心的偏移
    gaussian_kernel = np.zeros((kernel_size, kernel_size), dtype=np.float32)  # 初始化高斯核
    for x in range(-k, k + 1):  # 遍历核的行坐标
        for y in range(-k, k + 1):  # 遍历核的列坐标
            gaussian_kernel[x + k, y + k] = np.exp(-(x**2 + y**2) / (2 * sigma**2))  # 根据高斯公式计算权重
    gaussian_kernel /= (2 * np.pi * sigma**2)  # 归一化常数
    gaussian_kernel /= gaussian_kernel.sum()  # 对高斯核进行归一化,使其所有元素的和为1
    return gaussian_kernel  # 返回生成的高斯核

def gaussian_filter(image, kernel_size=3, sigma=1.0):
    pad_size = kernel_size // 2  # 计算填充大小
    padded_image = np.pad(image, pad_size, mode='constant', constant_values=0)  # 用常数0填充图像边缘
    output_image = np.zeros_like(image)  # 初始化输出图像
    
    kernel = gaussian_kernel(kernel_size, sigma)  # 生成高斯核
    
    # 滑动窗口进行高斯滤波
    for i in range(pad_size, padded_image.shape[0] - pad_size):
        for j in range(pad_size, padded_image.shape[1] - pad_size):
            window = padded_image[i-pad_size:i+pad_size+1, j-pad_size:j+pad_size+1]  # 获取窗口内的像素
            output_image[i-pad_size, j-pad_size] = np.sum(window * kernel)  # 计算窗口像素与高斯核的加权和
    
    return output_image  # 返回滤波后的图像

# 中值滤波实现
# 中值滤波一般的具体实现步骤是:
# .选择一个(2n+l)x(2n+l)的窗口(通常为3x3或5x5),并用该窗口沿图像数据进行行或列的滑动;
# .读取窗口下各对应像素的灰度值;
# .将这些灰度值从小到大排成一列,用排序所得的中值替代窗口中心位置的原始像素灰度值;
def median_filter(image, kernel_size=3):
    pad_size = kernel_size // 2  # 计算填充大小
    padded_image = np.pad(image, pad_size, mode='constant', constant_values=0)  # 用常数0填充图像边缘
    output_image = np.zeros_like(image)  # 初始化输出图像
    
    # 滑动窗口进行中值滤波
    for i in range(pad_size, padded_image.shape[0] - pad_size):
        for j in range(pad_size, padded_image.shape[1] - pad_size):
            # 获取窗口内的像素
            window = padded_image[i-pad_size:i+pad_size+1, j-pad_size:j+pad_size+1]  
            output_image[i-pad_size, j-pad_size] = np.median(window)  # 计算窗口像素的中值,并赋给输出图像的对应位置
    
    return output_image  # 返回滤波后的图像

# 进行均值滤波、高斯滤波、中值滤波
mean_filtered_img = mean_filter(noisy_image_clipped, kernel_size=3)  # 应用均值滤波,使用3x3窗口
gaussian_filtered_img = gaussian_filter(noisy_image_clipped, kernel_size=3, sigma=1.0)  # 应用高斯滤波,使用3x3窗口,sigma为1.0
median_filtered_img = median_filter(noisy_image_clipped, kernel_size=3)  # 应用中值滤波,使用3x3窗口

# 定义运算及其标题
operations = [
    ("Original", gray),  # 原始图像
    ("Noised", noisy_image_clipped),  # 添加噪声后的图像
    ("Mean Filter", mean_filtered_img),  # 均值滤波后的图像
    ("Gaussian Filter", gaussian_filtered_img),  # 高斯滤波后的图像
    ("Median Filter", median_filtered_img)  # 中值滤波后的图像
]

# 绘图
plt.figure(figsize=(15, 7))  # 设置绘图窗口大小
for i, (title, result) in enumerate(operations, 1):  # 遍历运算结果
    plt.subplot(2, 3, i)  # 创建子图,2行3列
    plt.title(title)  # 设置子图标题
    plt.imshow(result, cmap='gray')  # 显示图像,使用灰度颜色映射
    plt.axis('off')  # 关闭坐标轴显示

plt.tight_layout()  # 自动调整子图布局,使之不重叠
plt.show()  # 显示图像


用OpenCV自带的滤波函数对实验图像分别进行滤波;

# (4)用OpenCV自带的滤波函数对实验图像分别进行滤波;
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt

# 读取图像并转换为灰度
img_dir = r'D:\Document\Experiment\data\image1.jpg'
gray = cv.imread(img_dir, 0)

# 灰度加噪(添加高斯噪声)
mean = 0  # 均值
sigma = 80  # 标准差(调整噪声强度)
gaussian_noise = np.random.normal(mean, sigma, gray.shape)  # 生成高斯噪声
noisy_image = gray + gaussian_noise  # 将噪声加入图像
noisy_image_clipped = np.clip(noisy_image, 0, 255).astype(np.uint8)  # 剪裁到0-255范围并转换为uint8

# 均值滤波实现
def mean_filter(image, kernel_size=5):
    # 使用cv2的blur函数进行均值滤波
    return cv.blur(image, (kernel_size, kernel_size))

# 高斯滤波实现
def gaussian_filter(image, kernel_size=5, sigma=1.0):
    # 使用cv2的GaussianBlur函数进行高斯滤波
    return cv.GaussianBlur(image, (kernel_size, kernel_size), sigma)

# 中值滤波实现
def median_filter(image, kernel_size=5):
    # 使用cv2的medianBlur函数进行中值滤波
    return cv.medianBlur(image, kernel_size)

# 进行均值滤波、高斯滤波、中值滤波
mean_filtered_img = mean_filter(noisy_image_clipped)
gaussian_filtered_img = gaussian_filter(noisy_image_clipped)
median_filtered_img = median_filter(noisy_image_clipped)

# 定义运算及其标题
operations = [
    ("Original", gray),
    ("Noised", noisy_image_clipped),
    ("Mean Filter", mean_filtered_img),
    ("Gaussian Filter", gaussian_filtered_img),
    ("Median Filter", median_filtered_img)
]

# 绘图
plt.figure(figsize=(15, 7))
for i, (title, result) in enumerate(operations, 1):
    plt.subplot(2, 3, i)
    plt.title(title)
    plt.imshow(result, cmap='gray')
    plt.axis('off')  # 关闭坐标轴显示

plt.tight_layout()
plt.show()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2179001.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

touch命令:创建文件,更新时间戳

一、命令简介 ​touch​ 命令在 Linux 和其他类 Unix 系统中用于创建空白文件或者更新已存在文件的时间戳。如果指定的文件不存在,touch​ 命令会创建一个空白文件;如果文件已经存在,touch​ 命令会更新文件的访问时间和修改时间&#xff0c…

誉天Linux云计算课程学什么?为什么保障就业?

一个IT工程师相当于干了哪些职业? 其中置顶回答生动而形象地描绘道: 一个IT工程师宛如一个超级多面手,相当于——加班狂程序员测试工程师实施工程师网络工程师电工装卸工搬运工超人。 此中酸甜苦辣咸,相信很多小伙伴们都深有体会。除了典…

用开源软件制作出精美的短视频#视频编辑

从前,有一个叫做创意森林的地方,住着各种各样的编辑精灵。一天,视频编辑精灵们发现了一本神秘的论文,里面写满了如何利用前沿的AI技术来提升他们的工作效率。于是,精灵们开始学习使用LLM和LLaVA,像魔法一样…

《企业实战分享 · 开发技术栈选型》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…

02Cesium中常用的鼠标事件

文章目录 02Cesium中常用的鼠标事件1、左键单击事件2、左键双击事件3、左键按下事件4、左键弹起事件5、中键按下事件6、中键弹起事件7、鼠标移动事件8、右键单击事件9、右键按下事件10、右键弹起事件11、鼠标滚轮事件具体在代码中的应用如下所示 02Cesium中常用的鼠标事件 Ces…

windows下安装rabbitMQ并开通管理界面和允许远程访问

如题,在windows下安装一个rabbitMQ server;然后用浏览器访问其管理界面;由于rabbitMQ的默认账号guest默认只能本机访问,因此需要设置允许其他机器远程访问。这跟mysql的思路很像,默认只能本地访问,要远程访…

《深度学习》OpenCV 图像拼接 拼接原理、参数解析、案例实现

目录 一、图像拼接 1、直接看案例 图1与图2展示: 合并完结果: 2、什么是图像拼接 3、图像拼接步骤 1)加载图像 2)特征点检测与描述 3)特征点匹配 4)图像配准 5)图像变换和拼接 6&am…

鸿蒙harmonyos next flutter通信之BasicMessageChannel获取app版本号

本文将通过BasicMessageChannel获取app版本号,以此来演练BasicMessageChannel用法。 建立channel flutter代码: //建立通道 BasicMessageChannel basicMessageChannel BasicMessageChannel("com.xmg.basicMessageChannel",StringCodec());…

系统工程 > 霍尔三维结构

简介 霍尔三维结构模型是由美国系统工程专家霍尔(A.D.Hall)在1969年提出的一种系统工程方法论,它集中体现了系统工程方法的系统化、综合化、最优化、程序化和标准化等特点 。该模型将系统工程整个活动过程分为前后紧密衔接的七个阶段和七个步…

MySQL的驱动安装

1、下载并安装MySQL 下载地址: 建议在下列框中选择LTS长期支持版本,下载对应的MSI安装文件。 安装完成后,将MySQL的环境bin路径添加到环境变量中。 可以运行MySQL Configurator进行配置,主要设置密码,并初始化。其余…

机器学习课程学习周报十四

机器学习课程学习周报十四 文章目录 机器学习课程学习周报十四摘要Abstract一、机器学习部分1. EM算法与高斯混合模型2. 概率论复习(三) 总结 摘要 本周的学习重点是EM算法与高斯混合模型的应用。单高斯模型无法有效拟合多峰数据分布,因此引…

论文精读:拓扑超导体PdBi2Te4和PdBi2Te5计算

npj Computational Materials (2023) 9:188 ; https://doi.org/10.1038/s41524-023-01144-y 摘要节选 超导拓扑金属(SCTMs)近年来成为一种很有前途的量子计算拓扑超导(TSC)和马约拉纳零模式平台。 本文提出了一种通过将超导单元嵌入到拓扑绝缘体中来设计sctm的策略。还编制了…

二叉树的中序遍历(java)

概述 关于二叉树,我们都不陌生,许多基于递归的问题发起点都是一个二叉树的root节点。对于各种二叉树的问题,我们也是通过dfs进行求解。例如求二叉树的深度、最近公共祖先等 算法分析 关于二叉树的中序遍历,我们都知道应该先访…

无人机之集群路径规划篇

无人机的集群路径规划是一个复杂而重要的任务,它要求为一群无人机设计出既安全又高效的飞行路径,同时考虑到多种约束条件和目标。 一、路径规划的重要性 无人机集群路径规划对于确保无人机能够安全、高效地完成任务至关重要。通过合理的路径规划&#x…

Word办公自动化的一些方法

1.Word部分内容介绍 word本身是带有格式的一种文档,有人说它本质是XML,所以一定要充分利用标记了【样式】的特性来迅速调整【格式】,从而专心编辑文档内容本身。 样式(集) 编号(多级关联样式编号&#xff…

企业如何提升知识产权管理效率?

随着企业规模的扩大和创新活动的增加,知识产权管理日益复杂。有效的知识产权管理不仅能够保护企业的创新成果,还能为企业带来巨大的商业价值。然而,许多企业在知识产权管理方面面临着效率低下的问题,管理效率的提升成为企业亟需解…

XSS | 存储型 XSS 攻击

关注这个漏洞的其他相关笔记:XSS 漏洞 - 学习手册-CSDN博客 0x01:存储型 XSS —— 理论篇 存储型 XSS 又称持久型 XSS,攻击脚本将被永久的存放在目标服务器的数据库或文件中,具有很高的隐蔽性。 常见的攻击方式: 这种…

升级 Windows 后如何恢复丢失的文件

升级到 Windows 11 后可以恢复丢失的文件!阅读帖子直到最后,了解如何做到这一点。 为了获得安全更新并使用最新的操作系统,人们会升级到最新版本的 Windows。然而,在这样做的过程中,许多人丢失了他们的重要文件&#…

Dynamics 365 dependency EntityType

导解决方案时经常会碰到组件依赖导致导入报错,而错误提示中组件只有type, 比如下图中的type 20和60, 初看之下并不知道是什么意思,从parentDisplayName能看出来,这个parent是个实体,但实体中的什么呢,目测是看不出来的…

8621 二分查找

**思路:** 1. 读取输入的元素个数 n。 2. 读取有序数组 ST。 3. 读取要查找的关键字 key。 4. 使用折半查找法(即二分查找)在数组 ST 中查找 key 的位置。 5. 如果找到 key,输出其位置;如果未找到,输出 &qu…