Python图像处理【12】基于小波变换执行图像去噪

news2024/9/27 5:41:34

基于小波变换执行图像去噪

    • 0. 前言
    • 1. 小波变换基础
    • 2. 小波变换去噪原理
    • 3. 使用 pywt 执行小波变换图像去噪
    • 4. 使用 scikit-image 执行小波变换图像去噪
      • 4.1 循环旋转技术
      • 4.2 改进图像去噪质量
    • 小结
    • 系列链接

0. 前言

小波 (wavelets) 变换是表示和分析多分辨率图像的通用方法,该方法在图像处理的许多不同领域中都有应用,例如图像压缩、去噪等。在本节中,我们将学习如何使用 pywtscikit-image 实现的小波变换执行图像去噪。

1. 小波变换基础

我们首先介绍小波变换的基础知识。以下代码使用离散小波变换 (Discrete Wavelet Transformation, DWT) 转换输入灰度图像(具有不同级别),并提取近似图像和水平/垂直/对角线细节。
我们使用原始图像经过高通滤波生成三幅图像,每个图像都描述了原始图像中亮度(细节)的局部变化。然后,将其执行低通滤波和缩放,从而产生近似图像;该图像经过高通滤波生产三个较小尺寸的细节图新,并使用低通滤波生成最终近似图像:

import numpy as np
import pywt
from pywt._doc_utils import wavedec2_keys, draw_2d_wp_basis
from skimage.filters import threshold_otsu
from skimage import img_as_float
import matplotlib.pylab as plt

x = pywt.data.ascent().astype(np.float32)
shape = x.shape

plt.rcParams.update({'font.size': 8})

max_lev = 3       # how many levels of decomposition to draw
label_levels = 3  # how many levels to explicitly label on the plots

fig, axes = plt.subplots(4, 2, figsize=[15, 35])
plt.subplots_adjust(0, 0, 1, 0.95, 0.05, 0.05)
for level in range(0, max_lev + 1):
    if level == 0:
        # show the original image before decomposition
        axes[0, 0].set_axis_off()
        axes[0, 1].imshow(x, cmap=plt.cm.gray)
        axes[0, 1].set_title('Image')
        axes[0, 1].set_axis_off()
        continue

    # plot subband boundaries of a standard DWT basis
    draw_2d_wp_basis(shape, wavedec2_keys(level), ax=axes[level, 0],
                     label_levels=label_levels)
    axes[level, 0].set_title('{} level\ndecomposition'.format(level))

    # compute the 2D DWT
    c = pywt.wavedec2(x, 'db2', mode='periodization', level=level)
    # normalize each coefficient array independently for better visibility
    c[0] /= np.abs(c[0]).max()
    for detail_level in range(level):
        c[detail_level + 1] = [d/np.abs(d).max() > threshold_otsu(d/np.abs(d).max()) for d in c[detail_level + 1]]
    # show the normalized coefficients
    arr, slices = pywt.coeffs_to_array(c)
    axes[level, 1].imshow(arr, cmap=plt.cm.gray)
    axes[level, 1].set_title('Coefficients\n({} level)'.format(level))
    axes[level, 1].set_axis_off()

plt.tight_layout()
plt.show()

小波变换基础

2. 小波变换去噪原理

小波变换通常用于图像去噪,基于小波变换的图像去噪步骤如下:

  • 选择一个小波类型(例如,双正交小波或 N 级分解小波),利用小波对图像执行离散小波变换
  • 在图像分解后,确定每个级别的阈值 (Birgé-Massart 策略是选择阈值的常见方法),使用此过程,可以为 N 个级别设置单独的阈值
  • 最后一步是使用逆离散小波变换从修改后的级别重建图像

需要注意的是,选择使用不同小波、级别和阈值策略可能会导致不同类型的滤波。

3. 使用 pywt 执行小波变换图像去噪

在本节中,我们将在输入 RGB 图像中添加高斯噪声,并使用小波的软阈值消除噪声。

(1) 首先,导入所需库,读取输入 RGB 图像,并用 σ = 0.25 σ=0.25 σ=0.25 添加高斯噪声,得到带有噪声的图像:

import numpy as np
import pywt
from skimage import img_as_float
import matplotlib.pylab as plt
from skimage.io import imread

image = img_as_float(imread('3.png'))
noise_sigma = 0.25 #16.0
image += np.random.normal(0, noise_sigma, size=image.shape)

(2) 我们可以使用 pywt 中的函数 Wavelet() 应用多级 2D DWT,该函数会应用小波变换并且级别 level=7

wavelet = pywt.Wavelet('haar')
levels  = int(np.floor(np.log2(image.shape[0])))
print(levels)
wavelet_coeffs = pywt.wavedec2(image, wavelet, level=levels)
# 7

(3) 定义函数 denoise() 执行图像去噪操作,该函数接受给定类型的小波对象和(估计的)噪声标准差作为参数。然后,函数计算出不同级别的 DWT 系数,并使用估计的噪声应用软阈值来计算新的系数;最后,使用新系数重建图像,并得到的返回图像:

def denoise(image, wavelet, noise_sigma):
    levels = int(np.floor(np.log2(image.shape[0])))
    wc = pywt.wavedec2(image, wavelet, level=levels)
    arr, coeff_slices = pywt.coeffs_to_array(wc)
    arr = pywt.threshold(arr, noise_sigma, mode='soft')
    nwc = pywt.array_to_coeffs(arr, coeff_slices, output_format='wavedec2')
    return pywt.waverec2(nwc, wavelet)

(4) 使用不同类型的离散小波,并将它们应用于带有噪声的图像,并使用 denoise() 函数从有噪输入 RGB 图像的每个颜色通道中去除噪声:

print(pywt.wavelist(kind='discrete'))
wlts = ['bior1.5', 'coif5', 'db6', 'dmey', 'haar', 'rbio2.8', 'sym15'] # pywt.wavelist(kind='discrete')
Denoised={}
for wlt in wlts:
    out = image.copy()
    for i in range(3):
        out[...,i] = denoise(image[...,i], wavelet=wlt, noise_sigma=3/2*noise_sigma)
    Denoised[wlt] = np.clip(out, 0, 1)
print(len(Denoised))

(5) 最后,绘制用不同小波类型去噪的所有输出图像,并使用 PSNR 比较图像质量:

plt.figure(figsize=(15,8))
plt.subplots_adjust(0,0,1,0.9,0.05,0.07)
plt.subplot(241), plt.imshow(np.clip(image,0,1)), plt.axis('off'), plt.title('original image', size=8)
i = 2
for wlt in Denoised:
    plt.subplot(2,4,i), plt.imshow(Denoised[wlt]), plt.axis('off'), plt.title(wlt, size=8)
    i += 1
plt.suptitle('Image Denoising with Wavelets', size=12)
plt.show()

图像去噪

4. 使用 scikit-image 执行小波变换图像去噪

4.1 循环旋转技术

离散的小波变换不具备平移不变性,为了实现平移不变性可以使用非抽样小波变换 (undecimated wavelet transform,也称平稳小波,stationary wavelet),但需要增加冗余的成本,即比输入图像像素更多的小波系数。为了使用离散小波变换实现图像去噪并近似平移不变性,我们也可以使用另一种称为循环旋转 (cycle-spinning) 的技术,这需要对多个空间移位结果求取均值:

  • 将信号(循环)移动量 n
  • 应用去噪
  • 应用反向平移

4.2 改进图像去噪质量

在本节中,我们将看到,对于 2D 图像去噪,循环旋转技术可以令图像质量得到大幅提高,通过对每个轴上仅 n=0n=1 的偏移求取均值,就可以获取大部分图像增益:

(1) 首先,导入所有必需的 Python 模块和函数:

from skimage.restoration import (denoise_wavelet, estimate_sigma)
from skimage import data, img_as_float
from skimage.util import random_noise
from skimage.metrics import peak_signal_noise_ratio
import numpy as np
from skimage import img_as_float
import matplotlib.pylab as plt
from skimage.io import imread

(2) 读取输入图像,并在图像中添加随机噪声:

original = img_as_float(imread('3.png'))[...,:3]
sigma = 0.12
noisy = random_noise(original, var=sigma**2)

(3) 估计跨颜色通道的平均噪声标准差:

sigma_est = estimate_sigma(noisy, multichannel=True, average_sigmas=True)
print(f"Estimated Gaussian noise standard deviation = {sigma_est}")
# Estimated Gaussian noise standard deviation = 0.10885399509583953

如以上代码执行结果所示,由于对值进行了裁剪,得到的平均噪声标准差估计值比指定的 sigma 小一点。

(4) 使用 skimage.restoration 模块的 denoise_wavelet() 函数在图像上执行小波去噪。分别使用两种不同的阈值方法,即 BayesshrinkVisuShrink

im_bayes = denoise_wavelet(noisy, multichannel=True, convert2ycbcr=True,
                           method='BayesShrink', mode='soft',
                           rescale_sigma=True)
im_visushrink = denoise_wavelet(noisy, multichannel=True, convert2ycbcr=True,
                                method='VisuShrink', mode='soft',
                                sigma=sigma_est, rescale_sigma=True)

Visushrink 旨在消除具有高概率的噪声,但这会导致图像在视觉上过于光滑。使用不同阈值重复以上过程,观察得到的不同结果:

im_visushrink2 = denoise_wavelet(noisy, multichannel=True, convert2ycbcr=True,
                                 method='VisuShrink', mode='soft',
                                 sigma=sigma_est/2, rescale_sigma=True)
im_visushrink4 = denoise_wavelet(noisy, multichannel=True, convert2ycbcr=True,
                                 method='VisuShrink', mode='soft',
                                 sigma=sigma_est/4, rescale_sigma=True)

(5) 计算 PSNR 作为图像质量的指标:

psnr_noisy = peak_signal_noise_ratio(original, noisy)
psnr_bayes = peak_signal_noise_ratio(original, im_bayes)
psnr_visushrink = peak_signal_noise_ratio(original, im_visushrink)
psnr_visushrink2 = peak_signal_noise_ratio(original, im_visushrink2)
psnr_visushrink4 = peak_signal_noise_ratio(original, im_visushrink4)

(6) 绘制输入图像、输出图像以及相应的PSNR值:

plt.figure(figsize=(20,20))
plt.subplots_adjust(0,0,1,1,0.05,0.05)
plt.subplot(231), plt.imshow(original), plt.axis('off'), plt.title('Original', size=10)
plt.subplot(232), plt.imshow(noisy), plt.axis('off'), plt.title('Noisy\nPSNR={:0.4g}'.format(psnr_noisy), size=10)
plt.subplot(233), plt.imshow(im_bayes/im_bayes.max()), plt.axis('off'), plt.title('Wavelet denoising\n(BayesShrink)\nPSNR={:0.4f}'.format(psnr_bayes), size=10)
plt.subplot(234), plt.imshow(im_visushrink/im_visushrink.max()), plt.axis('off')
plt.title('Wavelet denoising\n' + r'(VisuShrink, $\sigma=\sigma_{est}$)' + '\nPSNR={:0.4g}'.format(psnr_visushrink), size=10)
plt.subplot(235), plt.imshow(im_visushrink2/im_visushrink2.max()), plt.axis('off')
plt.title('Wavelet denoising\n' + r'(VisuShrink, $\sigma=\sigma_{est}/2$)' + '\nPSNR={:0.4g}'.format(psnr_visushrink2), size=10)
plt.subplot(236), plt.imshow(im_visushrink4/im_visushrink4.max()), plt.axis('off')
plt.title('Wavelet denoising\n' + r'(VisuShrink, $\sigma=\sigma_{est}/4$)' + '\nPSNR={:0.4g}'.format(psnr_visushrink4), size=10)
plt.show()

运行以上代码,可以得到以下结果图像:

改进去噪效果

小结

离散小波变换是对基本小波的尺度和平移进行离散化的一种谱分析工具,能够同时考察局部时域过程的频域特征以及局部频域过程的时域特征。对于图像来说,离散小波变换能够将图像变换为一系列的小波系数并将这些系数进行高效的压缩和储存,并且可以更好地还原和表现图像。本节中,我们学习了小波变换的基本原理,以及如何利用 pywtscikit-image 库实现小波变换图像去噪。

系列链接

Python图像处理【1】图像与视频处理基础
Python图像处理【2】探索Python图像处理库
Python图像处理【3】Python图像处理库应用
Python图像处理【4】图像线性变换
Python图像处理【5】图像扭曲/逆扭曲
Python图像处理【6】通过哈希查找重复和类似的图像
Python图像处理【7】采样、卷积与离散傅里叶变换
Python图像处理【8】使用低通滤波器模糊图像
Python图像处理【9】使用高通滤波器执行边缘检测
Python图像处理【10】基于离散余弦变换的图像压缩
Python图像处理【11】利用反卷积执行图像去模糊

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

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

相关文章

上海震坤行工业超市建设数字化采购供应链的实践

上海震坤行工业超市建设数字化采购供应链的实践 对客户而言,MRO工业用品采购一直存在着SKU繁杂、紧急需求多、计划性不强、库存难以管理等特点。有企业统计,MRO零星采购金额占其全类目采购总金额的2%,但是用于管理的时间精力却占到了总体的6…

[使用指南]在使用MyEclipse时如何添加 更新插件

MyEclipse v2022.1.0正式版下载 通过Eclipse市场目录或各种更新站点类型添加插件,可以定制你的MyEclipse IDE(或Angular IDE)。 一、从目录中添加插件 添加额外插件最简单方法是通过Eclipse Marketplace目录。 1. 要打开目录,请从Catalog中选择Help&…

腾讯云服务器网络收发包PPS是什么?性能介绍

什么是网络收发包PPS?云服务器网络收发包PPS多少合适?网络收发包PPS是指云服务器每秒可以处理的网络数据包数量,单位是PPS即packets per second每秒发包数量。云服务器吧来详细说下阿里云服务器网络收发包PPS和腾讯云网络收发包性能参数表&am…

k8s安装部署apollo配置中心

一、文章大纲 二、安装MySQL5.7 三、创建apollo-config 四、创建apollo-admin 五、创建apollo-portal 六、查看apollo各个组件服务状态 七、访问apollo 八、nginx代理配置转发#注意 一定要先启动apollo-config,再启动apollo-admin,最后启动apollo-porta…

什么才是好CDN

选择一种领先于网络和移动技术不断进步以及不断演变的威胁格局的CDN,将使您能够始终如一地为客户提供尽可能好的在线体验,同时最大限度地降低运营复杂性和管理成本。 但问题来了:什么才是最好的CDN? 这个问题的唯一答案是&#x…

HBase高手之路7—HBase之全文检索Phoneix

文章目录 HBase之全文检索Phoenix一、全文检索二、全文检索工具phoenix简介1. 简介2. 使用Phoenix是否会影响HBase性能3. 哪些公司在使用Phoenix4. 官方性能测试4.1 Phoenix对标Hive(基于HDFS和HBase)4.2 Phoenix对标Impala4.3 关于上述官网两张性能测试…

python基础案例题:进制转换、字符串加密的实现、猜拳游戏、多种方法计算π

目录 前言1.进制转换2.字符串加密的实现3.猜拳游戏4.多种方法计算π尾语 💝 前言 嗨喽~大家好呀,这里是魔王呐 ❤ ~! 1.进制转换 功能: 获取十进制整数的二进制串,相当于内置函数bin。 算法分析: 对2辗转相除&…

pyecharts从入门到精通-地图专题Map-世界地图和中国城市地图

文章目录 参考安装与查看pyecharts地图实现-Geo数据集查看读取数据生成中文国家名称国家中文和英文名称字典:根据字典,生成国家中文名查看没有转换成功的国家中文有哪些过滤包含中文国家名的数据 可视化人口数据显示中国城市地图数据 拓展-pyecharts中Map源码拓展-p…

开放耳机有什么优缺点,推荐几款不错的开放式耳机

​由于骨传导耳机可以保持耳朵的开放,长时间佩戴不会有闷热感,同时可以在运动中保持安全,因此被越来越多的人接受。在目前市面上骨传导耳机品牌众多,价格从几十元到上千元不等,为了让大家更好地挑选适合自己的骨传导耳…

java获取两个日期之间的所有日期

1、获取日期的过程: 首先创建一个数组,然后在数组的末尾加上一个日期。当我们有两个日期时,可以把这两个日期当做是不同的数组,然后使用 next函数把这两个日期之间的所有时间都获取出来。 2、代码演示: 3、实现效果&am…

bat批处理文件无法执行

执行后弹出cmd窗口,但里面命令未执行 方案一: 1、打开开始菜单——控制面板 2、点击系统和安全——系统 3、点击左上角的“高级系统设置” 4、切换到“高级”选项卡,点击下方的“环境变量” 5、在用户变量下方点击“新建”,…

3.2.3队列的链式实现

队列的链式实现 注意声明队头指针和队尾指针作用 (1)插入节点的时候只要rear指针指向结点的next指针指向的位置; (2)删除只要front指指针指向的头节点next指针指向的位置删除; (1)初始化(带头结点) 初试化…

C++:多态的底层实现原理 -- 虚函数表

目录 一. 多态的原理 1.1 虚函数表 1.2 多态的实现原理 1.3 动态绑定与静态绑定 二. 多继承中的虚函数表 2.1 虚函数表的打印 2.2 多继承中虚函数表中的内容存储情况 一. 多态的原理 1.1 虚函数表 对于一个含有虚函数的的类,在实例化出来对象以后&#xff0…

Docker部署SpringBoot+Vue项目

1.项目部署规划 1.后端多模块项目blog以及各模块运行端口: 前台服务模块sangeng-blog->7777,后台服务模块sangeng-admin->8989,公共模块sangeng-framework 2.前端前台Vue项目:sg-blog-vue->80 3.前端后台Vue项目&#x…

如何在AWS EKS上部署安装nginx ingress controller

Ingress Controller Ingress Controller 通常是一个负载均衡器,用于将外部流量路由到您的 Kubernetes 集群,并负责 L4-L7 网络服务 Ingress controller 仅覆盖 L7 流量,而入口重新路由 HTTP 和 HTTPS 流量 Type of Ingress Controllers C…

QT编程集成环境在Ubuntu中如何使用ROS工程?

文章目录 0.引言1.安装Qt Creator(带ROS插件)2.创建ROS工程3.创建功能包4.创建节点5.添加编译规则6.编译运行 0.引言 在进行ROS开发过程中,会创建许多功能包和源代码文件,这些文件少量时,手动管理还能接受,…

微搭低代码学习之数据收集

低代码和开发之间的关系 低代码平台是一种快速构建应用程序的工具,旨在提高开发效率。它们提供了一种基于图形用户界面的方式来创建应用程序,而无需编写大量的代码。使用低代码平台,开发人员可以更快速地构建和交付应用程序,从而缩…

nginx--HTTPS服务

目录 1.为什么要使用https 2.https协议的实现 1.对称加密 2.非对称加密 3.https加密 3.生成密钥和CA证书需要的依赖 1.查看是否有装openssl 2.查看nginx是否有 --with-http_ssl_module 4.生成密钥和CA证书步骤 步骤一、生成key密钥 步骤二、通过密钥去生成证书签名请求文件…

Java多例Bean的应用场景-easyExcel导入

目录 1. bean注入方式(IOC)2. 有状态会话bean和无状态会话bean3. 单例模式和多例模式4. 深挖多例模式应用场景? 1. bean注入方式(IOC) 2. 有状态会话bean和无状态会话bean 有状态会话bean:每个用户有自己特…

2023什么电脑配置适合机器学习和人工智能

机器学习和人工智能应用有多种类型——从传统的回归模型、非神经网络分类器和以 Python SciKitLearn 和 R 语言的功能为代表的统计模型,到使用 PyTorch 和 TensorFlow 等框架的深度学习模型. 在这些不同类型的 ML/AI 模型中,也可能存在显着差异。“最佳”…