在Python中不使用包实现Haar小波

问题描述 投票:0回答:2

我正在尝试编写代码来实现离散小波变换(haar 小波 dwt),而不使用 python 中的包。

到目前为止,我找到了一个链接,他们实现了类似的东西,链接这个小波变换实现正确吗?。运行时没有报错,但最终结果不正确。我运行的代码是:

def discreteHaarWaveletTransform(x):
    N = len(x)
    output = [0.0]*N

    length = N >> 1
    while True:
        for i in range(0,length):
            summ = x[i * 2] + x[i * 2 + 1]
            difference = x[i * 2] - x[i * 2 + 1]
            output[i] = summ
            output[length + i] = difference

        if length == 1:
            return output

        #Swap arrays to do next iteration
        x = output[:length << 1]
        length >>= 1

输入:

list=[56, 40, 8, 24, 48, 48, 40, 16]

电流输出:

[280, -24, 64, 40, 16, -16, 0, 24]

预期输出:

[35, -3, 16, 10, 8, -8, 0, 12]

有什么明显的东西我看不到吗?

python fft wavelet haar-wavelet
2个回答
4
投票

类似这样的东西应该可以解决问题——它几乎是这个 C 答案的直译。这可能意味着这不是非常 Python-y 的代码,但如果你没有使用 numpy

 来实现它,那无论如何也不是非常 Python-y。

您没有获得预期输出的主要原因是您忘记在过滤后缩放输出。这使得每个下一级的系数大约高两倍。

请注意,1/2 的缩放可以提供预期的输出,但更常用的是 1/2√2 的缩放,以保留小波变换下信号的 L2 范数。

def haarFWT ( signal, level ): s = .5; # scaling -- try 1 or ( .5 ** .5 ) h = [ 1, 1 ]; # lowpass filter g = [ 1, -1 ]; # highpass filter f = len ( h ); # length of the filter t = signal; # 'workspace' array l = len ( t ); # length of the current signal y = [0] * l; # initialise output t = t + [ 0, 0 ]; # padding for the workspace for i in range ( level ): y [ 0:l ] = [0] * l; # initialise the next level l2 = l // 2; # half approximation, half detail for j in range ( l2 ): for k in range ( f ): y [j] += t [ 2*j + k ] * h [ k ] * s; y [j+l2] += t [ 2*j + k ] * g [ k ] * s; l = l2; # continue with the approximation t [ 0:l ] = y [ 0:l ] ; return y def main(): s0 = [ 56, 40, 8, 24, 48, 48, 40, 16 ]; print( "level 0" ); print( s0 ); print( "level 1" ); print( haarFWT (s0, 1 ) ); print( "level 2" ); print( haarFWT (s0, 2 ) ); print( "level 3" ); print( haarFWT (s0, 3 ) ); if __name__ == "__main__": main() # run with: >>> execfile ( "haarwavelet.py" )
    

0
投票
可以通过这种方式实现基于 numpy 的方法,使用 Haar 小波执行多级 1D DWT 信号分解。结果与

pywt.wavedec(signal, "haar", mode="zero")

的pywavelet实现一致。

def haar_wavedec(signal, level=None, scale=np.sqrt(0.5)): """ A numpy-based implementation of a multi-level 1D wavelet decomposition using the Haar wavelet. The input signal must be at least 2 samples long, and is always zero-padded to a length of (2^(level+1)) samples. Parameters ---------- signal : np.ndarray A numpy array containing the input signal. level : int or None, optional A number of levels of the decomposition or None for automatic estimation. The default is None. scale : float, optional A scaling factor for the decomposition. The default value preserves L2 norm of the transformed signal. The default is np.sqrt(0.5). Returns ------- res : List[np.ndarray] A list of numpy arrays containing the result in pywavelets format: [cA(n), cD(n), cD(n-1), ..., cD(1)], i.e., the approximate coefficients from the n-th level and all the detail coefficients ordered from the n-th level to the 1st. """ if len(signal) < 2: return None # get the level n (by maximizing n while 2^n <= signal length) if not specified n = int(np.log2(len(signal))) if level is None else level h = np.array([1.0, 1.0]) # low-pass filter (sum) g = np.array([1.0, -1.0]) # high-pass filter (difference) # zero-pad the signal to 2^(n+1) length t = np.pad(signal, (0,2**(n+1)-len(signal)), constant_values=0) res = list() for i in range(n, 0, -1): l = len(t) // 2 # array c for intermediate results of the convolution c = np.zeros(l * 2) for j in range(l): for k in range(len(h)): c[j] += t[2*j + k] * h[k] * scale # calculate the low-pass convolution c[j+l] += t[2*j + k] * g[k] * scale # calculate the high-pass convolution # the next iteration will process the low-pass coefficients t = c[:l] # store the high-pass (detail) coefficients (stripped zeros from right) res.append(c[l:l+np.argwhere(c[l:]).max()+1]) # store the final low-pass (approximate) coefficients res.append(c[:l][:np.argwhere(c[:l]).max()+1]) return res[::-1]
    
© www.soinside.com 2019 - 2024. All rights reserved.