详解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高并发异步服务器核心库forkcore使用方法
Nov 26 Python
详解Python3.1版本带来的核心变化
Apr 07 Python
浅谈Python的Django框架中的缓存控制
Jul 24 Python
基于Python实现文件大小输出
Jan 11 Python
详解Python 爬取13个旅游城市,告诉你五一大家最爱去哪玩?
May 07 Python
简单了解python代码优化小技巧
Jul 08 Python
python tkinter实现屏保程序
Jul 30 Python
pygame实现俄罗斯方块游戏(基础篇3)
Oct 29 Python
解决pycharm不能自动补全第三方库的函数和属性问题
Mar 12 Python
Keras Convolution1D与Convolution2D区别说明
May 22 Python
Python如何设置指定窗口为前台活动窗口
Aug 12 Python
python实现图片素描效果
Sep 26 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
漫威DC御用漫画家去世 他的表情包曾走红网络
2020/04/09 欧美动漫
杏林同学录(九)
2006/10/09 PHP
php之对抗Web扫描器的脚本技巧
2008/10/01 PHP
php实现只保留mysql中最新1000条记录
2015/06/18 PHP
php实现解析xml并生成sql语句的方法
2018/02/03 PHP
PHP实现 APP端微信支付功能
2018/06/22 PHP
深入研究PHP中的preg_replace和代码执行
2018/08/15 PHP
PHP调用接口API封装的例子
2019/10/11 PHP
createTextRange()的使用示例含文本框选中部分文字内容
2014/02/24 Javascript
JQuery中$(document)是什么意思有什么作用
2014/07/21 Javascript
jQuery progressbar通过Ajax请求实现后台进度实时功能
2016/10/11 Javascript
JavaScript获取短信验证码(周期性)
2016/12/29 Javascript
详解angularJs指令的3种绑定策略
2017/04/13 Javascript
jQuery插件Validation表单验证详解
2018/05/26 jQuery
.vue文件 加scoped 样式不起作用的解决方法
2018/05/28 Javascript
JavaScript基于对象方法实现数组去重及排序操作示例
2018/07/10 Javascript
vue做移动端适配最佳解决方案(亲测有效)
2018/09/04 Javascript
详解React中传入组件的props改变时更新组件的几种实现方法
2018/09/13 Javascript
vue-cli3 DllPlugin 提取公用库的方法
2019/04/24 Javascript
[07:06]2018DOTA2国际邀请赛寻真——卫冕冠军Team Liquid
2018/08/10 DOTA
Python守护进程和脚本单例运行详解
2017/01/06 Python
利用信号如何监控Django模型对象字段值的变化详解
2017/11/27 Python
python之DataFrame实现excel合并单元格
2021/02/22 Python
利用python的socket发送http(s)请求方法示例
2018/05/07 Python
python基于递归解决背包问题详解
2019/07/03 Python
python3.6+selenium实现操作Frame中的页面元素
2019/07/16 Python
安装完Python包然后找不到模块的解决步骤
2020/02/13 Python
让你相见恨晚的十个Python骚操作
2020/11/18 Python
html5记忆翻牌游戏实现思路及代码
2013/07/25 HTML / CSS
HTML5 weui使用笔记
2019/11/21 HTML / CSS
Nisbets爱尔兰:英国最大的厨房和餐饮设备供应商
2019/01/26 全球购物
PHP面试题集
2016/12/18 面试题
毛主席纪念堂观后感
2015/06/17 职场文书
分析设计模式之模板方法Java实现
2021/06/23 Java/Android
Mysql中有关Datetime和Timestamp的使用总结
2021/12/06 MySQL
springboot为异步任务规划自定义线程池的实现
2022/06/14 Java/Android