详解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安装mysql-python简明笔记(ubuntu环境)
Jun 25 Python
基于python脚本实现软件的注册功能(机器码+注册码机制)
Oct 09 Python
1 行 Python 代码快速实现 FTP 服务器
Jan 25 Python
python奇偶行分开存储实现代码
Mar 19 Python
使用pandas对两个dataframe进行join的实例
Jun 08 Python
Django 多语言教程的实现(i18n)
Jul 07 Python
Python中常用的内置方法
Jan 28 Python
使用python 的matplotlib 画轨道实例
Jan 19 Python
基于Python爬虫采集天气网实时信息
Jun 05 Python
最新Python idle下载、安装与使用教程图文详解
Nov 28 Python
python实现xml转json文件的示例代码
Dec 30 Python
Python中字符串对象语法分享
Feb 24 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+AJAX实现无刷新注册(带用户名实时检测)
2006/12/02 PHP
php fputcsv命令 写csv文件遇到的小问题(多维数组连接符)
2011/05/24 PHP
php class中public,private,protected的区别以及实例分析
2013/06/18 PHP
PHP获取毫秒级时间戳的方法
2015/04/15 PHP
ECSHOP完美解决Deprecated: preg_replace()报错的问题
2016/05/17 PHP
javascript自适应宽度的瀑布流实现思路
2013/02/20 Javascript
jQuery简单入门示例之用户校验demo示例
2016/07/09 Javascript
javascript 数组的正态分布排序的问题
2016/07/31 Javascript
一个简单的JavaScript Map实例(分享)
2016/08/03 Javascript
Backbone View 之间通信的三种方式
2016/08/09 Javascript
AngularJS实现ajax请求的方法
2016/11/22 Javascript
微信小程序中实现一对多发消息详解及实例代码
2017/02/14 Javascript
Node.js五大应用性能技巧小结(必须收藏)
2017/08/09 Javascript
vue-cli项目中怎么使用mock数据
2017/09/27 Javascript
Vue 第三方字体图标引入 Font Awesome的方法
2018/09/28 Javascript
重学 JS:为啥 await 不能用在 forEach 中详解
2019/04/15 Javascript
[01:36]极致酷炫!TI9典藏宝瓶+撼地者至宝展示
2019/06/11 DOTA
python通过socket查询whois的方法
2015/07/18 Python
Python中functools模块的常用函数解析
2016/06/30 Python
Python绘制3D图形
2018/05/03 Python
Flask之flask-script模块使用
2018/07/26 Python
python 图像平移和旋转的实例
2019/01/10 Python
Python实现使用request模块下载图片demo示例
2019/05/24 Python
将Pytorch模型从CPU转换成GPU的实现方法
2019/08/19 Python
Python BeautifulReport可视化报告代码实例
2020/04/13 Python
matplotlib相关系统目录获取方式小结
2021/02/03 Python
CSS3弹性伸缩布局之box布局
2016/07/12 HTML / CSS
利用canvas实现图片压缩的示例代码
2018/07/17 HTML / CSS
运动服饰每月订阅盒:Ellie
2018/04/29 全球购物
如果一个类实现了多个接口但是这些接口有相同的方法名将会怎样
2013/06/16 面试题
AJAX的优缺点都有什么
2015/08/18 面试题
Boolean b = new Boolean(“abcde”); 会编译错误码
2013/11/27 面试题
毕业自我评价范文
2013/11/17 职场文书
高中英语教学反思
2014/02/04 职场文书
寻找最美家庭活动方案
2014/08/20 职场文书
2015年教研室工作总结范文
2015/05/23 职场文书