离散小波变换算法的C++实现

头文件:

/*
 * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), [email protected]
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 2 or any later version.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details. A copy of the GNU General Public License is available at:
 * http://www.fsf.org/licensing/licenses
 */


/*****************************************************************************
 *                                filtercoefs.h
 *
 * Some generally used filter coeffcients in wavelet transform.
 *
 * Zhang Ming, 2010-03, Xi'an Jiaotong University.
 *****************************************************************************/


#ifndef COEFFICIENTS_H
#define COEFFICIENTS_H


#include <vector.h>


namespace splab
{


	template<typename Type>	void db4Coefs( Vector<Type>&, Vector<Type>&,
	                                       Vector<Type>&, Vector<Type>& );


    #include <filtercoefs-impl.h>

}
// namespace splab


#endif
// COEFFICIENTS_H
/*
 * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), [email protected]
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 2 or any later version.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details. A copy of the GNU General Public License is available at:
 * http://www.fsf.org/licensing/licenses
 */


/*****************************************************************************
 *                                    dwt.h
 *
 * Discrete Wavelet Transform.
 *
 * Class template of discrete wavelet transform, which is designed for
 * computing the discrete wavelet transform and it's inverse transform. The
 * wavelet type is specified by parameter "wname".
 *
 * The decompse and reconstruction levels are specified by integer "J". The
 * approximation and detial coefficents are stroed in an 1D vector as
 * fallowing format:
 *                      ---------------------------------
 *		                | d1 | d2 | * | * | * | dJ | aJ |
 *		                ---------------------------------
 * The signal's length, detial's and approximation's  lengths, are stored
 * in a vectro as fallow:
 *              --------------------------------------------------
 *              | L_sig | L_d1 | L_d2 | * | * | * | L_dJ | L_aJ |
 *              --------------------------------------------------
 *
 * Zhang Ming, 2010-03, Xi'an Jiaotong University.
 *****************************************************************************/


#ifndef DWT_H
#define DWT_H


#include <string>
#include <cstdlib>
#include <vector.h>
#include <convolution.h>
#include <filtercoefs.h>


namespace splab
{

	template <typename Type>
	class DWT
	{

	public:

		DWT( const string &wname );
		~DWT();

		Vector<Type> dwt( const Vector<Type> &signal, int J );
		Vector<Type> idwt( const Vector<Type> &coefs, int j );

		Vector<Type> getApprox( const Vector<Type> &coefs );
		Vector<Type> getDetial( const Vector<Type> &coefs, int j );
		void setApprox( const Vector<Type> &approx, Vector<Type> &coefs );
		void setDetial( const Vector<Type> &detial, Vector<Type> &coefs,
                        int j );

    private:

        // wavelet type
        string waveType;

        // decompose and reconstruction filter banks
        Vector<Type> ld, hd,
                     lr, hr;

		// length information of coefficients
		Vector<int> lenInfo;

		void getFilter( const string &wname );
		void lengthInit( int sigLength, int J );

	};
    // class DWT


    #include <dwt-impl.h>

}
// namespace splab


#endif
// DWT_H

实现文件:

/*
 * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), [email protected]
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 2 or any later version.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details. A copy of the GNU General Public License is available at:
 * http://www.fsf.org/licensing/licenses
 */


/*****************************************************************************
 *                            filtercoefs-impl.h
 *
 * Implementation for filter coeffcients in wavelet transform.
 *
 * Zhang Ming, 2010-03, Xi'an Jiaotong University.
 *****************************************************************************/


/**
 * Daubichies filters for wavelets with 4 vanishing moments.
 */
template <typename Type>
void db4Coefs( Vector<Type> &ld, Vector<Type> &hd,
               Vector<Type> &lr, Vector<Type> &hr )
{
    ld.resize(8);
    ld[0] = Type(-0.010597401784997);		ld[1] = Type(0.032883011666983);
    ld[2] = Type(0.030841381835987); 		ld[3] = Type(-0.187034811718881);
    ld[4] = Type(-0.027983769416984);		ld[5] = Type(0.630880767929590);
    ld[6] = Type(0.714846570552542);		ld[7] = Type(0.230377813308855);

    hd.resize(8);
    hd[0] = Type(-0.230377813308855);		hd[1] = Type(0.714846570552542);
    hd[2] = Type(-0.630880767929590);		hd[3] = Type(-0.027983769416984);
    hd[4] = Type(0.187034811718881);		hd[5] = Type(0.030841381835987);
    hd[6] = Type(-0.032883011666983);		hd[7] = Type(-0.010597401784997);

    lr = flip(ld);
    hr = flip(hd);
}
/*
 * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), [email protected]
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 2 or any later version.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details. A copy of the GNU General Public License is available at:
 * http://www.fsf.org/licensing/licenses
 */


/*****************************************************************************
 *                               dwt-impl.h
 *
 * Implementation for DWT class.
 *
 * Zhang Ming, 2010-03, Xi'an Jiaotong University.
 *****************************************************************************/


/**
 * constructors and destructor
 */
template<typename Type>
DWT<Type>::DWT( const string &wname ) : waveType(wname)
{
    if( waveType != "db4" )
    {
        cerr << "No such wavelet type!" << endl;
        exit(1);
    }

    getFilter(wname);
}

template<typename Type>
DWT<Type>::~DWT()
{
}


/**
 * get coefficients of filter bank
 */
template<typename Type>
inline void DWT<Type>::getFilter( const string &wname )
{
    if( wname == "db4" )
        db4Coefs( ld, hd, lr, hr );
}


/**
 * Initializing the length of coefficients.
 */
template <typename Type>
void DWT<Type>::lengthInit( int sigLength, int J )
{
    lenInfo.resize(J+2);

    int na = sigLength,
        nd = 0,
        total = 0;

    lenInfo[0] = sigLength;
    for( int j=1; j<=J; ++j )
    {
        // detial's length at level j
        nd = (na+hd.dim()-1)/2;

        // approx's length at level j
        na = (na+ld.dim()-1)/2;

        lenInfo[j] = nd;
        total += nd;
    }
    total += na;

    lenInfo[J+1] = na;
}


/**
 * Get the jth level approximation coefficients.
 */
template <typename Type>
Vector<Type> DWT<Type>::getApprox( const Vector<Type> &coefs )
{
    int J = lenInfo.dim()-2;
    Vector<Type> approx(lenInfo[J+1]);

    int start = 0;
    for( int i=1; i<=J; ++i )
        start += lenInfo[i];

    for( int i=0; i<lenInfo[J+1]; ++i )
        approx[i] = coefs[i+start];

    return approx;
}


/**
 * Get the Jth level detial coefficients.
 */
template <typename Type>
Vector<Type> DWT<Type>::getDetial( const Vector<Type> &coefs, int j )
{
    if( (j < 1) || (j > lenInfo.dim()-2) )
    {
        cerr << "Invalid level for getting detial coefficients!" << endl;
        return Vector<Type>(0);
    }

    Vector<Type> detial(lenInfo[j]);

    int start = 0;
    for( int i=1; i<j; ++i )
        start += lenInfo[i];

    for( int i=0; i<lenInfo[j]; ++i )
        detial[i] = coefs[i+start];

    return detial;
}


/**
 * Set the Jth level approximation coefficients.
 */
template <typename Type>
void DWT<Type>::setApprox( const Vector<Type> &approx, Vector<Type> &coefs )
{
    int J = lenInfo.dim()-2;
    if( approx.dim() != lenInfo[J+1] )
    {
        cerr << "Invalid length for setting approximation coefficient!"
             << endl;
        return;
    }

    // the approximation's start position in the coe
    int start = 0;
    for( int i=1; i<=J; ++i )
        start += lenInfo[i];

    for( int i=0; i<lenInfo[J+1]; ++i )
        coefs[i+start] = approx[i];
}


/**
 * Set the jth level's detial coefficients.
 */
template <typename Type>
void DWT<Type>::setDetial( const Vector<Type> &detial, Vector<Type> &coefs,
                           int j )
{
    if( detial.dim() != lenInfo[j] )
    {
        cerr << "Invalid length for setting detial coefficients!" << endl;
        return;
    }

    // the jth level detial's start position in the coe
    int start = 0;
    for( int i=1; i<j; ++i )
        start += lenInfo[i];

    for( int i=0; i<lenInfo[j]; ++i )
        coefs[i+start] = detial[i];
}


/**
 * Doing J levels decompose for input signal "signal".
 */
template <typename Type>
Vector<Type> DWT<Type>::dwt( const Vector<Type> &signal, int J )
{
    if( (lenInfo.size() != J+2) || (lenInfo[0] != signal.size()) )
    {
        cout << "first" << endl;
        lengthInit( signal.size(), J );
    }
//        lengthInit( signal.size(), J );

    int total = 0;
    for( int i=1; i<=J+1; ++i )
        total += lenInfo[i];

    Vector<Type> coefs(total);
    Vector<Type> approx = signal;
    Vector<Type> tmp;

    for( int j=1; j<=J; ++j )
    {
        // high frequency filtering
        tmp = conv( approx, hd );

        // stored the downsampled signal
        setDetial( dyadDown(tmp,1), coefs, j );

        // low frequency filtering
        tmp = conv( approx, ld );
        approx = dyadDown( tmp, 1 );
    }
    setApprox( approx, coefs );

    return coefs;
}


/**
 * Recover the jth level approximation signal.
 * The default parameter is "j=0", which means recover the original signal.
 */
template <typename Type>
Vector<Type> DWT<Type>::idwt( const Vector<Type> &coefs, int j )
{
    if( coefs.size() != (sum(lenInfo)-lenInfo[0]) )
    {
        cerr << "Invalid wavelet coeffcients!" << endl;
        return Vector<Type>(0);
    }

    int J = lenInfo.dim() - 2;
    if( (j < 0) || (j > J) )
    {
        cerr << "Invalid level for reconstructing signal!" << endl;
        return Vector<Type>(0);
    }

    Vector<Type> signal = getApprox( coefs );
    Vector<Type> detial;

    for( int i=J; i>j; --i )
    {
        detial = getDetial( coefs, i );

        // upsampling
        signal = dyadUp( signal, 0 );
        detial = dyadUp( detial, 0 );

        // recover the jth approximation
        signal = conv( signal, lr ) + conv( detial, hr );

        // cut off
        signal = wkeep( signal,lenInfo[i-1],"center" );
    }

    return signal;
}

测试代码:

/*****************************************************************************
 *                               dwt_test.cpp
 *
 * Discrete wavelet transform testing.
 *
 * Zhang Ming, 2010-03, Xi'an Jiaotong University.
 *****************************************************************************/


#define BOUNDS_CHECK

#include <iostream>
#include <dwt.h>
#include <timing.h>


using namespace std;
using namespace splab;


typedef float   Type;
const   int     Ls = 1000;


int main()
{

	/******************************* [ signal ] ******************************/
	Vector<Type> s(Ls);
	for(int i=0; i<Ls; i++)
	{
		if(i<Ls/4)
			s[i] = 0.0;
		else if(i<2*Ls/4)
			s[i] = 1.0;
		else if(i<3*Ls/4)
			s[i] = 3.0;
		else
			s[i] = 0.0;
	}

	/******************************** [ DWT ] ********************************/
	int level = 3;
	DWT<Type> discreteWT("db4");
	Timing cnt;
	double runtime = 0.0;
	cout << "Taking discrete wavelet transform." << endl;
	cnt.start();
	Vector<Type> coefs = discreteWT.dwt( s, level );
	cnt.stop();
	runtime = cnt.read();
	cout << "The running time = " << runtime << " (s)" << endl << endl;

	/******************************** [ IDWT ] *******************************/
	level = 0;
    cout << "Taking inverse discrete wavelet transform." << endl;
	cnt.start();
	Vector<Type> x = discreteWT.idwt( coefs, level );
	cnt.stop();
	runtime = cnt.read();
	cout << "The running time = " << runtime << " (s)" << endl << endl;

	cout << "The relative error is : norm(s-x) / norm(s) = "
	     << norm(s-x)/norm(s) << endl << endl;

	return 0;
}

运行结果:

Taking discrete wavelet transform.
first
The running time = 0 (s)

Taking inverse discrete wavelet transform.
The running time = 0 (s)

The relative error is : norm(s-x) / norm(s) = 9.26354e-008


Process returned 0 (0x0)   execution time : 0.062 s
Press any key to continue.

你可能感兴趣的:(离散小波变换算法的C++实现)