详解python实现小波变换的一个简单例子


Posted in Python onJuly 18, 2019

最近工作需要,看了一下小波变换方面的东西,用python实现了一个简单的小波变换类,将来可以用在工作中。

简单说几句原理,小波变换类似于傅里叶变换,都是把函数用一组正交基函数展开,选取不同的基函数给出不同的变换。例如傅里叶变换,选择的是sin和cos,或者exp(ikx)这种复指数函数;而小波变换,选取基函数的方式更加灵活,可以根据要处理的数据的特点(比如某一段上信息量比较多),在不同尺度上采用不同的频宽来对已知信号进行分解,从而尽可能保留多一点信息,同时又避免了原始傅里叶变换的大计算量。以下计算采用的是haar基,它把函数分为2段(A1和B1,但第一次不分),对第一段内相邻的2个采样点进行变换(只考虑A1),变换矩阵为

sqrt(0.5)       sqrt(0.5)

sqrt(0.5)        -sqrt(0.5)

变换完之后,再把第一段(A1)分为两段,同样对相邻的点进行变换,直到无法再分。

下面直接上代码

Wavelet.py

import math
 
class wave:
  def __init__(self):
    M_SQRT1_2 = math.sqrt(0.5)
    self.h1 = [M_SQRT1_2, M_SQRT1_2]
    self.g1 = [M_SQRT1_2, -M_SQRT1_2]
    self.h2 = [M_SQRT1_2, M_SQRT1_2]
    self.g2 = [M_SQRT1_2, -M_SQRT1_2]
    self.nc = 2
    self.offset = 0
 
  def __del__(self):
    return
 
class Wavelet:
  def __init__(self, n):
    self._haar_centered_Init()
    self._scratch = []
    for i in range(0,n):
      self._scratch.append(0.0)
    return
    
  def __del__(self):
    return
    
  def transform_inverse(self, list, stride):
    self._wavelet_transform(list, stride, -1)
    return
    
  def transform_forward(self, list, stride):
    self._wavelet_transform(list, stride, 1)
    return
    
  def _haarInit(self):
    self._wave = wave()
    self._wave.offset = 0
    return
    
  def _haar_centered_Init(self):
    self._wave = wave()
    self._wave.offset = 1
    return
    
  def _wavelet_transform(self, list, stride, dir):
    n = len(list)
    if (len(self._scratch) < n):
      print("not enough workspace provided")
      exit()
    if (not self._ispower2(n)):
      print("the list size is not a power of 2")
      exit()
    
    if (n < 2):
      return
 
    if (dir == 1): # 正变换
      i = n
      while(i >= 2):
        self._step(list, stride, i, dir)
        i = i>>1
       
    if (dir == -1):  # 逆变换
      i = 2
      while(i <= n):
        self._step(list, stride, i, dir)
        i = i << 1
    return
    
  def _ispower2(self, n):
    power = math.log(n,2)
    intpow = int(power)
    intn = math.pow(2,intpow)
    if (abs(n - intn) > 1e-6):
      return False
    else:
      return True
      
  def _step(self, list, stride, n, dir):
    for i in range(0, len(self._scratch)):
      self._scratch[i] = 0.0
    
    nmod = self._wave.nc * n
    nmod -= self._wave.offset
    n1 = n - 1
    nh = n >> 1
    
    if (dir == 1): # 正变换
      ii = 0
      i = 0
      while (i < n):
        h = 0
        g = 0
        ni = i + nmod
        for k in range(0, self._wave.nc):
          jf = n1 & (ni + k)
          h += self._wave.h1[k] * list[stride*jf]
          g += self._wave.g1[k] * list[stride*jf]
        self._scratch[ii] += h
        self._scratch[ii + nh] += g
        i += 2
        ii += 1
    
    if (dir == -1):  # 逆变换
      ii = 0
      i = 0
      while (i < n):
        ai = list[stride*ii]
        ai1 = list[stride*(ii+nh)]
        ni = i + nmod
        for k in range(0, self._wave.nc):
          jf = n1 & (ni + k)
          self._scratch[jf] += self._wave.h2[k] * ai + self._wave.g2[k] * ai1
        i += 2
        ii += 1
        
    for i in range(0, n):
      list[stride*i] = self._scratch[i]

测试代码如下:

test.py

import math
import Wavelet
 
waveletn = 256
waveletnc = 20  #保留的分量数
wavelettest = Wavelet.Wavelet(waveletn)
waveletorigindata = []
waveletdata = []
for i in range(0, waveletn):
  waveletorigindata.append(math.sin(i)*math.exp(-math.pow((i-100)/50,2))+1)
  waveletdata.append(waveletorigindata[-1])
  
Wavelet.wavelettest.transform_forward(waveletdata, 1)
newdata = sorted(waveletdata, key = lambda ele: abs(ele), reverse=True)
for i in range(waveletnc, waveletn):  # 筛选出前 waveletnc个分量保留
  for j in range(0, waveletn):
    if (abs(newdata[i] - waveletdata[j]) < 1e-6):
      waveletdata[j] = 0.0
      break
  
Wavelet.wavelettest.transform_inverse(waveletdata, 1)
waveleterr = 0.0
for i in range(0, waveletn):
  print(waveletorigindata[i], ",", waveletdata[i])
  waveleterr += abs(waveletorigindata[i] - waveletdata[i])/abs(waveletorigindata[i])
print("error: ", waveleterr/waveletn)

当waveletnc = 20时,可得到下图,误差大约为2.1

详解python实现小波变换的一个简单例子

当waveletnc = 100时,则为下图,误差大约为0.04

详解python实现小波变换的一个简单例子

当waveletnc = 200时,得到下图,误差大约为0.0005

详解python实现小波变换的一个简单例子

 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现获取序列中最小的几个元素
Sep 25 Python
在centos7中分布式部署pyspider
May 03 Python
Python入门_浅谈数据结构的4种基本类型
May 16 Python
python中闭包Closure函数作为返回值的方法示例
Dec 17 Python
python使用selenium登录QQ邮箱(附带滑动解锁)
Jan 23 Python
python批量修改文件夹及其子文件夹下的文件内容
Mar 15 Python
python中dict使用方法详解
Jul 17 Python
Python安装tar.gz格式文件方法详解
Jan 19 Python
利用Tensorflow构建和训练自己的CNN来做简单的验证码识别方式
Jan 20 Python
Python 动态变量名定义与调用方法
Feb 09 Python
Python创建空列表的字典2种方法详解
Feb 13 Python
python实现启动一个外部程序,并且不阻塞当前进程
Dec 05 Python
Django基础知识 URL路由系统详解
Jul 18 #Python
对Django项目中的ORM映射与模糊查询的使用详解
Jul 18 #Python
Django基础知识 web框架的本质详解
Jul 18 #Python
django 使用全局搜索功能的实例详解
Jul 18 #Python
Django中Middleware中的函数详解
Jul 18 #Python
对DJango视图(views)和模版(templates)的使用详解
Jul 17 #Python
react+django清除浏览器缓存的几种方法小结
Jul 17 #Python
You might like
php数组函数序列之each() - 获取数组当前内部指针所指向元素的键名和键值,并将指针移到下一位
2011/10/31 PHP
PHP将二维数组某一个字段相同的数组合并起来的方法
2016/02/26 PHP
Yii2如何批量添加数据
2016/05/17 PHP
php 输出缓冲 Output Control用法实例详解
2020/03/03 PHP
JavaScript弹簧振子超简洁版 完全符合能量守恒,胡克定理
2009/10/25 Javascript
JQuery Dialog(JS 模态窗口,可拖拽的DIV)
2010/02/07 Javascript
javascript检测浏览器flash版本的实现代码
2011/12/06 Javascript
jquery基础教程之数组使用详解
2014/03/10 Javascript
对于jQuery性能的一些优化建议
2015/08/13 Javascript
JavaScript代码里的判断小结
2016/08/22 Javascript
BootStrap fileinput.js文件上传组件实例代码
2017/02/20 Javascript
Centos6.8下Node.js安装教程
2017/05/12 Javascript
vue.js路由跳转详解
2017/08/28 Javascript
javascript实现电脑和手机版样式切换
2017/11/10 Javascript
js实现以最简单的方式将数组元素添加到对象中的方法
2017/12/20 Javascript
快速搭建vue2.0+boostrap项目的方法
2018/04/09 Javascript
nodejs环境使用Typeorm连接查询Oracle数据
2019/12/05 NodeJs
[02:03]完美世界DOTA2联赛10月30日赛事集锦
2020/10/31 DOTA
剖析Python的Twisted框架的核心特性
2016/05/25 Python
matlab中实现矩阵删除一行或一列的方法
2018/04/04 Python
Python面向对象程序设计之继承与多继承用法分析
2018/07/13 Python
python实现从本地摄像头和网络摄像头截取图片功能
2019/07/11 Python
Python获取时间戳代码实例
2019/09/24 Python
Python实现把类当做字典来访问
2019/12/16 Python
Django Serializer HiddenField隐藏字段实例
2020/03/31 Python
详解Python中import机制
2020/09/11 Python
如何在python中处理配置文件代码实例
2020/09/27 Python
VSCode中autopep8无法运行问题解决方案(提示Error: Command failed,usage)
2021/03/02 Python
马德里运动鞋商店:Nigra Mercato
2020/02/16 全球购物
Python中pass语句的作用是什么
2016/06/01 面试题
博士研究生自我鉴定范文
2013/12/04 职场文书
自荐书模板
2013/12/15 职场文书
2015年清明节网上祭英烈活动总结
2015/03/26 职场文书
2015年挂职锻炼个人总结
2015/10/22 职场文书
Python GUI编程之tkinter 关于 ttkbootstrap 的使用详解
2022/03/03 Python
字节飞书面试promise.all实现示例
2022/06/16 Javascript