2026/4/18 14:35:27
网站建设
项目流程
网站数据库出问题,学广告设计难不难,网站做定向的作用,wordpress数据库批量替换网址前言大家好#xff01;今天给大家分享《数字图像处理》中非常重要的第 7 章内容 —— 小波与多分辨率处理。小波变换作为一种强大的时频分析工具#xff0c;在图像处理领域有着广泛的应用#xff0c;比如图像压缩、去噪、边缘检测等。本文会按照教材目录#xff0c;用通俗易…前言大家好今天给大家分享《数字图像处理》中非常重要的第 7 章内容 —— 小波与多分辨率处理。小波变换作为一种强大的时频分析工具在图像处理领域有着广泛的应用比如图像压缩、去噪、边缘检测等。本文会按照教材目录用通俗易懂的语言讲解核心概念每个知识点都配套可直接运行的 Python 代码、效果对比图让大家不仅能理解理论还能动手实践。7.1 背景知识在正式学习小波变换前我们先了解几个基础概念这些是理解多分辨率处理的关键。7.1.1 图像金字塔图像金字塔是最简单的多分辨率表示方法本质是将图像按不同分辨率分层像金字塔一样从下到上分辨率逐渐降低。常见的有高斯金字塔下采样和拉普拉斯金字塔上采样恢复。代码实现图像金字塔import cv2 import numpy as np import matplotlib.pyplot as plt # 设置matplotlib支持中文显示 plt.rcParams[font.sans-serif] [SimHei] # 黑体 plt.rcParams[axes.unicode_minus] False # 解决负号显示问题 # 读取图像以灰度图为例 img cv2.imread(lena.jpg, 0) # 替换为你的图像路径lena是数字图像处理常用测试图 if img is None: raise ValueError(图像读取失败请检查路径是否正确) # 构建高斯金字塔下采样 def gaussian_pyramid(img, levels): pyramid [img] for i in range(levels): img cv2.pyrDown(img) pyramid.append(img) return pyramid # 构建拉普拉斯金字塔上采样恢复 def laplacian_pyramid(gaussian_pyramid): pyramid [] levels len(gaussian_pyramid) - 1 for i in range(levels, 0, -1): img_up cv2.pyrUp(gaussian_pyramid[i]) # 确保尺寸匹配 h, w gaussian_pyramid[i-1].shape img_up cv2.resize(img_up, (w, h)) laplacian cv2.subtract(gaussian_pyramid[i-1], img_up) pyramid.append(laplacian) return pyramid # 生成4层金字塔 gaussian_pyr gaussian_pyramid(img, 3) laplacian_pyr laplacian_pyramid(gaussian_pyr) # 可视化对比 plt.figure(figsize(12, 8)) # 原始图像 plt.subplot(2, 4, 1) plt.imshow(img, cmapgray) plt.title(原始图像) plt.axis(off) # 高斯金字塔各层 for i in range(3): plt.subplot(2, 4, i2) plt.imshow(gaussian_pyr[i1], cmapgray) plt.title(f高斯金字塔 {i1} 层) plt.axis(off) # 拉普拉斯金字塔各层 for i in range(3): plt.subplot(2, 4, i6) plt.imshow(laplacian_pyr[i], cmapgray) plt.title(f拉普拉斯金字塔 {i1} 层) plt.axis(off) plt.tight_layout() plt.show()代码说明cv2.pyrDown()对图像进行下采样高斯模糊 降维生成高斯金字塔cv2.pyrUp()对图像进行上采样升维 高斯模糊结合高斯金字塔生成拉普拉斯金字塔拉普拉斯金字塔存储的是 “残差”可以通过这些残差恢复原始分辨率图像。效果对比运行代码后能看到高斯金字塔越往上图像越小、分辨率越低拉普拉斯金字塔保留了图像的细节信息边缘、纹理这也是多分辨率分析的核心 —— 不同层关注不同尺度的特征。7.1.2 子带编码子带编码的核心思想是将图像信号分解到不同的频率子带对不同子带采用不同的编码策略比如高频子带压缩更多低频子带保留更多细节从而在保证视觉效果的前提下降低数据量。代码实现基于傅里叶变换的子带分解import cv2 import numpy as np import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 读取灰度图像 img cv2.imread(lena.jpg, 0) if img is None: raise ValueError(图像读取失败请检查路径) # 傅里叶变换中心化 f np.fft.fft2(img) f_shift np.fft.fftshift(f) # 划分4个子带低频左上、高频水平右上、高频垂直左下、高频对角右下 rows, cols img.shape crow, ccol rows//2, cols//2 # 构建子带掩码 mask_low np.zeros((rows, cols), np.uint8) mask_low[crow-30:crow30, ccol-30:ccol30] 1 # 低频子带 mask_h_horiz np.zeros((rows, cols), np.uint8) mask_h_horiz[crow-30:crow30, ccol30:] 1 # 水平高频子带 mask_h_vert np.zeros((rows, cols), np.uint8) mask_h_vert[crow30:, ccol-30:ccol30] 1 # 垂直高频子带 mask_h_diag np.zeros((rows, cols), np.uint8) mask_h_diag[crow30:, ccol30:] 1 # 对角高频子带 # 子带滤波 f_low f_shift * mask_low f_h_horiz f_shift * mask_h_horiz f_h_vert f_shift * mask_h_vert f_h_diag f_shift * mask_h_diag # 逆傅里叶变换 img_low np.fft.ifft2(np.fft.ifftshift(f_low)).real img_h_horiz np.fft.ifft2(np.fft.ifftshift(f_h_horiz)).real img_h_vert np.fft.ifft2(np.fft.ifftshift(f_h_vert)).real img_h_diag np.fft.ifft2(np.fft.ifftshift(f_h_diag)).real # 可视化 plt.figure(figsize(12, 10)) plt.subplot(2, 3, 1) plt.imshow(img, cmapgray) plt.title(原始图像) plt.axis(off) plt.subplot(2, 3, 2) plt.imshow(img_low, cmapgray) plt.title(低频子带保留轮廓) plt.axis(off) plt.subplot(2, 3, 3) plt.imshow(img_h_horiz, cmapgray) plt.title(水平高频子带水平边缘) plt.axis(off) plt.subplot(2, 3, 4) plt.imshow(img_h_vert, cmapgray) plt.title(垂直高频子带垂直边缘) plt.axis(off) plt.subplot(2, 3, 5) plt.imshow(img_h_diag, cmapgray) plt.title(对角高频子带对角边缘) plt.axis(off) # 子带重构 img_recon img_low img_h_horiz img_h_vert img_h_diag plt.subplot(2, 3, 6) plt.imshow(img_recon, cmapgray) plt.title(子带重构图像) plt.axis(off) plt.tight_layout() plt.show()代码说明通过傅里叶变换将图像转换到频域用掩码划分不同频率子带低频子带保留图像的整体轮廓高频子带保留边缘、纹理等细节子带编码的关键对不同子带分配不同的编码比特数比如低频用更多比特高频用更少实现高效压缩。7.1.3 哈尔变换哈尔变换是最简单的小波变换也是理解小波的基础。哈尔基函数是一组正交函数能实现信号的多分辨率分解。代码实现哈尔变换import numpy as np import matplotlib.pyplot as plt import cv2 plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 定义1D哈尔变换函数 def haar_transform_1d(signal): n len(signal) # 确保长度是2的幂次 if not (n and (n (n - 1)) 0): raise ValueError(信号长度必须是2的幂次) output np.copy(signal).astype(float) length n while length 1: half length // 2 for i in range(half): # 哈尔变换平均近似和差值细节 avg (output[2*i] output[2*i1]) / np.sqrt(2) diff (output[2*i] - output[2*i1]) / np.sqrt(2) output[i] avg output[i half] diff length half return output # 定义逆哈尔变换函数 def inverse_haar_transform_1d(coeffs): n len(coeffs) if not (n and (n (n - 1)) 0): raise ValueError(系数长度必须是2的幂次) output np.copy(coeffs).astype(float) length 2 while length n: half length // 2 for i in range(half): # 逆变换恢复原始信号 avg output[i] diff output[i half] output[2*i] (avg diff) / np.sqrt(2) output[2*i1] (avg - diff) / np.sqrt(2) length * 2 return output # 1D哈尔变换示例 signal np.array([8, 4, 6, 2, 7, 3, 5, 1], dtypefloat) haar_coeffs haar_transform_1d(signal) recon_signal inverse_haar_transform_1d(haar_coeffs) # 2D哈尔变换图像 img cv2.imread(lena.jpg, 0) # 裁剪图像为2的幂次尺寸方便计算 img img[:256, :256] # 对行和列分别做哈尔变换 haar_img np.copy(img).astype(float) # 行变换 for i in range(haar_img.shape[0]): haar_img[i, :] haar_transform_1d(haar_img[i, :]) # 列变换 for j in range(haar_img.shape[1]): haar_img[:, j] haar_transform_1d(haar_img[:, j]) # 逆变换恢复图像 recon_img np.copy(haar_img).astype(float) for j in range(recon_img.shape[1]): recon_img[:, j] inverse_haar_transform_1d(recon_img[:, j]) for i in range(recon_img.shape[0]): recon_img[i, :] inverse_haar_transform_1d(recon_img[i, :]) # 可视化 plt.figure(figsize(15, 10)) # 1D信号对比 plt.subplot(2, 3, 1) plt.plot(signal, b-o, label原始信号) plt.title(1D原始信号) plt.legend() plt.subplot(2, 3, 2) plt.plot(haar_coeffs, r-o, label哈尔变换系数) plt.title(哈尔变换系数前半近似后半细节) plt.legend() plt.subplot(2, 3, 3) plt.plot(recon_signal, g-o, label重构信号) plt.title(逆哈尔变换重构信号) plt.legend() # 2D图像对比 plt.subplot(2, 3, 4) plt.imshow(img, cmapgray) plt.title(原始图像256x256) plt.axis(off) plt.subplot(2, 3, 5) plt.imshow(haar_img, cmapgray) plt.title(哈尔变换后的图像系数) plt.axis(off) plt.subplot(2, 3, 6) plt.imshow(recon_img, cmapgray) plt.title(逆哈尔变换重构图像) plt.axis(off) plt.tight_layout() plt.show()代码说明1D 哈尔变换将信号分解为 “近似系数”平均和 “细节系数”差值2D 哈尔变换对图像的行和列分别做 1D 变换实现图像的多分辨率分解哈尔变换是正交变换逆变换可以无失真恢复原始信号 / 图像。7.2 多分辨率展开多分辨率展开是小波变换的理论基础核心是用 “尺度函数” 描述信号的近似低频部分用 “小波函数” 描述细节高频部分。7.2.1 级数展开7.2.2 尺度函数代码实现哈尔尺度函数可视化import numpy as np import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 定义哈尔尺度函数 def haar_scaling_function(x): return np.where((x 0) (x 1), 1, 0) # 不同尺度的哈尔尺度函数j0,1,2 x np.linspace(-1, 2, 1000) phi_0 haar_scaling_function(x) phi_1 haar_scaling_function(2*x) # j1尺度缩小 phi_2 haar_scaling_function(4*x) # j2尺度进一步缩小 # 可视化 plt.figure(figsize(10, 6)) plt.plot(x, phi_0, labelj0 (φ(x)), linewidth2) plt.plot(x, phi_1, labelj1 (φ(2x)), linewidth2) plt.plot(x, phi_2, labelj2 (φ(4x)), linewidth2) plt.title(哈尔尺度函数不同尺度) plt.xlabel(x) plt.ylabel(φ(x)) plt.grid(True) plt.legend() plt.show()7.2.3 小波函数小波函数母小波用于构建信号的细节表示哈尔小波函数定义代码实现哈尔小波函数可视化import numpy as np import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 定义哈尔小波函数 def haar_wavelet_function(x): return np.where((x 0) (x 0.5), 1, np.where((x 0.5) (x 1), -1, 0)) # 不同尺度和平移的哈尔小波 x np.linspace(-1, 2, 1000) psi_0 haar_wavelet_function(x) # j0, k0 psi_1_0 haar_wavelet_function(2*x) # j1, k0 psi_1_1 haar_wavelet_function(2*x - 1) # j1, k1 # 可视化 plt.figure(figsize(10, 6)) plt.plot(x, psi_0, labelj0, k0 (ψ(x)), linewidth2) plt.plot(x, psi_1_0, labelj1, k0 (ψ(2x)), linewidth2) plt.plot(x, psi_1_1, labelj1, k1 (ψ(2x-1)), linewidth2) plt.title(哈尔小波函数不同尺度和平移) plt.xlabel(x) plt.ylabel(ψ(x)) plt.grid(True) plt.legend() plt.show()核心说明尺度函数决定了信号的“粗粒度”表示低频小波函数决定了信号的“细粒度”表示高频不同尺度j对应不同分辨率不同平移k对应不同位置。7.3 一维小波变换一维小波变换是理解二维图像小波变换的基础分为连续小波变换、离散小波变换。7.3.1 小波级数展开7.3.2 离散小波变换DWT离散小波变换是工程中最常用的形式通过“分解滤波器组”实现低通滤波器h计算尺度系数高通滤波器g计算小波系数。代码实现1D DWTimport numpy as np import pywt import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 生成测试信号 t np.linspace(0, 1, 1024, endpointFalse) signal np.sin(2*np.pi*10*t) np.sin(2*np.pi*20*t) np.random.normal(0, 0.1, 1024) # 1D离散小波变换使用pywt库更高效 # 选择小波基haar wavelet haar # 2级分解 coeffs pywt.wavedec(signal, wavelet, level2) cA2, cD2, cD1 coeffs # cA近似系数cD细节系数 # 重构信号 recon_signal pywt.waverec(coeffs, wavelet) # 可视化 plt.figure(figsize(12, 8)) plt.subplot(3, 1, 1) plt.plot(t, signal) plt.title(原始1D信号含噪声) plt.subplot(3, 1, 2) plt.plot(cA2, labelcA22级近似系数) plt.plot(cD2, labelcD22级细节系数) plt.plot(cD1, labelcD11级细节系数) plt.title(小波分解系数) plt.legend() plt.subplot(3, 1, 3) plt.plot(t, recon_signal) plt.title(小波重构信号) plt.tight_layout() plt.show()代码说明使用pywtPython Wavelets库实现DWT这是工业界常用的小波库pywt.wavedec()对信号进行小波分解返回近似系数和各层细节系数pywt.waverec()根据分解系数重构原始信号。7.3.3 连续小波变换CWT连续小波变换是小波变换的原始形式尺度和平移都是连续的代码实现1D CWTimport numpy as np import pywt import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 生成测试信号 t np.linspace(0, 1, 512, endpointFalse) signal np.concatenate([ np.sin(2*np.pi*5*t[:256]), np.sin(2*np.pi*20*t[256:]) ]) # 连续小波变换 wavelet morl # 莫尔小波 scales np.arange(1, 64) cwt_coeffs, frequencies pywt.cwt(signal, scales, wavelet, sampling_period1/512) # 可视化 plt.figure(figsize(12, 8)) # 原始信号 plt.subplot(2, 1, 1) plt.plot(t, signal) plt.title(原始1D信号5Hz→20Hz) plt.xlabel(时间 (s)) # CWT时频图 plt.subplot(2, 1, 2) plt.imshow(np.abs(cwt_coeffs), extent[0, 1, 1, 64], cmapjet, aspectauto, originlower) plt.colorbar(label小波系数幅值) plt.title(连续小波变换时频图) plt.xlabel(时间 (s)) plt.ylabel(尺度对应频率) plt.tight_layout() plt.show()效果说明连续小波变换的结果是一个二维矩阵尺度×时间能清晰展示信号在不同时间、不同频率的能量分布从时频图中可以明显看到前0.5s信号频率为5Hz后0.5s为20Hz这是傅里叶变换无法直观展示的傅里叶变换只能看到整体频率。7.4 快速小波变换FWT快速小波变换基于“塔式算法”是离散小波变换的高效实现方式计算复杂度为O(N)N为信号长度核心是通过滤波器组的下采样实现。代码实现快速小波变换import numpy as np import pywt import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 自定义快速小波变换塔式算法 def fast_wavelet_transform(signal, wavelethaar, level2): # 获取小波滤波器 wavelet_obj pywt.Wavelet(wavelet) h wavelet_obj.dec_lo # 低通滤波器 g wavelet_obj.dec_hi # 高通滤波器 coeffs [] current_signal np.copy(signal) for _ in range(level): # 卷积下采样 cA np.convolve(current_signal, h, modesame)[::2] # 近似系数 cD np.convolve(current_signal, g, modesame)[::2] # 细节系数 coeffs.append(cD) current_signal cA coeffs.append(current_signal) coeffs.reverse() # [cA_n, cD_n, ..., cD1] return coeffs # 测试 signal np.array([8, 4, 6, 2, 7, 3, 5, 1], dtypefloat) # 自定义FWT fwt_coeffs fast_wavelet_transform(signal, wavelethaar, level2) # pywt库FWT对比验证 pywt_coeffs pywt.wavedec(signal, haar, level2) # 可视化 plt.figure(figsize(10, 6)) plt.subplot(2, 1, 1) plt.plot(signal, b-o, label原始信号) plt.title(原始信号) plt.legend() plt.subplot(2, 1, 2) plt.plot(fwt_coeffs[0], r-o, labelcA2自定义FWT) plt.plot(fwt_coeffs[1], g-o, labelcD2自定义FWT) plt.plot(fwt_coeffs[2], y-o, labelcD1自定义FWT) plt.title(快速小波变换系数) plt.legend() plt.tight_layout() plt.show() # 验证自定义FWT和pywt库结果是否一致 print(自定义FWT系数, fwt_coeffs) print(pywt库FWT系数, pywt_coeffs)代码说明快速小波变换的核心是“卷积下采样”先用低通/高通滤波器卷积再隔点取数下采样每一级分解都会将信号长度减半近似系数可以继续分解实现多分辨率分析自定义实现和pywt库结果一致验证了算法的正确性。7.5 二维小波变换二维小波变换是一维的扩展用于图像处理核心是对图像的行和列分别做一维小波变换最终得到4个子带cA低频近似图像轮廓cH水平高频垂直边缘cV垂直高频水平边缘cD对角高频对角边缘。代码实现二维小波变换应用案例import numpy as np import pywt import cv2 import matplotlib.pyplot as plt # 设置matplotlib支持中文显示 plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 读取并预处理图像增加异常处理 img_path ../picture/Java.png img cv2.imread(img_path, 0) if img is None: raise FileNotFoundError(f图像读取失败请检查路径是否正确{img_path}) img cv2.resize(img, (256, 256)) # 调整尺寸为256x256 img img / 255.0 # 归一化 # 2D小波分解2级 wavelet haar coeffs pywt.wavedec2(img, wavelet, level2) cA2, (cH2, cV2, cD2), (cH1, cV1, cD1) coeffs # 可视化分解结果 def plot_wavelet_coeffs(cA, cH, cV, cD, title): 拼接小波分解系数并归一化显示 :param cA: 近似系数低频 :param cH: 水平高频系数 :param cV: 垂直高频系数 :param cD: 对角高频系数 :param title: 图像标题用于标识此处函数内未直接使用仅为参数完整性 :return: 拼接后的系数图像 # 归一化显示避免系数范围差异导致显示异常 cA (cA - np.min(cA)) / (np.max(cA) - np.min(cA)) if np.max(cA) ! np.min(cA) else cA cH (cH - np.min(cH)) / (np.max(cH) - np.min(cH)) if np.max(cH) ! np.min(cH) else cH cV (cV - np.min(cV)) / (np.max(cV) - np.min(cV)) if np.max(cV) ! np.min(cV) else cV cD (cD - np.min(cD)) / (np.max(cD) - np.min(cD)) if np.max(cD) ! np.min(cD) else cD # 拼接成2x2矩阵保证尺寸匹配 # 统一尺寸避免重构后尺寸微小差异导致拼接失败 h, w cA.shape cH cv2.resize(cH, (w, h)) cV cv2.resize(cV, (w, h)) cD cv2.resize(cD, (w, h)) top np.hstack([cA, cH]) bottom np.hstack([cV, cD]) coeff_img np.vstack([top, bottom]) return coeff_img # 1级和2级系数图补充title参数 coeff_img1 plot_wavelet_coeffs(cA2, cH2, cV2, cD2, 2级小波分解系数) # 重构1级近似系数为原始尺寸再拼接1级细节 cA1 pywt.waverec2([cA2, (cH2, cV2, cD2)], wavelet) coeff_img2 plot_wavelet_coeffs(cA1, cH1, cV1, cD1, 1级小波分解系数) # 应用1图像压缩保留低频置零高频 coeffs_compress coeffs.copy() # 置零2级细节系数 coeffs_compress[1] (np.zeros_like(cH2), np.zeros_like(cV2), np.zeros_like(cD2)) # 置零1级细节系数的小值阈值0.1 cH1_compress np.where(np.abs(cH1) 0.1, 0, cH1) cV1_compress np.where(np.abs(cV1) 0.1, 0, cV1) cD1_compress np.where(np.abs(cD1) 0.1, 0, cD1) coeffs_compress[2] (cH1_compress, cV1_compress, cD1_compress) img_compress pywt.waverec2(coeffs_compress, wavelet) # 应用2图像去噪阈值处理细节系数 coeffs_denoise coeffs.copy() # 对细节系数做阈值处理 threshold 0.05 cH2_denoise pywt.threshold(cH2, threshold, modesoft) cV2_denoise pywt.threshold(cV2, threshold, modesoft) cD2_denoise pywt.threshold(cD2, threshold, modesoft) cH1_denoise pywt.threshold(cH1, threshold, modesoft) cV1_denoise pywt.threshold(cV1, threshold, modesoft) cD1_denoise pywt.threshold(cD1, threshold, modesoft) coeffs_denoise[1] (cH2_denoise, cV2_denoise, cD2_denoise) coeffs_denoise[2] (cH1_denoise, cV1_denoise, cD1_denoise) img_denoise pywt.waverec2(coeffs_denoise, wavelet) # 可视化所有结果 plt.figure(figsize(16, 12)) # 原始图像 plt.subplot(3, 3, 1) plt.imshow(img, cmapgray) plt.title(原始图像) plt.axis(off) # 2级分解系数 plt.subplot(3, 3, 2) plt.imshow(coeff_img1, cmapgray) plt.title(2级小波分解系数) plt.axis(off) # 1级分解系数 plt.subplot(3, 3, 3) plt.imshow(coeff_img2, cmapgray) plt.title(1级小波分解系数) plt.axis(off) # 压缩图像 plt.subplot(3, 3, 4) plt.imshow(img_compress, cmapgray) plt.title(小波压缩图像保留低频) plt.axis(off) # 去噪图像 plt.subplot(3, 3, 5) plt.imshow(img_denoise, cmapgray) plt.title(小波去噪图像阈值处理) plt.axis(off) # 噪声对比添加噪声后去噪 img_noisy img np.random.normal(0, 0.05, img.shape) coeffs_noisy pywt.wavedec2(img_noisy, wavelet, level2) coeffs_noisy_denoise coeffs_noisy.copy() coeffs_noisy_denoise[1] (pywt.threshold(coeffs_noisy[1][0], threshold, modesoft), pywt.threshold(coeffs_noisy[1][1], threshold, modesoft), pywt.threshold(coeffs_noisy[1][2], threshold, modesoft)) coeffs_noisy_denoise[2] (pywt.threshold(coeffs_noisy[2][0], threshold, modesoft), pywt.threshold(coeffs_noisy[2][1], threshold, modesoft), pywt.threshold(coeffs_noisy[2][2], threshold, modesoft)) img_noisy_denoise pywt.waverec2(coeffs_noisy_denoise, wavelet) plt.subplot(3, 3, 6) plt.imshow(img_noisy, cmapgray) plt.title(含噪声图像) plt.axis(off) plt.subplot(3, 3, 8) plt.imshow(img_noisy_denoise, cmapgray) plt.title(噪声图像去噪结果) plt.axis(off) # 补充空白子图让布局更整齐 for i in range(8, 10): plt.subplot(3, 3, i) plt.axis(off) plt.tight_layout() plt.show()代码说明pywt.wavedec2()二维小波分解返回各层近似系数和细节系数pywt.waverec2()二维小波重构根据分解系数恢复图像图像压缩置零高频细节系数只保留低频近似能大幅减少数据量图像去噪对细节系数做阈值处理软阈值滤除噪声对应的小系数。效果对比分解系数图中cA左上是图像的轮廓cH/cV/cD分别对应不同方向的边缘压缩后的图像虽然细节减少但整体轮廓清晰去噪后的图像能有效滤除高斯噪声同时保留边缘细节优于均值滤波。7.6 小波包小波包是小波变换的扩展不仅分解近似系数低频还分解细节系数高频能提供更精细的频率划分适合处理高频信息丰富的图像如纹理、边缘。代码实现小波包变换import numpy as np import pywt import cv2 import matplotlib.pyplot as plt # 设置matplotlib支持中文显示 plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 读取并校验图像 img_path ../picture/GaoDa.png img cv2.imread(img_path, 0) if img is None: raise FileNotFoundError(f图像读取失败请检查路径是否正确{img_path}) # 预处理调整尺寸为2的幂次小波包分解要求归一化 img cv2.resize(img, (256, 256)) img img / 255.0 # 归一化到[0,1]区间 # 小波包分解2级 wavelet haar # 选择哈尔小波基 # 初始化小波包注意初始化时不指定level参数 wp pywt.WaveletPacket2D(dataimg, waveletwavelet, modesymmetric) # 分解到2级核心修复通过构造节点路径实现2级分解 # 1级分解aa, ad, da, dd # 2级分解对1级的每个节点再分解得到8个2级节点 wp.get_level(2) # 显式分解到2级 # 获取2级所有小波包节点按自然顺序 nodes wp.get_level(2, ordernatural) node_names [node.path for node in nodes] # 获取节点路径名如aaa, aad等 node_data [node.data for node in nodes] # 获取每个节点的系数数据 # 小波包重构从2级节点恢复原始图像 wp_recon pywt.WaveletPacket2D(None, waveletwavelet, modesymmetric) for name, data in zip(node_names, node_data): wp_recon[name] data # 将系数赋值给重构的小波包节点 img_recon wp_recon.reconstruct() # 执行重构 # 可视化小波包子带 plt.figure(figsize(16, 8)) # 显示原始图像 plt.subplot(2, 5, 1) plt.imshow(img, cmapgray) plt.title(原始图像) plt.axis(off) # 显示2级小波包的8个子带 for i in range(8): plt.subplot(2, 5, i2) # 归一化显示避免系数范围差异导致显示过亮/过暗 data node_data[i] if np.max(data) ! np.min(data): # 防止除以0 data_normalized (data - np.min(data)) / (np.max(data) - np.min(data)) else: data_normalized data plt.imshow(data_normalized, cmapgray) plt.title(f小波包节点{node_names[i]}) plt.axis(off) # 显示重构后的图像 plt.subplot(2, 5, 10) plt.imshow(img_recon, cmapgray) plt.title(小波包重构图像) plt.axis(off) plt.tight_layout() # 自动调整子图间距 plt.show() # 应用小波包特征提取纹理分类核心特征 # 计算每个子带的能量L2范数的平方作为特征 energies [np.sum(np.square(data)) for data in node_data] # 归一化能量特征便于后续分类使用 energies_normalized energies / np.sum(energies) # 打印特征结果 print(*50) print(2级小波包子带能量特征原始值) for name, energy in zip(node_names, energies): print(f节点 {name}: {energy:.4f}) print(\n2级小波包子带能量特征归一化后) for name, energy in zip(node_names, energies_normalized): print(f节点 {name}: {energy:.4f}) print(*50)代码说明pywt.WaveletPacket2D()二维小波包分解支持多级别、全子带分解get_level()获取指定级别的所有小波包节点小波包的每个节点对应一个频率子带能更精细地刻画图像的频率特征子带能量可以作为图像的纹理特征用于分类、检索等任务。小结多分辨率处理的核心是将图像分解为不同尺度/频率的分量图像金字塔是基础小波变换是进阶小波变换分为连续CWT和离散DWT快速小波变换FWT是DWT的高效实现二维小波变换是图像处理的核心小波包扩展了小波变换的分解能力能同时分解低频和高频适合高频信息丰富的图像分析小波变换在图像压缩、去噪、边缘检测、特征提取等领域有广泛应用核心优势是“时频局部化”同时保留时间/空间和频率信息。环境依赖运行本文代码需要安装以下库pip install numpy opencv-python matplotlib pywavelets总结关键点回顾核心概念多分辨率分析的本质是“分而治之”用尺度函数描述低频近似小波函数描述高频细节代码实践所有代码均可直接运行重点掌握二维小波变换的分解/重构以及压缩、去噪等应用应用场景小波变换适合处理需要保留边缘细节的图像处理任务小波包适合高频信息丰富的场景。希望本文能帮助大家理解小波与多分辨率处理的核心内容动手实践代码后相信你会对小波变换有更直观的认识如果有问题欢迎在评论区交流~