離散沃爾什變換(DWT)與DHT的實現思路其實是一致的,只是變換核需要經過一個變換,這里記錄下原理和實現方法。
哈達瑪變換核
哈達瑪變換核具有遞推性,也就是\(H_{2N}\)可以由\(H_{N}\)得到:
\[H_{2N}=\frac{1}{\sqrt{2}} \left[ \begin{array}{cc} H_{N} & H_{N} \\\\ H_{N} & -H_{N} \end{array} \right] \]
哈達瑪變換核的另一個特點是,變號次數亂序,以\(H_4\)為例,每行的變號次數分別如下:
\[H_4 = \frac{1}{2} \left[ \begin{array}{cccc} 1&1&1&1 \\ 1 &-1& 1 &-1 \\ 1 &1 &-1& -1 \\ 1 &-1 &-1 &1 \end{array} \right] \begin{array}{cccc} 0\\ 3 \\ 1 \\ 2 \end{array} \]
沃爾什變換核
沃爾什變換核可以從與哈達瑪變換核間接得到,只需將DHT的變換核按變號次序遞增重新排列即可
\[W_4 = \frac{1}{2} \left[ \begin{array}{cccc} 1&1&1&1 \\ 1 &1 &-1& -1 \\ 1 &-1 &-1 &1 \\ 1 &-1& 1 &-1 \\ \end{array} \right] \begin{array}{cccc} 0\\ 1 \\ 2 \\ 3 \end{array} \]
程序實現
生成DHT變換核
在scipy.linalg這個庫中,已經實現了DHT的變換核生成,我們可以通過以下語句調用
from scipy.linalg import hadamard
H4 = hadamard(4)
生成DWT變換核
要得到沃爾什變換核,我們要先得到DHT變換核每一行的變號次數,然后按照變號次數排列,具體實現上我采用的方法如下:
- 生成變號次數向量invTimes
要獲取H矩陣的變號次數,可以對H矩陣的每行取差分,然后取絕對值求和再除2(稍微一想就明白,這里不解釋了哈),這些操作在numpy 中都有相應的函數diffMat = np.abs(np.diff(H))/2 invTimes = np.sum(diffMat,axis = 1)
- 對invTimes進行排序
對invTImes這個列向量排序並不難,問題是我們要在排序時或者排序后能對H矩陣做相同的排序操作,這里我想了很久發現可以通過numpy數組的花式索引來解決
numpy 排序方法不止一種,但我們想要的不是排序好的數組,而是排序的過程,也即是原數組每一行排序后在哪個位置,好在 ndarray 對象有 argsort() 方法能滿足我們的需求,它返回的是原數組排序后的索引。#對invTImes排序會是這樣,因為argsort()返回的是索引 invTImes[invTImes.argsort()]
- 對H矩陣做相同的排序操作
有了以上的鋪墊,我們做相同的排序就會很簡單了#用invTImes的排序方法對H矩陣的行排序 H[invTimes.argsort(),:]
以上過程封裝后
def hada2wal(H):
diffMat = np.abs(np.diff(H))/2
invTimes = np.sum(diffMat,axis = 1)
W = H[invTimes.argsort(),:]
return W
效果對比


驗證正確性
從結果的圖來看,實現基本上是正確了,但如何確定實現正確了呢,這里用一下DWT的性質
DWT是正交變換,其變換矩陣是實正交對稱陣,也就是說,其每一行做內積的結果是0,只有與自己內積時才有非零值
因此用W矩陣與其自身做矩陣乘法
得到對角陣,驗證了結果是正交的,我們可以確定得到的沃爾什變換核是正確的