详解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装饰器初探(推荐)
Jul 21 Python
利用python求相邻数的方法示例
Aug 18 Python
Scrapy抓取京东商品、豆瓣电影及代码分享
Nov 23 Python
python分治法求二维数组局部峰值方法
Apr 03 Python
Python网络编程基于多线程实现多用户全双工聊天功能示例
Apr 10 Python
python中几种自动微分库解析
Aug 29 Python
python 使用多线程创建一个Buffer缓存器的实现思路
Jul 02 Python
详解pycharm连接远程linux服务器的虚拟环境的方法
Nov 13 Python
python绘制雷达图实例讲解
Jan 03 Python
python math模块的基本使用教程
Jan 16 Python
教你用python控制安卓手机
May 13 Python
Pygame Event事件模块的详细示例
Nov 17 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
论坛头像随机变换代码
2006/10/09 PHP
Ajax PHP分页演示
2007/01/02 PHP
phpwind中的数据库操作类
2007/01/02 PHP
微信公众号判断用户是否已关注php代码解析
2016/06/24 PHP
Avengerls vs KG BO3 第二场2.18
2021/03/10 DOTA
一个轻量级的javascript库 pj介绍
2010/12/19 Javascript
jquery插件制作 自增长输入框实现代码
2012/08/17 jQuery
JavaScript中getUTCSeconds()方法的使用详解
2015/06/11 Javascript
Javascript 计算字符串在localStorage中所占字节数
2015/10/21 Javascript
JS实现Ajax的方法分析
2016/12/20 Javascript
Vue循环组件加validate多表单验证的实例
2018/09/18 Javascript
koa2使用ejs和nunjucks作为模板引擎的使用
2018/11/27 Javascript
js实现unicode码字符串与utf8字节数据互转详解
2019/03/21 Javascript
IDEA安装vue插件图文详解
2019/09/26 Javascript
原生JS实现烟花效果
2020/03/10 Javascript
JavaScript设计模式之观察者模式与发布订阅模式详解
2020/05/07 Javascript
[01:02:48]2018DOTA2亚洲邀请赛小组赛 A组加赛 Newbee vs Liquid
2018/04/03 DOTA
Python交换变量
2008/09/06 Python
对Python中type打开文件的方式介绍
2018/04/28 Python
Python3.9 beta2版本发布了,看看这7个新的PEP都是什么
2020/06/10 Python
python右对齐的实例方法
2020/07/05 Python
python 6行代码制作月历生成器
2020/09/18 Python
python破解同事的压缩包密码
2020/10/14 Python
python爬虫爬取图片的简单代码
2021/01/18 Python
River Island美国官网:英国高街时尚品牌
2018/09/04 全球购物
美国时尚大码女装购物网站:Avenue
2019/05/24 全球购物
介绍java中初始化块的使用
2012/09/11 面试题
毕业生精彩的自我评价分享
2013/10/06 职场文书
怎么写有吸引力的自荐信
2013/11/17 职场文书
妈妈的账单教学反思
2014/02/06 职场文书
个人投资计划书
2014/05/01 职场文书
清正廉洁演讲稿
2014/05/22 职场文书
先进学校事迹材料
2014/12/30 职场文书
学雷锋献爱心倡议书
2015/04/27 职场文书
《秋思》教学反思
2016/02/23 职场文书
vue项目多环境配置(.env)的实现
2021/07/21 Vue.js