详解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去掉字符串中重复字符的方法
Feb 27 Python
python通过定义一个类实例作为ftp回调方法
May 04 Python
python数据类型_字符串常用操作(详解)
May 30 Python
使用Python更换外网IP的方法
Jul 09 Python
win8下python3.4安装和环境配置图文教程
Jul 31 Python
python占位符输入方式实例
May 27 Python
PyQt5显示GIF图片的方法
Jun 17 Python
Python实现直播推流效果
Nov 26 Python
解决Keras使用GPU资源耗尽的问题
Jun 22 Python
详解Django中views数据查询使用locals()函数进行优化
Aug 24 Python
有关pycharm登录github时有的时候会报错connection reset的问题
Sep 15 Python
python爬取音频下载的示例代码
Oct 19 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
人尽可用的Windows技巧小贴士之下篇
2007/03/22 PHP
PHP批量上传图片的具体实现方法介绍.
2014/02/26 PHP
使用php实现从身份证中提取生日
2016/05/09 PHP
浅谈PHPANALYSIS提取关键字
2019/03/08 PHP
ThinkPHP5+UEditor图片上传到阿里云对象存储OSS功能示例
2019/08/05 PHP
很多人都是用下面的js刷新站IP和PV
2008/09/05 Javascript
js去除重复字符串两种实现方法
2013/01/09 Javascript
js字符串转换成数字与数字转换成字符串的实现方法
2014/01/08 Javascript
轻松创建nodejs服务器(1):一个简单nodejs服务器例子
2014/12/18 NodeJs
jQuery选择器源码解读(四):tokenize方法的Expr.preFilter
2015/03/31 Javascript
javascript的列表切换【实现代码】
2016/05/03 Javascript
20分钟成功编写bootstrap响应式页面 就这么简单
2016/05/12 Javascript
layer实现弹窗提交信息
2016/12/12 Javascript
解决vue+webpack打包路径的问题
2018/03/06 Javascript
详解Javascript中new()到底做了些什么?
2018/03/29 Javascript
vue-cli3中配置alias和打包加hash值操作
2020/09/04 Javascript
Vue实现穿梭框效果
2020/09/30 Javascript
vue+elementUI中表格高亮或字体颜色改变操作
2020/11/02 Javascript
python密码错误三次锁定(实例讲解)
2017/11/14 Python
Python3匿名函数lambda介绍与使用示例
2019/05/18 Python
Python学习笔记之lambda表达式用法详解
2019/08/08 Python
使用python快速在局域网内搭建http传输文件服务的方法
2019/11/14 Python
Canvas多边形绘制的实现方法
2019/08/05 HTML / CSS
Boston Proper官网:美国女装品牌
2017/10/30 全球购物
struct与class的区别
2014/02/03 面试题
关于环保的建议书400字
2014/03/12 职场文书
追悼会主持词
2014/03/20 职场文书
置业顾问岗位职责
2015/02/09 职场文书
2015年党员个人工作总结
2015/05/13 职场文书
运动会新闻报道稿
2015/07/22 职场文书
手术室消毒隔离制度
2015/08/05 职场文书
感恩老师主题班会
2015/08/12 职场文书
创业计划书之烤红薯
2019/09/26 职场文书
Python 如何安装Selenium
2021/05/06 Python
Django分页器的用法你都了解吗
2021/05/26 Python
总结python多进程multiprocessing的相关知识
2021/06/29 Python