详解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解析html开发库pyquery使用方法
Feb 07 Python
Windows上使用virtualenv搭建Python+Flask开发环境
Jun 07 Python
详解python中xlrd包的安装与处理Excel表格
Dec 16 Python
Python3实现购物车功能
Apr 18 Python
python selenium 对浏览器标签页进行关闭和切换的方法
May 21 Python
python遍历文件夹,指定遍历深度与忽略目录的方法
Jul 11 Python
python创建文件时去掉非法字符的方法
Oct 31 Python
python通过ffmgep从视频中抽帧的方法
Dec 05 Python
实例讲解Python中浮点型的基本内容
Feb 11 Python
利用Python的sympy包求解一元三次方程示例
Nov 22 Python
python、PyTorch图像读取与numpy转换实例
Jan 13 Python
Pytest实现setup和teardown的详细使用详解
Apr 17 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中的登陆login
2007/01/18 PHP
php GeoIP的使用教程
2011/03/09 PHP
PHP获取一年中每个星期的开始和结束日期的方法
2015/02/12 PHP
PHP代码实现爬虫记录――超管用
2015/07/31 PHP
php JWT在web端中的使用方法教程
2018/09/06 PHP
在网站上应该用的30个jQuery插件整理
2011/11/03 Javascript
兼容FF和IE的动态table示例自写
2013/10/21 Javascript
JS获取url链接字符串 location.href
2013/12/23 Javascript
AngularJS实现全选反选功能
2015/12/08 Javascript
js表单处理中单选、多选、选择框值的获取及表单的序列化
2016/03/08 Javascript
Web前端新人笔记之jquery入门心得(新手必看)
2016/05/17 Javascript
jquery 追加元素append、prepend、before、after用法与区别分析
2016/12/02 Javascript
JS实现DIV高度自适应窗口示例
2017/02/16 Javascript
jQuery插件FusionCharts实现的3D柱状图效果实例【附demo源码下载】
2017/03/03 Javascript
Node.js编写CLI的实例详解
2017/05/17 Javascript
详解vue-cli项目中的proxyTable跨域问题小结
2018/02/09 Javascript
vue3.0实现点击切换验证码(组件)及校验
2020/11/18 Vue.js
[50:58]2018DOTA2亚洲邀请赛 4.1 小组赛 B组 Mineski vs EG
2018/04/03 DOTA
[01:47]2018年度DOTA2最具人气解说-完美盛典
2018/12/16 DOTA
python使用PyGame模块播放声音的方法
2015/05/20 Python
django 实现编写控制登录和访问权限控制的中间件方法
2019/01/15 Python
Python实现遗传算法(二进制编码)求函数最优值方式
2020/02/11 Python
Django 设置多环境配置文件载入问题
2020/02/25 Python
python与c语言的语法有哪些不一样的
2020/09/13 Python
详解CSS3开启硬件加速的使用和坑
2017/08/21 HTML / CSS
HTML5 实现图片上传预处理功能
2020/02/06 HTML / CSS
H&M美国官网:欧洲最大的服饰零售商
2016/09/07 全球购物
Omio西班牙:全欧洲低价大巴、火车和航班搜索和比价
2017/02/11 全球购物
Strawberrynet草莓网新加坡站:护肤、彩妆、香水及美发产品
2018/08/31 全球购物
小学家长通知书评语
2014/12/31 职场文书
工程服务质量承诺书
2015/04/29 职场文书
2015民办小学年度工作总结
2015/05/26 职场文书
男人帮观后感
2015/06/18 职场文书
新娘婚礼致辞
2015/07/27 职场文书
Python离线安装openpyxl模块的步骤
2021/03/30 Python
opencv检测动态物体的实现
2021/07/21 Python