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

Posted

技术标签:

【中文标题】CDF 9/7 离散小波变换(卷积)【英文标题】:CDF 9/7 Discrete Wavelet Transform (Convolution) 【发布时间】:2011-06-30 07:35:26 【问题描述】:

我正在尝试编写一个简单的自包含程序,该程序使用 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 示例代码中使用。

【问题讨论】:

提示:使用numpy 这样你就可以在没有循环的情况下执行DWTSynthesisHighpass *= math.sqrt(2.0) 之类的操作。更一般地说,当您可以执行 for x in stuff 时,您几乎不需要执行 for i in range(len(stuff)) 是的,我知道,但我没有在我当前的机器上安装 numpy,我只想做一个快速粗略的测试。在这种情况下,我真的不能做for x in stuff;我可以在实际转换中使用切片,但我认为这会使它更加模糊。 重新考虑使用 map 和 lambda 函数可能会更干净(鉴于我没有 numpy),但过滤器的生成并不是我认为的损坏。跨度> 【参考方案1】:

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

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

【讨论】:

我用不同的过滤器(例如 Haar)运行了这段代码,但它对它们不起作用。它是否适用于任何类型的过滤器?

以上是关于CDF 9/7 离散小波变换(卷积)的主要内容,如果未能解决你的问题,请参考以下文章

FPGA小波变换基于FPGA的图像9/7整数小波变换verilog实现

小波变换教程(十七)

图像的小波变换

用于图像纹理分析的离散小波变换

2DWT:2维离散小波变换(附Pytorch代码)

离散小波变换——一维