详解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线程详解
Jun 24 Python
Python 的内置字符串方法小结
Mar 15 Python
python基于phantomjs实现导入图片
May 13 Python
Python调用微信公众平台接口操作示例
Jul 08 Python
Python实现的建造者模式示例
Aug 06 Python
Python数据可视化之画图
Jan 15 Python
初探利用Python进行图文识别(OCR)
Feb 26 Python
Pandas DataFrame数据的更改、插入新增的列和行的方法
Jun 25 Python
基于Python fminunc 的替代方法
Feb 29 Python
python装饰器三种装饰模式的简单分析
Sep 04 Python
python爬虫泛滥的解决方法详解
Nov 25 Python
只用Python就可以制作的简单词云
Jun 07 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/11/16 PHP
Apache2 httpd.conf 中文版
2006/12/06 PHP
yii2使用gridView实现下拉列表筛选数据
2017/04/10 PHP
php使用curl实现ftp文件下载功能
2017/05/16 PHP
Mac下快速搭建PHP开发环境步骤详解
2019/05/05 PHP
用window.location.href实现刷新另个框架页面
2007/03/07 Javascript
div浮层,滚动条移动,位置保持不变的4种方法汇总
2013/12/11 Javascript
可恶的ie8提示缺少id未定义
2014/03/20 Javascript
JavaScript清空数组元素的两种方法简单比较
2015/07/10 Javascript
实例讲解避免javascript冲突的方法
2016/01/03 Javascript
jQuery 获取多选框的值及多选框中文的函数
2016/05/16 Javascript
angular ngClick阻止冒泡使用默认行为的方法
2016/11/03 Javascript
基于Node的React图片上传组件实现实例代码
2017/05/10 Javascript
js canvas实现放大镜查看图片功能
2017/06/08 Javascript
详解ES6中的代理模式——Proxy
2018/01/08 Javascript
react 移动端实现列表左滑删除的示例代码
2019/07/04 Javascript
JavaScript实现单点登录的示例
2020/09/23 Javascript
[02:36]DOTA2混沌骑士 英雄基础教程
2013/11/26 DOTA
[01:14]DOTA2亚洲邀请赛 ShowOpen
2015/02/07 DOTA
Python随机生成均匀分布在三角形内或者任意多边形内的点
2017/12/14 Python
Python中的list与tuple集合区别解析
2019/10/12 Python
Python如何使用BeautifulSoup爬取网页信息
2019/11/26 Python
使用TensorFlow-Slim进行图像分类的实现
2019/12/31 Python
python 实现图像快速替换某种颜色
2020/06/04 Python
keras model.fit 解决validation_spilt=num 的问题
2020/06/19 Python
基于python判断字符串括号是否闭合{}[]()
2020/09/21 Python
美国新兴城市生活方式零售商:VILLA
2017/12/06 全球购物
墨尔本照明批发商店:Mica Lighting
2017/12/28 全球购物
租租车:国际租车、美国租车、欧洲租车、特价预订国外租车(中文服务)
2018/03/28 全球购物
Delphi CS笔试题
2014/01/04 面试题
后勤采购员岗位职责
2013/12/19 职场文书
法律专业大学生职业生涯规划书:向目标一步步迈进
2014/09/22 职场文书
个人贷款授权委托书样本
2014/10/07 职场文书
MySQL 慢查询日志深入理解
2021/04/22 MySQL
python tkinter Entry控件的焦点移动操作
2021/05/22 Python
Python游戏开发实例之graphics实现AI五子棋
2021/11/01 Python