详解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日期操作学习笔记
Oct 07 Python
python解析xml文件操作实例
Oct 05 Python
python中threading超线程用法实例分析
May 16 Python
在Django框架中设置语言偏好的教程
Jul 27 Python
星球大战与Python之间的那些事
Jan 07 Python
Python3编码问题 Unicode utf-8 bytes互转方法
Oct 26 Python
将Python字符串生成PDF的实例代码详解
May 17 Python
Python unittest 自动识别并执行测试用例方式
Mar 09 Python
Django中Aggregation聚合的基本使用方法
Jul 09 Python
python中使用.py配置文件的方法详解
Nov 23 Python
解决virtualenv -p python3 venv报错的问题
Feb 05 Python
详细总结Python常见的安全问题
May 21 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下过滤html代码的函数 提高程序安全性
2010/03/02 PHP
ThinkPHP视图查询详解
2014/06/30 PHP
php遍历树的常用方法汇总
2015/06/18 PHP
Yii2框架实现数据库常用操作总结
2017/02/08 PHP
Laravel (Lumen) 解决JWT-Auth刷新token的问题
2019/10/24 PHP
for 循环性能比较 提高for循环的效率
2009/03/19 Javascript
基于jQuery的动态增删改查表格信息,可左键/右键提示(原创自Zjmainstay)
2012/07/31 Javascript
JavaScript检测鼠标移动方向的方法
2015/05/22 Javascript
JavaScript获取当前cpu使用率的方法
2015/12/15 Javascript
JS实现漂亮的时间选择框效果
2016/08/20 Javascript
详解EasyUi控件中的Datagrid
2017/08/23 Javascript
angularjs 缓存的使用详解
2018/03/19 Javascript
详解React之父子组件传递和其它一些要点
2018/06/25 Javascript
浅谈React之状态(State)
2018/09/19 Javascript
微信小程序仿知乎实现评论留言功能
2018/11/28 Javascript
如何换个角度使用VUE过滤器详解
2019/09/11 Javascript
详解如何在JS代码中消灭for循环
2019/12/11 Javascript
js实现翻牌小游戏
2020/07/31 Javascript
[42:20]2014 DOTA2华西杯精英邀请赛5 24 DK VS NewBee
2014/05/25 DOTA
Python设计模式之门面模式简单示例
2018/01/09 Python
python生成tensorflow输入输出的图像格式的方法
2018/02/12 Python
解决import tensorflow as tf 出错的原因
2020/04/16 Python
python怎么提高计算速度
2020/06/11 Python
德购商城:德国进口直邮商城
2017/06/13 全球购物
美国和加拿大计算机和电子产品购物网站:TigerDirect.com
2019/09/13 全球购物
程序员经常用到的UNIX命令
2015/04/13 面试题
高三上学期学习自我评价
2014/04/23 职场文书
禁毒宣传活动总结
2014/08/26 职场文书
小学毕业典礼演讲稿
2014/09/09 职场文书
政风行风建设整改方案
2014/10/27 职场文书
2014年个人工作总结报告
2014/11/27 职场文书
2015试用期转正工作总结
2014/12/12 职场文书
大学生求职意向书
2015/05/11 职场文书
2019年聘任书的写作格式及范文!
2019/07/03 职场文书
MySQL事务的隔离级别详情
2022/07/15 MySQL
Rust中的Struct使用示例详解
2022/08/14 Javascript