2

我正在尝试在 C 中实现小波变换,但我以前从未做过。我已经阅读了一些关于小波的内容,并了解“生长子空间”的想法,以及 Mallat 的单边滤波器组如何本质上是相同的想法。

但是,我被困在如何实际实现 Mallat 的快速小波变换上。这是我目前所理解的:

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

  2. g(t) 是弥补差异的低通滤波器。它应该是 h(t) 的正交镜

  3. 要获得详细系数或第 j 级的近似系数,您需要分别将信号块与 h(t) 或 g(t) 进行卷积,并将信号下采样 2^{j}(即每 2^ {j} 值)

然而,这些是我的问题:

  1. 当我知道 h(t) 时如何找到 g(t)?

  2. 我怎样才能计算这个变换的逆?

你有我可以参考的 C 代码吗?(是的,我在 wiki 上找到了那个,但它没有帮助)

我想要一些代码说的是:

A. 这是过滤器

B. 这是变换(非常明确) C.)这是逆变换(再次用于假人)

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

4

2 回答 2

4

fwt 的 Mallat 配方非常简单。如果您查看 matlab 代码,例如 Jeffrey Kantor 的脚本,所有步骤都是显而易见的。

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

首先,关于你的总结:

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

关于您的问题:

  1. 对于正交小波基的滤波器h [h_1 h_2 .. h_m h_n],QMF 为 [h_n -h_m .. h_2 -h_1],其中n是偶数,m == n -1
  2. 逆变换与 fwt 相反:在每个级别上,它对细节d和近似值c进行上采样,将dgch卷积,并将信号加在一起 ​​- 请参见相应的 matlab脚本

使用此信息,并给定类型点的信号x、系数(也是类型)的缩放和小波滤波器以及分解级别,这段代码实现了 Mallat fwt:lendoublehgfdoublelev

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);

它使用一个额外的数组:一个“工作空间”t来复制下一次迭代的近似值c(开始的输入信号x)。

请参阅此示例 C程序,您可以使用它进行编译gcc -std=c99 -fpermissive main.cpp和运行./a.out

逆也应该是这样的。祝你好运!

于 2014-09-23T13:00:02.517 回答
1

唯一缺少的是过滤操作的一些填充。线条

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));    
}
于 2015-06-19T19:19:27.453 回答