天天看點

信号處理 - 小波 - 努力的孔子

信号處理 - 小波

小波,就是很小的波,它的積分總是接近于 0;

小波 又分為 小波分解 和 小波包分解;

小波分解 隻對 低頻部分 進行分解,對高頻部分不再分解,是以能夠過濾掉 高頻部分;

信号處理 - 小波 - 努力的孔子

低頻部分 代表了 趨勢,也叫 近似信号;高頻部分 代表了 噪聲,也叫 細節信号;

小波包分解 則既對 低頻部分 進行分解,也對 高頻部分 進行分解;

信号處理 - 小波 - 努力的孔子

對小波的了解

小波變換 就是把 一個波形 分解成 N個 低頻部分 和 M個 高頻部分 的 和; 

同一個小波基函數可以通過 平移和縮放 生成不同的小波基;

小波變換就是 把 原始信号 與 小波基函數 以及 尺度函數 進行内積運算,是以一個 小波基 和一個 尺度函數 就确定了一個小波變換;

類比了解:小波基 就相當于 一個 标準正交基;原始信号 與 小波基 作内積 相當于 向量在 标準正交基上做投影;

Python 小波用法 

CWT:連續的小波變換

DWT:離散的小波變換

安裝

pip install PyWavelets      

檢視所有小波族

import pywt

print(pywt.families())      # 檢視所有小波基
# [\'haar\', \'db\', \'sym\', \'coif\', \'bior\', \'rbio\', \'dmey\', \'gaus\', \'mexh\', \'morl\', \'cgau\', \'shan\', \'fbsp\', \'cmor\']
print(pywt.families(short=False))
# [\'Haar\', \'Daubechies\', \'Symlets\', \'Coiflets\', \'Biorthogonal\', \'Reverse biorthogonal\', \'Discrete Meyer (FIR Approximation)\', \'Gaussian\', \'Mexican hat wavelet\', \'Morlet wavelet\', \'Complex Gaussian wavelets\', \'Shannon wavelets\', \'Frequency B-Spline wavelets\', \'Complex Morlet wavelets\']      

離散 1D 小波變換 

1D 多階小波變換 wavedec

def wavedec(data, wavelet, mode=\'symmetric\', level=None, axis=-1):
    """
    Multilevel 1D Discrete Wavelet Transform of data.
    wavelet : Wavelet object or name string    小波基
        Wavelet to use
    mode : str, optional    預設是對稱的
        Signal extension mode, see :ref:`Modes <ref-modes>`.
    level : int, optional
        Decomposition level (must be >= 0). If level is None (default) then it
        will be calculated using the ``dwt_max_level`` function.
    axis: int, optional
        Axis over which to compute the DWT. If not given, the last axis is used.

    Returns
    -------
    [cA_n, cD_n, cD_n-1, ..., cD2, cD1] : list
      

level 指定了 分解 階數 

傳回的是 各層的小波系數     【也就是 特征值,一個 信号 分解為 多個 波形,每個 波形 對應一個 小波系數,計算 這個小波系數 的範數,就是這個 波形 對應的 能量】

示例

import numpy as np
from pywt import wavedec
import matplotlib.pylab as plt

np.random.seed(10)
data = np.random.random((100, ))
coeffs = wavedec(data, \'db1\', level=2)     # 一維離散信号的小波變換
cA2, cD2, cD1 = coeffs      # 一個低頻,多個高頻,高頻數 取決于 level

plt.subplot(411); plt.title(\'original\'); plt.plot(data)
plt.subplot(412); plt.title(\'ca2\'); plt.plot(cA2)
plt.subplot(413); plt.title(\'cd2\'); plt.plot(cD2)
plt.subplot(414); plt.title(\'cd1\'); plt.plot(cD1)
plt.show()      
信号處理 - 小波 - 努力的孔子

1D 1 階小波分解    

level = 2 相當于 進行了 2 次 1階小波分解

def dwt(data, wavelet, mode=\'symmetric\', axis=-1)      

可以看到 沒有 level 參數,level 恒為 1

與 wavedec 進行比對,指定 wavedec level=2,結果相同

np.random.seed(10)
data = np.random.random((10, ))
coeffs = wavedec(data, \'db1\', level=2)     # 一維離散信号的小波變換
cA2, cD2, cD1 = coeffs      # 一個低頻,多個高頻,高頻數 取決于 level
print(cA2)      # [1.08726236 0.84094862 0.25745065]
print(cD2)      # [-0.29518976 -0.11764496  0.        ]
print(cD1)      # [ 0.53073221 -0.08142734  0.19354246 -0.39772483  0.05711374]

### 一次 小波分解, level=1
a = data
ca = []  # 近似分量
cd = []  # 細節分量
for i in range(2):
    (a, d) = pywt.dwt(a, \'db1\')  # 進行2階離散小波變換
    ca.append(a)
    cd.append(d)

print(ca)   # [array([0.5600799 , 0.97754127, 0.51145292, 0.67782802, 0.1820451 ]), array([1.08726236, 0.84094862, 0.25745065])]    ### 取最後一個 近似信号
print(cd)   # [array([ 0.53073221, -0.08142734,  0.19354246, -0.39772483,  0.05711374]), array([-0.29518976, -0.11764496,  0.        ])]      

wavedec 相當于 dwt 的封裝 

離散 2D 小波變換 

用法 基本 等同于 1D

2D 1階小波變換 dwt2

def dwt2(data, wavelet, mode=\'symmetric\', axes=(-2, -1)):
    returns (cA, (cH, cV, cD)) : tuple
             

要注意傳回值,分别為低頻分量,水準高頻、垂直高頻、對角線高頻。高頻的值包含在一個tuple中

示例

import pywt
import pywt.data

# Load image
original = pywt.data.camera()

# Wavelet transform of image, and plot approximation and details
titles = [\'Approximation\', \'Horizontal detail\', \'Vertical detail\', \'Diagonal detail\']
coeffs2 = pywt.dwt2(original, \'bior1.3\')        # 2D 離散信号 小波分解
LL, (LH, HL, HH) = coeffs2
fig = plt.figure(figsize=(12, 3))
for i, a in enumerate([LL, LH, HL, HH]):
    ax = fig.add_subplot(1, 4, i + 1)
    ax.imshow(a, interpolation="nearest", cmap=plt.cm.gray)
    ax.set_title(titles[i], fontsize=10)
    ax.set_xticks([])
    ax.set_yticks([])

fig.tight_layout()
plt.show()      
信号處理 - 小波 - 努力的孔子

2D 多階小波變換 wavedec2

print(pywt.waverec2(coeffs, wavelet=\'db1\',  level=3))      

官網有 level 參數,我的版本沒有,應該是版本問題,暫未解決

信号重構

小波 經常用于 降噪,降完噪後 需要把 信号進行重構,生成無噪聲的信号,1D、2D 用法類似

def waverec(coeffs, wavelet, mode=\'symmetric\', axis=-1)      

示例

import numpy as np
import pywt
import matplotlib.pylab as plt

plt.rcParams[\'font.sans-serif\']=[\'SimHei\']
plt.rcParams[\'axes.unicode_minus\']=False

data = np.hstack([np.ones((1, 10)), np.ones((1, 50)) * 2])[0]
ca, cd2, cd1 = pywt.wavedec(data, \'db1\', level=2)
plt.subplot(211)
plt.title(\'original\')
plt.plot(data)

out = pywt.waverec([ca, cd2, cd1], \'db1\')
plt.subplot(212)
plt.title(\'重構信号\')
plt.plot(out)
plt.show()      
信号處理 - 小波 - 努力的孔子

小波 VS 傅裡葉變換

小波變換還是比較複雜的,确切地說 如果想 徹底弄懂,基本不可能,我這裡 隻重點記錄下 學習心得

1. 傅裡葉變換 的 基 隻能是 正弦波,如果 原始波形 比較陡峭,需要無窮多的 正弦波 才能逼近 這種陡峭,計算量很大;小波基 則 比較 靈活,甚至可以自定義小波基;

2. 正弦波 會以 同樣的 幅度 在無窮大空間内做 無限震動,能量巨大;而 小波 是一個 很短的波,它的能力比較集中,而且集中在 某一點附近; 如下圖

信号處理 - 小波 - 努力的孔子

  

信号處理 - 小波 - 努力的孔子

之是以叫 小波,就是 跟 傅裡葉的正弦波 比較起來 很小 

3. 小波 擅長 瞬時突變 信号的檢測,傅裡葉變換無能為力 

小波 應用于 特征提取

信号處理 - 小波 - 努力的孔子

代碼

#進行小波變換,提取樣本特征
wp = pywt.WaveletPacket(SingleSampleDataWavelet, wavelet=\'db3\', mode=\'symmetric\', maxlevel=3) #小波包三層分解
#print([node.path for node in wp.get_level(3, \'natural\')])   #第3層有8個
#擷取第level層的節點系數
aaa = wp[\'aaa\'].data #第1個節點
aad = wp[\'aad\'].data #第2個節點
ada = wp[\'ada\'].data #第3個節點
add = wp[\'add\'].data #第4個節點
daa = wp[\'daa\'].data #第5個節點
dad = wp[\'dad\'].data #第6個節點
dda = wp[\'dda\'].data #第7個節點
ddd = wp[\'ddd\'].data #第8個節點
#求取節點的範數
ret1 = np.linalg.norm(aaa,ord=None) #第一個節點系數求得的範數/ 矩陣元素平方和開方
ret2 = np.linalg.norm(aad,ord=None)
ret3 = np.linalg.norm(ada,ord=None)
ret4 = np.linalg.norm(add,ord=None)
ret5 = np.linalg.norm(daa,ord=None)
ret6 = np.linalg.norm(dad,ord=None)
ret7 = np.linalg.norm(dda,ord=None)
ret8 = np.linalg.norm(ddd,ord=None)
#8個節點組合成特征向量
SingleSampleFeature = [ret1, ret2, ret3, ret4, ret5, ret6, ret7, ret8]      

關鍵是 細節信号 的能量 計算,其實就是 系數(類似于特征值大小) 的 歸一化

參考資料:

https://www.cnblogs.com/shuimuqingyang/p/10919918.html  小波變換庫——Pywalvets 學習筆記

https://pywavelets.readthedocs.io/en/latest/ref/index.html    PyWavelets 官網

https://github.com/PyWavelets/pywt    PyWavelets git上的demo

https://blog.csdn.net/alwaystry/article/details/52756051  用法挺全的

https://zhuanlan.zhihu.com/p/44215123  小波變換完美通俗講解系列之 (一)    【原理就看這篇吧】

https://blog.csdn.net/zds13257177985/article/details/102896041?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase  小波包變換/能量特征提取/結果圖繪制-python代碼

發表于

2020-07-07 14:12 

努力的孔子 

閱讀(1316) 

評論(0) 

編輯 

收藏 

舉報

信号處理 - 小波 - 努力的孔子