打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
C#小波变换 - 平骜的日志 - 网易博客

C#小波变换

小波 2007-12-21 16:06:58 阅读395 评论7 字号:大中小

在我的一些文章中用到了小波变换所产生的结果。仅仅两个类完成的工作,现共享出来,欢迎大家使用,并体意见。

Seq.cs类是最基础的用于一维数组处理的;Wvlt.cs是小波变换的类;其中的主要思路来源于Matlab6.5.

Seq.cs的源码是:

using System;

usingSystem.Diagnostics;

namespaceMathArithmetic.Wavelet

{

    /// <summary>

    ///

   /// Seq 的摘要说明。

    /// 为小波变换而设计的序列运算对象。

    ///

   /// 何险峰

    ///

    /// </summary>

    public class Seq{

        public float[] elements=null;

        public Seq(){

            elements = new float[0];

        }

       public Seq(int Len){

           elements = new float[Len];

        }

        public Seq(float[] elt){

            elements = new float[elt.Length];

            elt.CopyTo(elements,0);

        }

       public Seq(double[] elt){

           elements = new float[elt.Length];

           for (int i=0;i<elt.Length; i++) elements[i] = (float)elt[i];

        }

       public Seq(Seq s){

           elements = new float[s.Length];

           s.elements.CopyTo(elements,0);

       }

        //Length of sequence

        public int Length {

            get {

                return elements.Length;

            }

       }

        public float this[ intindex ] {

            get    {

                Debug.Assert( 0 <= index);

                return elements[index];

            }

            set {

               Debug.Assert( 0 <= index );

               elements[index] = value;

           }

        }

        public void Split2(out Seq s1,out Seqs2){

            int i,half = Length /2;

            float[]

                A = new float[half],

                D = new float[half];

            for (i=0;i<A.Length;i++) A[i] =this[i];

            for(i=0;i<D.Length;i++) D[i] = this[i + half];

            s1 = new Seq(A);

            s2 = new Seq(D);

        }

       public Seq Concatenate(Seq s){

           if (Length == 0) return s;

           int len = Length + s.Length;

           float[] d = new float[len];

           elements.CopyTo(d,0);

           for (int i=0;i<s.Length;i++){

               d[Length + i] = s[i];

           }

            return newSeq(d);

        }

        public bool IsOdd{

            get    {return (Length % 2 != 0);}

        }

       public bool IsEven{

           get    {return (Length % 2 == 0);}

       }

        static public booloperator==( Seq a, Seq b ) {

           for(int i = 0; i<a.Length;i++){

               if(a[i] != b[i]) return false;

            }

            returntrue;

        }

        static public bool operator!=( Seq a,Seq b ) {

            return !(a == b);

        }

       public override bool    Equals( object o ) {

            if( o is Seq ) {

                Seq s = (Seq) o;

                return ( this == s );

            }

           return false;

        }

        public override int    GetHashCode() {

            return this.GetHashCode();

        }

       static public Seq operator+(Seq s1,Seq s2){

            Seq sum = new Seq(s1.Length);

            for (int i = 0; i < s1.Length;i++) sum[i] = s1[i] + s2[i];

           return sum;

        }

        static public Seq operator-(Seq s1,Seqs2){

            Seq sum = newSeq(s1.Length);

            for (int i =0; i < s1.Length; i++) sum[i] = s1[i] - s2[i];

            return sum;

        }

       //边缘处理

        static private intEdge(int x,int xsize)

        {

            while ((x<0)||(x>=xsize))

            {

                if (x<0) x = -x;

                if (x>=xsize)

                   x = xsize * 2 - x - 2;

           }

            return x;

        }

       //卷积

        static public Seqoperator *(Seq s1,Seq s2)

        {

            //Seq ss2 =SymmetricExtension(s2);

            Seqcon = new Seq(s1.Length + s2.Length - 1);

            int i,j,k;

           for (i = 0; i < con.Length; i++){

                con[i] = 0.0f;

               for (j = 0; j < s1.Length; j++){

                    k = i-j;

                    con[i] += s1[j] *s2[Edge(k,s2.Length)];

                   //if (k >= 0 && k < s2.Length) con[i] += s1[j] *s2[k];

                }

            }

           return con;

        }

        static public Seq operator*(float d,Seq s){

            Seq m = new Seq(s);

            for (int i = 0; i <m.Length; i++) m[i] *= d;

           return m;

        }

        //反转

       public Seq Wrev(){

            Seqtr = new Seq(Length);

            for(int i = 0; i < Length; i++)

               tr.elements[i] = elements[Length-1-i];

            return tr;

        }

       //积分镜像过滤

        public Seq Qmf(){

            //Quadrature mirror filter

            Seq tr = Wrev().Altsign();

            return tr;

        }

       //间隔变号

        public SeqAltsign(){

            Seq alt = newSeq(this);

            int sign = 1;

            for (int i = 0; i < Length;i++) {

                alt[i] *= sign;

                sign *= -1;

            }

           return alt;

        }

        //返回间隔抽样

        public Seq Dyaddown(){

           Seq down = new Seq(Length / 2);

            for (int i = 0; i < down.Length; i++)down[i] =this[2*i];

            return down;

        }

       //倍增样本

        public SeqDyadup(){

            Seq up = newSeq(Length * 2);

            for (int i= 0; i < up.Length; i++)

               up[i] = (i%2 == 0)  ?  0.0f : this[i/2];

            return up;

        }

       //返回序列中间部分--见Matlab wkeep

       public Seq Wkeep(int len){

           if (len>=Length) return new Seq(this);

            Seq keep = new Seq(len);

            int dif=Length - len,  start = dif / 2;

            if((start==0)&&(dif>0))start=1;

            for(int i=0;i<len;i++) keep[i] = this[i+start];

           return keep;

        }

        //模2

       public float Norm(){

           float sum = 0.0f;

            for(inti=0;i<Length;i++){

               sum += this[i] * this[i];

            }

            sum = (float)Math.Sqrt(sum);

            return sum;

        }

       //合计

        public float Sum(){

            float sum = 0.0f;

            for(int i=0;i<Length;i++){

                sum += this[i];

            }

           return sum;

        }

        public string EleStr(){

            string s="";

            int i;

            for (i=0;i<Length;i++)

                s += String.Format("{0:d} {1:f},",i, elements[i]);

            return s + "\n";

        }

       public string EleFrequencyStr(){

           float delta = (float)(Math.PI /Length);

            string s = "";

            for (float w = 0.0f; w <=Math.PI; w+=delta) {

               double rsum = 0.0f, isum = 0.0f;

               for (int n = 0; n <= Length; n++) {

                    rsum += this[n] *Math.Cos(-n * w);

                   isum += this[n] * Math.Sin(-n * w);

               }

                double

                    hypot =Math.Sqrt(rsum*rsum + isum*isum),

                   atan2 = Math.Atan2(isum,rsum);

                s += String.Format("w={0:f},hypot={1:f}, atan2= {2:f}",w,hypot,atan2);

            }

            return s+ "\n";

        }

    }

}

using System;

using MathArithmetic;

namespaceMathArithmetic

{

    /// <summary>

    ///

   /// Wvlt 的摘要说明。

    /// Mallat快速小波变换

    ///

   /// 何险峰

    ///

    ///   该小波变换采用的是递归算法,仅2维检验测试有误。

    /// 可以用Matlab的非递归算法替代。

    ///   2005-09-04

    ///

   /// </summary>

    public classWvlt

    {

        public static float[]

           haar= {0.5f,0.5f},

           db1 = {0.5f,0.5f},

            db2 ={0.34151f,    0.59151f,0.15849f,-0.091506f},

            db3 = {0.23523f,   0.57056f,0.32518f,-0.095467f,-0.060416f,0.024909f},

            db4 = {0.1629f,   0.50547f,0.4461f,    -0.019788f,-0.13225f,    0.021808f,   0.023252f,    -0.0074935f},

           db5 = {0.11321f,    0.42697f,0.51216f, 0.097883f,-0.17133f,   -0.022801f,    0.054851f,    -0.0044134f,    -0.0088959f,   0.0023587f},

            db6 ={0.078871f,0.34975f,0.53113f, 0.22292f, -0.15999f,    -0.091759f,   0.068944f,     0.019462f,    -0.022332f,    0.00039163f,   0.003378f,    -0.00076177f    },

           db7 = {0.05505f,    0.2804f,    0.51557f, 0.33219f,-0.10176f,    -0.15842f,    0.050423f,     0.057002f,    -0.026891f,   -0.01172f,    0.0088749f,    0.00030376f,    -0.001274f,   0.00025011f},

            db8 ={0.038478f,0.22123f,0.47774f, 0.41391f, -0.011193f,-0.20083f,   0.0003341f,     0.091038f,    -0.012282f,    -0.031175f,   0.0098861f,    0.0061844f,    -0.0034439f,    -0.000277f,   0.00047761f,    -8.3069e-005f},

           db9 = {0.026925f,0.17242f,0.42767f, 0.46477f, 0.094185f,-0.20738f,  -0.068477f,    0.10503f,    0.021726f,   -0.047824f,    0.00017745f,    0.015812f,    -0.0033398f,   -0.0030275f,    0.0013065f,    0.00016291f,    -0.00017816f,   2.7823e-005f},

            db10={0.018859f,0.13306f,0.37279f, 0.48681f,  0.19882f,    -0.17667f, -0.13855f,     0.090064f,     0.065801f,    -0.050483f,    -0.02083f,   0.023485f,    0.0025502f,    -0.0075895f,    0.00098666f,   0.0014088f,    -0.00048497f,    -8.2355e-005f,    6.6177e-005f,   -9.3792e-006f},

            coif2 ={0.011588f,-0.02932f,-0.04764f,0.27302f,0.57468f,0.29487f,-0.054086f,-0.042026f,0.016744f,0.0039679f,-0.0012892f,-0.00050951f},

            coif3 ={-0.0026824f,0.0055031f,0.016584f,-0.046508f,-0.043221f,0.2865f,0.56129f,0.30298f,-0.05077f,-0.058196f,0.024434f,0.011229f,-0.0063696f,-0.0018205f,0.00079021f,0.00032967f,-5.0193e-005f,-2.4466e-005f},

            coif4 ={0.00063096f,-0.0011522f,-0.0051945f,0.011362f,0.018867f,-0.057464f,-0.039653f,0.29367f,0.55313f,0.30716f,-0.047113f,-0.068038f,0.027814f,0.017736f,-0.010756f,-0.004001f,0.0026527f,0.00089559f,-0.0004165f,-0.00018383f,4.408e-005f,2.2083e-005f,-2.3049e-006f,-1.2622e-006f},

            dmey ={-7.1418e-013f,6.0242e-009f,-7.8626e-009f,-7.6359e-009f,4.29e-008f,-7.6838e-008f,5.7988e-008f,8.3318e-008f,-3.8936e-007f,7.9959e-007f,-1.0533e-006f,5.2097e-007f,2.2666e-006f,-1.1535e-005f,4.6346e-005f,-0.00042508f,-0.0019125f,0.0015574f,0.004275f,-0.0045168f,-0.0078217f,0.010798f,0.01232f,-0.02272f,-0.017217f,0.04507f,0.021676f,-0.093936f,-0.024811f,0.31437f,0.5265f,0.31437f,-0.024811f,-0.093936f,0.021676f,0.04507f,-0.017217f,-0.02272f,0.01232f,0.010798f,-0.0078217f,-0.0045168f,0.004275f,0.0015574f,-0.0019125f,-0.00042508f,4.6346e-005f,-1.1535e-005f,2.2666e-006f,5.2097e-007f,-1.0533e-006f,7.9959e-007f,-3.8936e-007f,8.3318e-008f,5.7988e-008f,-7.6838e-008f,4.29e-008f,-7.6359e-009f,-7.8626e-009f,6.0242e-009f,-7.1418e-013f,0},

            df2_2 ={-0.1250f,0.2500f,0.7500f,0.2500f,-0.1250f},

            rf2_2 = {0.2500f,0.5000f,0.2500f},

            df1_3 ={-0.0625f,0.0625f,0.5000f,0.5000f,0.0625f,-0.0625f},

            rf1_3 = {0.5f,0.5f},

            df1_5 ={0.0117f,-0.0117f,-0.0859f,0.0859f, 0.5000f, 0.5000f, 0.0859f,-0.0859f},

            rf1_5 ={0.5f,0.5f},

            df3_1 ={-0.2500f,0.7500f,0.7500f,-0.2500f},

           rf3_1 = {0.1250f,0.3750f,0.3750f,0.1250f},

            df4_4 = {0.0267f,   -0.0169f, -0.0782f,   0.2669f,    0.6029f,    0.2669f,   -0.0782f,   -0.0169f,   0.0267f},

            rf4_4 ={-0.0456f,   -0.0288f,   0.2956f,   0.5575f,    0.2956f,  -0.0288f,  -0.0456f},

            df5_5 ={0.0281f,0.0056f,-0.0385f, 0.2444f, 0.5209f, 0.2444f, -0.0385f,0.0056f,0.0281f},

            rf5_5 ={0.0095f,-0.0019f,-0.0967f, -0.0661f,  0.3372f, 0.6360f, 0.3372f,-0.0661f,-0.0967f, -0.0019f, 0.0095f},

           df6_8 = {0.0013f,-0.0014f,-0.0120f, 0.0084f,0.0352f,-0.0546f,-0.0665f, 0.2975f,0.5840f,0.2975f, -0.0665f,  -0.0546f, 0.0352f,0.0084f, -0.0120f, -0.0014f,0.0013f},

           rf6_8 = {-0.0102f,-0.0102f,0.0557f, 0.0285f,-0.2955f, -0.5366f,-0.2955f, 0.0285f,0.0557f, -0.0102f, -0.0102f};

        protected

            Seq    LPrime,        

            Lo_D,Hi_D, //Decomposition of Low_Pass,High_Pass

            Lo_R,Hi_R; //Reconstruction ofLow_Pass,High_Pass

        /*

          [RF,DF] = biorwavf(W) returns twoscaling filters associated with the biorthogonal wavelet specified bythe string W. W = 'biorNr.Nd' where possible values for Nr and Nd areNr =1 Nd = 1 , 3 or 5 Nr = 2 Nd = 2 , 4 , 6 or 8Nr = 3Nd = 1 , 3 , 5 , 7 or9Nr = 4 Nd = 4 Nr = 5 Nd = 5 Nr = 6 Nd = 8The output arguments arefilters. RF is the reconstruction filter. DF is the decompositionfilter. Examples% Set spline biorthogonal wavelet name.

          wname = 'bior2.2';

          % Compute the two correspondingscaling filters.

          % rf is thereconstruction scaling filter.

         % df is the decomposition scaling filter.

            [rf,rd] = biorwavf(wname)

            rf =  0.2500   0.5000   0.2500

            df = -0.1250   0.2500   0.7500  0.2500 -0.1250

         */

        // Construct orthogonal wavelet withcoeffients from array fv

        publicWvlt(float[]fv)

        {

            LPrime = new Seq(fv);

            GetFilters(LPrime);

        }

       public Wvlt(string fltnm)

        {

            switch (fltnm)

            {

               case "haar":

               case "db1": LPrime = new Seq(db1);GetFilters(LPrime);break;

                case "db2": LPrime = newSeq(db2);GetFilters(LPrime);break;

               case "db3": LPrime = new Seq(db3);GetFilters(LPrime);break;

                case "db4": LPrime = newSeq(db4);GetFilters(LPrime);break;

               case "db5": LPrime = new Seq(db5);GetFilters(LPrime);break;

                case "db6": LPrime = newSeq(db6);GetFilters(LPrime);break;

               case "db7": LPrime = new Seq(db7);GetFilters(LPrime);break;

                case "db8": LPrime = newSeq(db8);GetFilters(LPrime);break;

               case "db9": LPrime = new Seq(db9);GetFilters(LPrime);break;

                case "db10": LPrime = newSeq(db10);GetFilters(LPrime);break;

               case "coif2": LPrime = newSeq(coif2);GetFilters(LPrime);break;

               case "coif3": LPrime = newSeq(coif3);GetFilters(LPrime);break;

               case "coif4": LPrime = newSeq(coif4);GetFilters(LPrime);break;

               case "dmey": LPrime = newSeq(dmey);GetFilters(LPrime);break;

               case "bior1.3" : Lo_R = new Seq(rf1_3); Lo_D = newSeq(df1_3);CalcuBior();break;

               case "bior1.5" : Lo_R = new Seq(rf1_5); Lo_D = newSeq(df1_5);CalcuBior();break;

               case "bior2.2" : Lo_R = new Seq(rf2_2); Lo_D = newSeq(df2_2);CalcuBior();break;

               case "bior3.1" : Lo_R = new Seq(rf3_1); Lo_D = newSeq(df3_1);CalcuBior();break;

               case "bior4.4" : Lo_R = new Seq(rf4_4); Lo_D = newSeq(df4_4);CalcuBior();break;

               case "bior5.5" : Lo_R = new Seq(rf5_5); Lo_D = newSeq(df5_5);CalcuBior();break;

               case "bior6.8" : Lo_R = new Seq(rf6_8); Lo_D = newSeq(df6_8);CalcuBior();break;

               default : LPrime = new Seq(db1);GetFilters(LPrime);break;

            }

        }

        public voidCalcuBior()   {

            Lo_R =1.0f/Lo_R.Norm() * Lo_R;

           Hi_R = Lo_R.Qmf();

            Lo_D =1.0f/Lo_D.Norm() * Lo_D;

           Hi_D = Hi_R.Wrev();

        }

        //根据给定滤波器,产生两对孪生小波变换基对象

        public void GetFilters(Seq w)   {

            //w.Norm() = 0.7071;

            float nw = 1 / w.Norm();

            Lo_R = nw * w;

            Hi_R = Lo_R.Qmf();

            Lo_D = Lo_R.Wrev();

            Hi_D = Hi_R.Wrev();

        }

       //一维Mallat快速小波正变换

        publicSeq fwt(Seq fv, int lev)   {

           Seq tmp=fv;

           if (lev==0) {

                tmp = fv;

            } else {

                lev /=2;

                Seq low  = Lo_D * fv;

                low  =low.Wkeep(fv.Length).Dyaddown();

               

                Seq high = Hi_D * fv;

                high =high.Wkeep(fv.Length).Dyaddown();

               tmp = fwt(low,lev);

               tmp = tmp.Concatenate(high);

           }

            return tmp;

        }

       //一维Mallat快速小波反变换

        publicSeq ifwt(Seq fv, int lev)   {

           Seq tmp = fv,low,high;

           int keeplen;

            if (lev==0) {

                 tmp = fv;

            } else {

                lev /=2;

                fv.Split2(out low,out high);

                keeplen = low.Length * 2;

                tmp  = ifwt(low,lev);

                Seq rlow  = Lo_R *tmp.Dyadup() ;

                Seqrhigh = Hi_R * high.Dyadup();

               tmp = rlow + rhigh;

               tmp = tmp.Wkeep(keeplen);

           }

            return tmp;

        }

       /* GetBlocksAndBaseLen功能:

        *   求二进波序列分块数、最小块长度。

         * 输入

         *   序列长度:len,

         *   尺度大小:lev

         * 输出

        *   分块数:numblocks

         *  最小块长度:baselen

         */

        private static voidGetBlocksAndBaseLen(int len,int lev,out int numblocks, out int baselen)

        {

           int mb = (int)Math.Log(len,2);

           numblocks = mb - lev;

           baselen = (int)(len / Math.Pow(2,numblocks));

            /*

            baselen = len;

           numblocks = 0;

            intn2 = (1 << lev);//2^lev

           while (baselen >= n2) {

               numblocks ++;

               baselen = baselen >> 1; //baselen / 2

            }

            baselen= baselen << 1;

           numblocks --;

            */

        }

       //获取mat中rid行

        publicfloat[] GetRow(int rid,float[,] mat)

       {

            int cols =mat.GetLength(1);

            float[]row = new float[cols];

            for(int j=0;j<cols;j++)

               row[j] = mat[rid,j];

           return row;

        }

        //设置mat中rid行

        public void SetRow(int rid,float[]row,float[,] mat)

        {

            int cols =  mat.GetLength(1);

            for (int j=0;j<cols;j++)

                mat[rid,j] = row[j];

        }

       //获取mat中cid列

        publicfloat[] GetCol(int cid,float[,] mat)

       {

            int rows = mat.GetLength(0);

            float[]col = new float[rows];

            for(int i=0;i<rows;i++)

               col[i] = (float)mat[i,cid];

           return col;

        }

        //设置mat中cid列

        public void SetCol(intcid,float[]col,float[,] mat)

        {

            int rows =  mat.GetLength(0);

            for (int i=0;i<rows;i++)

                mat[i,cid] = col[i];

        }

       //二维Mallat快速小波正变换

        publicvirtual float[,] fwt2( float[,]fi, int wlev,int hlev)

        {

           int rows = fi.GetLength(0),cols = fi.GetLength(1);

            float[,] wt = newfloat[rows,cols];

            Seq tmp;

            int i;

            for (i = 0; i < rows; i++)

            {

                tmp = new Seq(GetRow(i,fi));

                tmp = fwt(tmp,wlev);

                SetRow(i,tmp.elements,wt);

            }

            for (i = 0; i < cols; i++)

            {

               tmp = new Seq(GetCol(i,wt));

                tmp = fwt(tmp,hlev);

                SetCol(i,tmp.elements,wt); 

            }

           return wt;

        }

        //二维Mallat快速小波反变换

        public virtual float[,] ifwt2(float[,]fi, int wlev, int hlev)

        {

            int rows = fi.GetLength(0),cols =fi.GetLength(1);

            float[,]iwt = (float[,])fi.Clone();

           Seq tmp;

            int i;

            for (i = 0; i < cols; i++)

            {

                tmp = new Seq(GetCol(i,iwt));

                tmp = ifwt(tmp,hlev);

                SetCol(i,tmp.elements,iwt); 

            }

            for (i = 0; i < rows; i++)

            {

               tmp = new Seq(GetRow(i,iwt));

                tmp = ifwt(tmp,wlev);

                SetRow(i,tmp.elements,iwt);

            }

           return iwt;

        }

        /*GetDim2Blocks 功能

         * 二维小波变换后的块数

         */

       private static int GetDim2Blocks(int numblocks)

        {

           int a0=4,d=3,an = a0 + (numblocks - 1) * d; //等差数列末项是块矩阵数

            return an;

        }

   }

}

效果检验

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
一文教你搞懂C语言的Q格式
使用Java中随机生成的数据进行pi的Monte Carlo计算
msg数据类型
经典程序100例(71-80)
选择排序
【转】PageRank算法源代码实现(java)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服