1. 程式人生 > >python實現小波變換的一個簡單例子

python實現小波變換的一個簡單例子

最近工作需要,看了一下小波變換方面的東西,用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

 

當waveletnc = 100時,則為下圖,誤差大約為0.04

 

當waveletnc = 200時,得到下圖,誤差大約為0.0005

相關推薦

python實現變換一個簡單例子

最近工作需要,看了一下小波變換方面的東西,用python實現了一個簡單的小波變換類,將來可以用在工作中。   簡單說

使用java實現快速排序的一個簡單例子

fast val rgs 快速 實現 個數 static void sta public static void main(String[] args) { // 測試排序 Random r = new Random(); int arr[] = new

變換簡單理解(1)

小波變換是對於訊號處理產生的一種分析方法。 1、在此之前,對於訊號分析應用的是傅立葉變換,但是傅立葉存在一定侷限性,不具備區域性化分析能力、不能分析非平穩訊號等。 2、基於傅立葉變換的侷限性,產生了短時傅立葉變換STFT,採用滑動視窗對訊號分段取樣,分段的訊號具

用socket.io實現websocket的一個簡單例子

soc .html www sock 在線 ket log html 簡單例子 http://biyeah.iteye.com/blog/1295196 socket.io的介紹 http://www.cnblogs.com/mazg/p/5467960.html

python入門篇:開發一個簡單的猜數字遊戲

python是史上最簡潔的語言!(其實就是一個文字遊戲) 今天太晚了,我把程式碼貼出來還有事情忙(其實是想偷個懶,不想打字,反正我有註釋) 看我的文章千萬不要著急,慢慢看完,看到最後。 ****************************** #coding=utf-8 name =

C語言實現一維變換

4、測試結果: 輸入訊號x(i)為: 取f1 = 5, f2 = 10, f0 = 320, n = 512。x(i)如圖1所示: 圖1 輸入訊號x(i) 一維小波變換後的訊號如圖2和圖3所示: 圖2 一維小波變換後的訊號,尺度係數和小波係數混在一起 圖3 一維小波變換後的訊號,尺度係數和小

Python烏龜----畫一個簡單的五角星

#五角星每個角的角度是36度啦 import turtle turtle.fd(100) turtle.right(144) turtle.fd(100) turtle.right(144) turtle.fd(100) turtle.right(144) turtle.fd

學習之一(單層一維離散變換DWT的Mallat演算法C++和MATLAB實現

1 Mallat演算法 離散序列的Mallat演算法分解公式如下: 其中,H(n)、G(n)分別表示所選取的小波函式對應的低通和高通濾波器的抽頭係數序列。 從Mallat演算法的分解原理可知,分解後的序列就是原序列與濾波器序列的卷積再進行隔點抽取而來。 離散序列的Ma

3D-DWT或者nD-DWT python下多維離散變換程式碼

3D-小波分解 這個示例是將一個三通道的RGB圖片看做一個時長為3的視訊序列來做3維的小波分解,通常2D-DWT的一級分解是將一張灰度圖分解為四個分量,而3D-DWT的以及分解是將一段視訊序列分解為8個分量。 import numpy as np imp

golang訊號處理及一個簡單例子實現

golang訊號處理及一個例子實現 往往實際專案中,我們希望修改了配置檔案後,但又不重啟程序的情況下而讓它重新載入配置檔案,這時候就需要通過訊號傳遞來進行處理這一優雅過程: 最常用的幾個Term終端傳入訊號 操作說明 一個簡單的栗子實現 幾個T

python 變換

pip install PyWavelets# -*- coding: utf-8 -*- import numpy as np import pywt import matplotlib.pyplot

Java後端實現websocket與微信程式端連線簡單例子

} 以上是網上的前端及後端的程式碼(原文地址:http://www.cnblogs.com/xdp-gacl/p/5193279.html?utm_source=tuicool&utm_medium=referral),jdk版本要求是在jdk1.7.0以上,tomcat版本也需要在tomcat7.0

哈爾變換的原理及其實現 Haar

for temp view include spa span csdn fun int Haar小波在圖像處理和數字水印等方面應用較多,這裏簡單的介紹一下哈爾小波的基本原理以及其實現情況。 一、Haar小波的基本原理 數學理論方面的東西我也不是很熟悉,

Haar變換的快速實現

先舉個例子,有a=[100,12,43,39]四個數,並使用b[4]陣列來儲存結果。 一級Haar小波變換的結果為: b[0] = (a[0] + a[1])/2 b[1] = (a[2] + a[3])/2 b[2] = (a[0] – a[1])/2 b[3] = (a[2] – a[3])/2 b[

變換檢測訊號突變點的MATLAB實現

**之前在**不經意間也有接觸過求突變點的問題。在我看來,與其說是求突變點,不如說是我們常常玩的"找不同"。給你兩幅影象,讓你找出兩個影象中不同的地方,我認為這其實也是找突變點在生活中的應用之一吧。回到找突變點位置上,以前自己有過一個傻傻的方法:就是直接求前後兩個取樣的的差分值,最後設定一個閾值,如果差分值大

C語言多線程的一個簡單例子

color oid blog stdlib.h null bsp 等待 creat 多線程   多線程的一個簡單例子:    #include <stdio.h> #include <stdlib.h> #include <string.h&

洗禮靈魂,修煉python(3)--從一個簡單的print代碼揭露編碼問題,運行原理和語法習慣

比較 編譯 windows 機器 函數 容易 打印字符 出現 無法 前期工作已經準備好後,可以打開IDE編輯器了,你可以選擇python自帶的IDLE,也可以選擇第三方的,這裏我使用pycharm——一個專門為python而生的編譯器 第一個python代碼當然是所有開發語

python實現那契數列筆記

log 得到 while span style mage lis nbsp images 斐波那契數列即著名的兔子數列:1、1、2、3、5、8、13、21、34、…… 數列特點:該數列從第三項開始,每個數的值為其前兩個數之和,用python實現起來很簡單: a=0 b=1

Python之自定義封裝一個簡單的Log類

實例對象 級別 port detail 問題 文件夾 相對 alt 腳本 參考:http://www.jb51.net/article/42626.htm 參考:http://blog.csdn.net/u011541946/article/details/70198676

python實現那契數列

定義函數 實現 python實現 code while 斐波那契數列 數列 int a+b 斐波那契數列 1, 1, 2, 3, 5, 8, 13, 21, 34, ... 除第一項和第二項外,任意一項的值為前面兩項的和 定義函數 def fib(N): n,a,b