详解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 相关文章推荐
使用wxPython获取系统剪贴板中的数据的教程
May 06 Python
python抓取百度首页的方法
May 19 Python
python实现的守护进程(Daemon)用法实例
Jun 02 Python
剖析Django中模版标签的解析与参数传递
Jul 21 Python
Python开发的实用计算器完整实例
May 10 Python
python3大文件解压和基本操作
Dec 15 Python
python使用Apriori算法进行关联性解析
Dec 21 Python
Django压缩静态文件的实现方法详析
Aug 26 Python
解读python如何实现决策树算法
Oct 11 Python
使用python实现数组、链表、队列、栈的方法
Dec 20 Python
文件上传服务器-jupyter 中python解压及压缩方式
Apr 22 Python
python前后端自定义分页器
Apr 13 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 set_time_limit(0) 设置程序执行时间的函数
2010/05/26 PHP
php循环语句 for()与foreach()用法区别介绍
2012/09/05 PHP
php实现可以设置中奖概率的抽奖程序代码分享
2014/01/19 PHP
thinkPHP简单遍历数组方法分析
2016/05/16 PHP
Yii2中使用asset压缩js,css文件的方法
2016/11/24 PHP
prototype 1.5相关知识及他人笔记
2006/12/16 Javascript
学习ExtJS(一) 之基础前提
2009/10/07 Javascript
from 表单提交返回值用post或者是get方法实现
2013/08/21 Javascript
javascript实现动态侧边栏代码
2014/02/19 Javascript
JavaScript ParseFloat()方法
2015/12/18 Javascript
Node.js中npm常用命令大全
2016/06/09 Javascript
jQuery简单实现彩色云标签效果示例
2016/08/01 Javascript
Bootstrap的基本应用要点浅析
2016/12/19 Javascript
详解Vue.js分发之作用域槽
2017/06/13 Javascript
vue脚手架及vue-router基本使用
2018/04/09 Javascript
如何从零开始利用js手写一个Promise库详解
2018/04/19 Javascript
Vue实现6位数密码效果
2018/08/18 Javascript
30分钟用Node.js构建一个API服务器的步骤详解
2019/05/24 Javascript
基于layui轮播图满屏是高度自适应的解决方法
2019/09/16 Javascript
js实现小时钟效果
2020/03/25 Javascript
Vue使用预渲染代替SSR的方法
2020/07/02 Javascript
python抓取网页内容示例分享
2014/02/24 Python
基于Python os模块常用命令介绍
2017/11/03 Python
python 把文件中的每一行以数组的元素放入数组中的方法
2018/04/29 Python
python 简单照相机调用系统摄像头实现方法 pygame
2018/08/03 Python
python 使用while循环输出*组成的菱形实例
2020/04/12 Python
马来西亚综合购物网站:Lazada马来西亚
2018/06/05 全球购物
什么是静态路由?什么是动态路由?各自的特点是什么?
2015/09/16 面试题
护士个人简历自荐信
2013/10/18 职场文书
校园报刊亭创业计划书
2014/01/02 职场文书
五型班组建设方案
2014/02/10 职场文书
交通局领导班子群众路线教育实践活动对照检查材料思想汇报
2014/10/09 职场文书
教师三严三实心得体会
2014/10/11 职场文书
车间统计员岗位职责
2015/04/14 职场文书
Python连接Postgres/Mysql/Mongo数据库基本操作大全
2021/06/29 Python
Python内置的数据类型及使用方法
2022/04/13 Python