详解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实现获取操作系统版本信息方法
Apr 08 Python
深入浅析python with语句简介
Apr 11 Python
浅析Python数据处理
May 02 Python
Python使用ConfigParser模块操作配置文件的方法
Jun 29 Python
pycharm 将python文件打包为exe格式的方法
Jan 16 Python
opencv实现静态手势识别 opencv实现剪刀石头布游戏
Jan 22 Python
Python 2/3下处理cjk编码的zip文件的方法
Apr 26 Python
python 实现查找文件并输出满足某一条件的数据项方法
Jun 12 Python
python实现按行分割文件
Jul 22 Python
深入浅析Python科学计算库Scipy及安装步骤
Oct 12 Python
利用python对excel中一列的时间数据更改格式操作
Jul 14 Python
Python实现Hash算法
Mar 18 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
基于PHPExcel的常用方法总结
2013/06/13 PHP
PHP中Session可能会引起并发问题
2015/06/26 PHP
PHP中模拟链表和链表的基本操作示例
2016/02/27 PHP
PHP高效获取远程图片尺寸和大小的实现方法
2017/10/20 PHP
js实现运行代码需要刷新的解决方法
2007/08/18 Javascript
jQuery UI 应用不同Theme的办法
2010/09/12 Javascript
JS 修改URL参数(实现代码)
2013/07/08 Javascript
JQuery $.each遍历JavaScript数组对象实例
2014/09/01 Javascript
JavaScript中的继承方式详解
2015/02/11 Javascript
在JavaScript应用中使用RequireJS来实现延迟加载
2015/07/01 Javascript
基于JS实现的倒计时程序实例
2015/07/24 Javascript
详解AngularJS中的filter过滤器用法
2016/01/04 Javascript
JS创建对象几种不同方法详解
2016/03/01 Javascript
AngularJS学习笔记之依赖注入详解
2016/05/16 Javascript
浅析$(function) ready和onload 的区别
2016/09/03 Javascript
js原生跨域_用script标签的简单实现
2016/09/24 Javascript
Nodejs中Express 常用中间件 body-parser 实现解析
2017/05/22 NodeJs
jQuery之动画ajax事件(实例讲解)
2017/07/18 jQuery
深入剖析Express cookie-parser中间件实现示例
2018/02/01 Javascript
解决Vue打包上线之后部分CSS不生效的问题
2019/11/12 Javascript
[36:33]2018DOTA2亚洲邀请赛 4.3 突围赛 EG vs Newbee 第二场
2018/04/04 DOTA
[50:27]OG vs LGD 2018国际邀请赛淘汰赛BO3 第一场 8.26
2018/08/30 DOTA
python通过ElementTree操作XML获取结点读取属性美化XML
2013/12/02 Python
python中lambda函数 list comprehension 和 zip函数使用指南
2014/09/28 Python
Android模拟器无法启动,报错:Cannot set up guest memory ‘android_arm’ Invalid argument的解决方法
2016/07/01 Python
python2.7 mayavi 安装图文教程(推荐)
2017/06/22 Python
Python实现矩阵转置的方法分析
2017/11/24 Python
python3+PyQt5图形项的自定义和交互 python3实现page Designer应用程序
2020/07/20 Python
详解Python中的分组函数groupby和itertools)
2018/07/11 Python
美国Jeep配件购物网站:Morris 4×4 Center
2019/05/01 全球购物
夜班门卫岗位职责
2013/12/09 职场文书
英语演讲稿范文
2014/01/03 职场文书
军训教官感言
2014/03/02 职场文书
寄语学生的话
2014/04/10 职场文书
关于springboot 配置date字段返回时间戳的问题
2021/07/25 Java/Android
tomcat默认最大连接数及相关调整方法
2022/05/06 Servers