C码小波变换及其解释

C码小波变换及其解释,c,numerical-methods,wavelet,C,Numerical Methods,Wavelet,我正在尝试用C语言实现小波变换,我以前从未做过。我读过一些关于小波的书,理解了“增长子空间”的概念,以及Mallat的单边滤波器组本质上是同一个概念 然而,我被困在如何实际实现Mallat的快速小波变换上。到目前为止,我的理解是: 高通滤波器h(t)为您提供细节系数。对于给定的尺度j,它是母小波W(t)的反射、放大和赋范版本 然后,g(t)是弥补差异的低通滤波器。它应该是h(t)的正交镜 要获得细节系数或第j级的近似系数,您需要分别用h(t)或g(t)卷积信号块,并按2^{j}(即每2^{j}取

我正在尝试用C语言实现小波变换,我以前从未做过。我读过一些关于小波的书,理解了“增长子空间”的概念,以及Mallat的单边滤波器组本质上是同一个概念

然而,我被困在如何实际实现Mallat的快速小波变换上。到目前为止,我的理解是:

  • 高通滤波器h(t)为您提供细节系数。对于给定的尺度j,它是母小波W(t)的反射、放大和赋范版本

  • 然后,g(t)是弥补差异的低通滤波器。它应该是h(t)的正交镜

  • 要获得细节系数或第j级的近似系数,您需要分别用h(t)或g(t)卷积信号块,并按2^{j}(即每2^{j}取一个值)对信号进行下采样

  • 但我的问题是:

  • 当我知道h(t)时,如何才能找到g(t)

  • 如何计算这个变换的逆

  • 你有我可以参考的C代码吗?(是的,我在维基上找到了,但没有帮助)

    我想让一些代码说的是:

    这是过滤器

    B.这是转换(非常明确) 这里是逆变换(同样适用于假人)


    感谢您的耐心,但是这里似乎没有一个带有明确示例的Step1-Step2-Step3-etc指南(这些示例不是HAAR,因为所有系数都是1s,这会让事情变得混乱)。

    马拉特的fwt配方非常简单。如果你看一下matlab代码,比如Jeffrey Kantor的代码,所有的步骤都是显而易见的

    在C语言中,这需要更多的工作,但这主要是因为您需要处理自己的声明和分配

    首先,关于你的总结:

  • 通常滤波器h是一个低通滤波器,代表缩放函数(父)
  • 同样,g通常是代表小波的高通滤波器(母)
  • 不能在1过滤+下采样步骤中执行J级分解。在每个级别上,通过h滤波和下采样创建近似信号c,通过g滤波和下采样创建细节信号d,并在下一个级别上重复此操作(使用当前c)
  • 关于您的问题:

  • 对于正交小波基的滤波器h,[h_1 h_2..h_m h_n],QMF为[h_n-h_m..h_2-h_1],其中n为偶数,m==n-1
  • 逆变换的作用与fwt相反:在每一级,它对细节d和近似值c进行上采样,将d与g和c与h进行卷积,并将信号相加——参见相应的matlab
  • 使用此信息,并给定
    len
    类型
    double
    点的信号
    x
    ,缩放
    h
    f
    系数的小波
    g
    滤波器(也是
    double
    类型),以及分解级别
    lev
    ,这段代码实现了Mallat fwt:

    double *t=calloc(len+f-1, sizeof(double));
    memcpy(t, x, len*sizeof(double));        
    for (int i=0; i<lev; i++) {            
        memset(y, 0, len*sizeof(double));
        int len2=len/2;
        for (int j=0; j<len2; j++)           
            for (int k=0; k<f; k++) {          
                y[j]     +=t[2*j+k]*h[k];      
                y[j+len2]+=t[2*j+k]*g[k];      
            }
        len=len2;                            
        memcpy(t, y, len*sizeof(double));    
    }
    free(t);
    
    double*t=calloc(len+f-1,sizeof(double));
    memcpy(t,x,len*sizeof(double));
    
    对于(inti=0;i而言,唯一缺少的是一些用于过滤操作的填充。 台词

    y[j]     +=t[2*j+k]*h[k];      
            y[j+len2]+=t[2*j+k]*g[k];
    
    在第一次迭代中超出t数组的边界,并在接下来的迭代中超出数组的近似部分。必须在t数组的开头添加(f-1)个元素

    double *t=calloc(len+f-1, sizeof(double));
    memcpy(&t[f], x, len*sizeof(double));        
    for (int i=0; i<lev; i++) {
    memset(t, 0, (f-1)*sizeof(double));        
    memset(y, 0, len*sizeof(double));
    int len2=len/2;
    for (int j=0; j<len2; j++)           
        for (int k=0; k<f; k++) {          
            y[j]     +=t[2*j+k]*h[k];      
            y[j+len2]+=t[2*j+k]*g[k];      
        }
    len=len2;                            
    memcpy(&t[f], y, len*sizeof(double));    
    }
    
    double*t=calloc(len+f-1,sizeof(double));
    memcpy(&t[f],x,len*sizeof(double));
    
    对于(int i=0;i)。这些是指向库的链接,但可能会对您有所帮助。此外,您的问题似乎更适合于数学论坛,而不是这里。很好的呼叫-编辑了我的解决方案!谢谢。另一个解决方案是定期进行(到达末尾后在信号开始处继续)。