Skip to main content
 首页 » 编程设计

python之CDF 9/7 离散小波变换(卷积)

2025年05月04日10虾米哥

我正在尝试编写一个简单的独立程序,该程序使用 CDF 9/7 小波对一维列表执行单级离散小波变换,然后对其进行重构。我只是使用卷积/滤波器组方法来了解它的工作原理。换句话说,将列表与滤波器进行卷积以获得比例系数,将列表与不同的滤波器进行卷积以获得小波系数,但只能从所有其他元素开始执行此操作。然后上采样(即在元素之间添加零),对小波和比例系数应用滤波器,将它们加在一起,得到原始列表。

我可以让它为 Haar 小波滤波器工作,但是当我尝试使用 CDF 9/7 滤波器时,它不会产生相同的输入。然而,结果列表和原始列表的总和是一样的。

我确定这是卷积中的一个非常愚蠢的错误,但我就是想不通。我已经尝试了一堆卷积排列,比如将过滤器集中在索引“i”上,而不是从它的左边缘开始,但似乎没有任何效果......这可能是那些会造成的错误之一当我弄清楚时,我拍了拍我的头。

代码如下:

import random 
import math 
length = 128 
array = list() 
row = list() 
scaleCoefficients = list() 
waveletCoefficients = list() 
reconstruction = list() 
 
def upsample(lst, index): 
    if (index % 2 == 0): 
        return 0.0 
    else: 
        return lst[index/2] 
 
for i in range(length): 
    array.append(random.random()) 
 
## CDF 9/7 Wavelet (doesn't work?) 
DWTAnalysisLowpass = [.026749, -.016864, -.078223, .266864, .602949, .266864, -.078223, -.016864, .026749] 
for i in range(len(DWTAnalysisLowpass)): 
    DWTAnalysisLowpass[i] = math.sqrt(2.0) * DWTAnalysisLowpass[i] 
DWTAnalysisHighpass = [0.0, .091272, -.057544, -0.591272, 1.115087, -.591272, -.057544, .091272, 0.0] 
for i in range(len(DWTAnalysisHighpass)): 
    DWTAnalysisHighpass[i] = 1.0/math.sqrt(2.0) * DWTAnalysisHighpass[i] 
 
DWTSynthesisLowpass = [0.0, -.091272, -.057544, 0.591272, 1.115087, .591272, -.057544, -.091272, 0.0] 
for i in range(len(DWTSynthesisLowpass)): 
    DWTSynthesisLowpass[i] = 1.0/math.sqrt(2.0) * DWTSynthesisLowpass[i] 
DWTSynthesisHighpass = [.026749, .016864, -.078223, -.266864, .602949, -.266864, -.078223, .016864, .026749] 
for i in range(len(DWTSynthesisHighpass)): 
    DWTSynthesisHighpass[i] = math.sqrt(2.0) * DWTSynthesisHighpass[i] 
 
## Haar Wavelet (Works) 
## c = 1.0/math.sqrt(2) 
## DWTAnalysisLowpass = [c,c] 
## DWTAnalysisHighpass = [c, -c] 
## DWTSynthesisLowpass = [c, c] 
## DWTSynthesisHighpass = [-c, c] 
 
 
## Do the forward transform - we only need to do it on half the elements 
for i in range(0,length,2): 
    newVal = 0.0 
    ## Convolve the next j elements 
    for j in range(len(DWTAnalysisLowpass)): 
        index = i + j 
        if(index >= length): 
            index = index - length 
 
        newVal = newVal + array[index]*DWTAnalysisLowpass[j] 
 
    scaleCoefficients.append(newVal) 
 
    newVal = 0.0 
    for j in range(len(DWTAnalysisHighpass)): 
        index = i + j 
        if(index >= length): 
            index = index - length 
 
        newVal = newVal + array[index]*DWTAnalysisHighpass[j] 
 
    waveletCoefficients.append(newVal) 
 
## Do the inverse transform 
for i in range(length): 
    newVal = 0.0 
    for j in range(len(DWTSynthesisHighpass)): 
        index = i + j 
        if(index >= length): 
            index = index - length 
 
        newVal = newVal + upsample(waveletCoefficients, index)*DWTSynthesisHighpass[j] 
 
    for j in range(len(DWTSynthesisLowpass)): 
        index = i + j 
        if(index >= length): 
            index = index - length 
 
        newVal = newVal + upsample(scaleCoefficients, index)*DWTSynthesisLowpass[j] 
 
    reconstruction.append(newVal) 
 
print sum(reconstruction) 
print sum(array) 
print reconstruction 
print array 

顺便说一句,我从这里的附录中获取了过滤器值:http://www1.cs.columbia.edu/~rso2102/AWR/Files/Overbeck2009AWR.pdf ,但我也看到它们也用在一堆 matlab 示例代码中。

请您参考如下方法:

实际上,我自己通过比较系数,然后使用此提升实现中的代码进行重构来解决了这个问题:

http://www.embl.de/~gpau/misc/dwt97.c

基本上,我 1) 使边界条件对称,而不是周期性的 2) 必须以某些方式抵消卷积(和上采样)才能使其全部对齐。

这是代码,以防其他人遇到问题。我觉得这仍然过于复杂,特别是因为它没有真正记录在任何地方,但至少它有效。这还包括我用来针对该引用进行测试的“开关”,我必须修改 Haar 小波才能使其工作。

import random 
import math 
length = int() 
array = list() 
row = list() 
scaleCoefficients = list() 
waveletCoefficients = list() 
reconstruction = list() 
switch = False 
 
def upsample1(lst, index): 
    if (index % 2 == 0): 
        return lst[index/2] 
    else: 
        return 0.0 
 
def upsample2(lst, index): 
    if (index % 2 == 0): 
        return 0.0 
    else: 
        return lst[index/2] 
 
## Generate a random list of floating point numbers 
if (not switch): 
    length = 128 
    for i in range(length): 
        array.append(random.random()) 
else: 
    length = 32 
    for i in range(32): 
        array.append(5.0+i+.4*i*i-.02*i*i*i) 
 
## First Part Just Calculates the Filters 
## CDF 9/7 Wavelet 
DWTAnalysisLowpass = [.026749, -.016864, -.078223, .266864, .602949, .266864, -.078223, -.016864, .026749] 
for i in range(len(DWTAnalysisLowpass)): 
    DWTAnalysisLowpass[i] = math.sqrt(2.0) * DWTAnalysisLowpass[i] 
DWTAnalysisHighpass = [.091272, -.057544, -0.591272, 1.115087, -.591272, -.057544, .091272] 
for i in range(len(DWTAnalysisHighpass)): 
    DWTAnalysisHighpass[i] = DWTAnalysisHighpass[i]/math.sqrt(2.0) 
 
DWTSynthesisLowpass = [-.091272, -.057544, 0.591272, 1.115087, .591272, -.057544, -.091272] 
for i in range(len(DWTSynthesisLowpass)): 
    DWTSynthesisLowpass[i] = DWTSynthesisLowpass[i]/math.sqrt(2.0) 
DWTSynthesisHighpass = [.026749, .016864, -.078223, -.266864, .602949, -.266864, -.078223, .016864, .026749] 
for i in range(len(DWTSynthesisHighpass)): 
    DWTSynthesisHighpass[i] = math.sqrt(2.0) * DWTSynthesisHighpass[i] 
 
## Haar Wavelet 
## c = 1.0/math.sqrt(2) 
## DWTAnalysisLowpass = [c,c] 
## DWTAnalysisHighpass = [c, -c] 
## DWTSynthesisLowpass = [-c, c] 
## DWTSynthesisHighpass = [c, c] 
 
# Do the forward transform. We can skip every other sample since they would 
# be removed in the downsampling anyway 
for i in range(0,length,2): 
    newVal = 0.0 
    ## Convolve the next j elements by the low-pass analysis filter 
    for j in range(len(DWTAnalysisLowpass)): 
        index = i + j - len(DWTAnalysisLowpass)/2 
        if(index >= length): 
            index = 2*length - index - 2 
        elif (index < 0): 
            index = -index 
 
        newVal = newVal + array[index]*DWTAnalysisLowpass[j] 
 
    # append the new value to the list of scale coefficients 
    scaleCoefficients.append(newVal) 
 
    newVal = 0.0 
    # Convolve the next j elements by the high-pass analysis filter 
    for j in range(len(DWTAnalysisHighpass)): 
        index = i + j - len(DWTAnalysisHighpass)/2 + 1 
        if(index >= length): 
            index = 2*length - index - 2 
        elif (index < 0): 
            index = -index 
 
        newVal = newVal + array[index]*DWTAnalysisHighpass[j] 
 
    # append the new value to the list of wavelet coefficients 
    waveletCoefficients.append(newVal) 
 
# Do the inverse transform 
for i in range(length): 
    newVal = 0.0 
    # convolve the upsampled wavelet coefficients with the high-pass synthesis filter 
    for j in range(len(DWTSynthesisHighpass)): 
        index = i + j - len(DWTSynthesisHighpass)/2 
        if(index >= length): 
            index = 2*length - index - 2 
        elif (index < 0): 
            index = -index 
 
        newVal = newVal + upsample2(waveletCoefficients, index)*DWTSynthesisHighpass[j] 
 
    # convolve the upsampled scale coefficients with the low-pass synthesis filter, and 
    # add it to the previous convolution 
    for j in range(len(DWTSynthesisLowpass)): 
        index = i + j - len(DWTSynthesisLowpass)/2 
        if(index >= length): 
            index = 2*length - index - 2 
        elif (index < 0): 
            index = -index 
 
        newVal = newVal + upsample1(scaleCoefficients, index)*DWTSynthesisLowpass[j] 
 
    reconstruction.append(newVal) 
 
print ("Sums: ") 
print sum(reconstruction) 
print sum(array) 
print ("Original Signal: ") 
print array 
if (not switch): 
    print ("Wavelet Coefficients: ") 
    for i in range(len(scaleCoefficients)): 
        print ("sc[" + str(i) + "]: " + str(scaleCoefficients[i])) 
    for i in range(len(waveletCoefficients)): 
        print ("wc[" + str(i) + "]: " + str(waveletCoefficients[i])) 
print ("Reconstruction: ") 
print reconstruction