详解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实现的人工神经网络算法示例【基于反向传播算法】
Nov 11 Python
Python 中字符串拼接的多种方法
Jul 30 Python
对Python实现简单的API接口实例讲解
Dec 10 Python
Python爬虫实现验证码登录代码实例
May 10 Python
python opencv将图片转为灰度图的方法示例
Jul 31 Python
Django项目中实现使用qq第三方登录功能
Aug 13 Python
python如何判断IP地址合法性
Apr 05 Python
Python3实现飞机大战游戏
Apr 24 Python
Python如何急速下载第三方库详解
Nov 02 Python
python不同版本的_new_不同点总结
Dec 09 Python
python tqdm用法及实例详解
Jun 16 Python
Python自动化实战之接口请求的实现
May 30 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
javascript iframe中打开文件,并检测iframe存在否
2008/12/28 Javascript
类似CSDN图片切换效果脚本
2009/09/17 Javascript
JavaScript初学者应注意的七个细节详细介绍
2012/12/27 Javascript
简介AngularJS中使用factory和service的方法
2015/06/17 Javascript
jQuery实现灰蓝风格标准二级下拉菜单效果代码
2015/08/31 Javascript
js如何改变文章的字体大小
2016/01/08 Javascript
常用的几个JQuery代码片段
2017/03/13 Javascript
Vue2.0实现将页面中表格数据导出excel的实例
2017/08/09 Javascript
Vue实现6位数密码效果
2018/08/18 Javascript
在Vue组件中获取全局的点击事件方法
2018/09/06 Javascript
解决vue keep-alive 数据更新的问题
2018/09/21 Javascript
JS中实现一个下载进度条及播放进度条的代码
2019/06/10 Javascript
jQuery高级编程之js对象、json与ajax用法实例分析
2019/11/01 jQuery
ES5新增数组的实现方法
2020/05/12 Javascript
[38:44]DOTA2上海特级锦标赛A组小组赛#2 Secret VS CDEC第二局
2016/02/25 DOTA
Python读写ini文件的方法
2015/05/28 Python
关于python的bottle框架跨域请求报错问题的处理方法
2017/03/19 Python
详解python OpenCV学习笔记之直方图均衡化
2018/02/08 Python
用TensorFlow实现多类支持向量机的示例代码
2018/04/28 Python
python生成多个只含0,1元素的随机数组或列表的实例
2018/11/12 Python
Python如何将装饰器定义为类
2020/07/30 Python
解决python便携版无法直接运行py文件的问题
2020/09/01 Python
python如何对链表操作
2020/10/10 Python
使用CSS Grid布局实现网格的流动
2014/12/30 HTML / CSS
HTML5手机端弹出遮罩菜单特效代码
2016/01/27 HTML / CSS
LVMH旗下最大的奢侈品网站平台:24S
2020/05/24 全球购物
真诚的求职信
2014/07/04 职场文书
服务行业演讲稿
2014/09/02 职场文书
支部书记四风问题对照检查材料
2014/10/04 职场文书
普通党员个人剖析材料
2014/10/08 职场文书
2015年安全员工作总结范文
2015/04/22 职场文书
教师文明餐桌光盘行动倡议书
2015/04/28 职场文书
2015年管理人员工作总结
2015/05/13 职场文书
毕业设计论文致谢词
2015/05/14 职场文书
导游词之金鞭溪风景区
2019/09/12 职场文书
详解非极大值抑制算法之Python实现
2021/06/28 Python