zoukankan      html  css  js  c++  java
  • 小波变换 C++ opencv 实现

    小波变换 C++ opencv 实现

    小波简介: http://www.blogbus.com/shijuanfeng-logs/221293135.html

    源码:

     
    ///  小波变换
    Mat WDT( const Mat &_src, const string _wname, const int _level )const
    {
        int reValue = THID_ERR_NONE;
        Mat src = Mat_<float>(_src);
        Mat dst = Mat::zeros( src.rows, src.cols, src.type() ); 
        int N = src.rows;
        int D = src.cols;
     
        /// 高通低通滤波器
        Mat lowFilter; 
        Mat highFilter;
        wavelet( _wname, lowFilter, highFilter );
     
        /// 小波变换
        int t=1;
        int row = N;
        int col = D;
     
        while( t<=_level )
        {
            ///先进行行小波变换
            for( int i=0; i<row; i++ ) 
            {
                /// 取出src中要处理的数据的一行
                Mat oneRow = Mat::zeros( 1,col, src.type() );
                for ( int j=0; j<col; j++ )
                {
                    oneRow.at<float>(0,j) = src.at<float>(i,j);
                }
                oneRow = waveletDecompose( oneRow, lowFilter, highFilter );
                /// 将src这一行置为oneRow中的数据
                for ( int j=0; j<col; j++ )
                {
                    dst.at<float>(i,j) = oneRow.at<float>(0,j);
                }
            }
     
    #if 0
            //normalize( dst, dst, 0, 255, NORM_MINMAX );
            IplImage dstImg1 = IplImage(dst); 
            cvSaveImage( "dst.jpg", &dstImg1 );
    #endif
            /// 小波列变换
            for ( int j=0; j<col; j++ )
            {
                /// 取出src数据的一行输入
                Mat oneCol = Mat::zeros( row, 1, src.type() );
                for ( int i=0; i<row; i++ )
                {
                    oneCol.at<float>(i,0) = dst.at<float>(i,j);
                }
                oneCol = ( waveletDecompose( oneCol.t(), lowFilter, highFilter ) ).t();
            
                for ( int i=0; i<row; i++ )
                {
                    dst.at<float>(i,j) = oneCol.at<float>(i,0);
                }
            }
     
    #if 0
            //normalize( dst, dst, 0, 255, NORM_MINMAX );
            IplImage dstImg2 = IplImage(dst); 
            cvSaveImage( "dst.jpg", &dstImg2 );
    #endif
     
            /// 更新
            row /= 2;
            col /=2;
            t++;
            src = dst;
        }
     
        return dst;
    }
     
    ///  小波逆变换
    Mat IWDT( const Mat &_src, const string _wname, const int _level )const
    {
        int reValue = THID_ERR_NONE;
        Mat src = Mat_<float>(_src);
        Mat dst = Mat::zeros( src.rows, src.cols, src.type() ); 
        int N = src.rows;
        int D = src.cols;
     
        /// 高通低通滤波器
        Mat lowFilter; 
        Mat highFilter;
        wavelet( _wname, lowFilter, highFilter );
     
        /// 小波变换
        int t=1;
        int row = N/std::pow( 2., _level-1);
        int col = D/std::pow(2., _level-1);
     
        while ( row<=N && col<=D )
        {
            /// 小波列逆变换
            for ( int j=0; j<col; j++ )
            {
                /// 取出src数据的一行输入
                Mat oneCol = Mat::zeros( row, 1, src.type() );
                for ( int i=0; i<row; i++ )
                {
                    oneCol.at<float>(i,0) = src.at<float>(i,j);
                }
                oneCol = ( waveletReconstruct( oneCol.t(), lowFilter, highFilter ) ).t();
     
                for ( int i=0; i<row; i++ )
                {
                    dst.at<float>(i,j) = oneCol.at<float>(i,0);
                }
            }
     
    #if 0
            //normalize( dst, dst, 0, 255, NORM_MINMAX );
            IplImage dstImg2 = IplImage(dst); 
            cvSaveImage( "dst.jpg", &dstImg2 );
    #endif
            ///行小波逆变换
            for( int i=0; i<row; i++ ) 
            {
                /// 取出src中要处理的数据的一行
                Mat oneRow = Mat::zeros( 1,col, src.type() );
                for ( int j=0; j<col; j++ )
                {
                    oneRow.at<float>(0,j) = dst.at<float>(i,j);
                }
                oneRow = waveletReconstruct( oneRow, lowFilter, highFilter );
                /// 将src这一行置为oneRow中的数据
                for ( int j=0; j<col; j++ )
                {
                    dst.at<float>(i,j) = oneRow.at<float>(0,j);
                }
            }
     
    #if 0
            //normalize( dst, dst, 0, 255, NORM_MINMAX );
            IplImage dstImg1 = IplImage(dst); 
            cvSaveImage( "dst.jpg", &dstImg1 );
    #endif
     
            row *= 2;
            col *= 2;
            src = dst;
        }
     
        return dst;
    }
     
     
    ////////////////////////////////////////////////////////////////////////////////////////////
     
    /// 调用函数
     
    /// 生成不同类型的小波,现在只有haar,sym2
    void wavelet( const string _wname, Mat &_lowFilter, Mat &_highFilter )const
    {
        if ( _wname=="haar" || _wname=="db1" )
        {
            int N = 2;
            _lowFilter = Mat::zeros( 1, N, CV_32F );
            _highFilter = Mat::zeros( 1, N, CV_32F );
            
            _lowFilter.at<float>(0, 0) = 1/sqrtf(N); 
            _lowFilter.at<float>(0, 1) = 1/sqrtf(N); 
     
            _highFilter.at<float>(0, 0) = -1/sqrtf(N); 
            _highFilter.at<float>(0, 1) = 1/sqrtf(N); 
        }
        if ( _wname =="sym2" )
        {
            int N = 4;
            float h[] = {-0.483, 0.836, -0.224, -0.129 };
            float l[] = {-0.129, 0.224,    0.837, 0.483 };
     
            _lowFilter = Mat::zeros( 1, N, CV_32F );
            _highFilter = Mat::zeros( 1, N, CV_32F );
     
            for ( int i=0; i<N; i++ )
            {
                _lowFilter.at<float>(0, i) = l[i]; 
                _highFilter.at<float>(0, i) = h[i]; 
            }
     
        }
    }
     
    /// 小波分解
    Mat waveletDecompose( const Mat &_src, const Mat &_lowFilter, const Mat &_highFilter )const
    {
        assert( _src.rows==1 && _lowFilter.rows==1 && _highFilter.rows==1 );
        assert( _src.cols>=_lowFilter.cols && _src.cols>=_highFilter.cols );
        Mat &src = Mat_<float>(_src);
     
        int D = src.cols;
        
        Mat &lowFilter = Mat_<float>(_lowFilter);
        Mat &highFilter = Mat_<float>(_highFilter);
     
     
        /// 频域滤波,或时域卷积;ifft( fft(x) * fft(filter)) = cov(x,filter) 
        Mat dst1 = Mat::zeros( 1, D, src.type() );
        Mat dst2 = Mat::zeros( 1, D, src.type()  );
     
        filter2D( src, dst1, -1, lowFilter );
        filter2D( src, dst2, -1, highFilter );
     
     
        /// 下采样
        Mat downDst1 = Mat::zeros( 1, D/2, src.type() );
        Mat downDst2 = Mat::zeros( 1, D/2, src.type() );
     
        resize( dst1, downDst1, downDst1.size() );
        resize( dst2, downDst2, downDst2.size() );
     
     
        /// 数据拼接
        for ( int i=0; i<D/2; i++ )
        {
            src.at<float>(0, i) = downDst1.at<float>( 0, i );
            src.at<float>(0, i+D/2) = downDst2.at<float>( 0, i );
        }
     
        return src;
    }
     
    /// 小波重建
    Mat waveletReconstruct( const Mat &_src, const Mat &_lowFilter, const Mat &_highFilter )const
    {
        assert( _src.rows==1 && _lowFilter.rows==1 && _highFilter.rows==1 );
        assert( _src.cols>=_lowFilter.cols && _src.cols>=_highFilter.cols );
        Mat &src = Mat_<float>(_src);
     
        int D = src.cols;
     
        Mat &lowFilter = Mat_<float>(_lowFilter);
        Mat &highFilter = Mat_<float>(_highFilter);
     
        /// 插值;
        Mat Up1 = Mat::zeros( 1, D, src.type() );
        Mat Up2 = Mat::zeros( 1, D, src.type() );
     
        /// 插值为0
        //for ( int i=0, cnt=1; i<D/2; i++,cnt+=2 )
        //{
        //    Up1.at<float>( 0, cnt ) = src.at<float>( 0, i );     ///< 前一半
        //    Up2.at<float>( 0, cnt ) = src.at<float>( 0, i+D/2 ); ///< 后一半
        //}
     
        /// 线性插值
        Mat roi1( src, Rect(0, 0, D/2, 1) );
        Mat roi2( src, Rect(D/2, 0, D/2, 1) );
        resize( roi1, Up1, Up1.size(), 0, 0, INTER_CUBIC );
        resize( roi2, Up2, Up2.size(), 0, 0, INTER_CUBIC );
     
        /// 前一半低通,后一半高通
        Mat dst1 = Mat::zeros( 1, D, src.type() );
        Mat dst2= Mat::zeros( 1, D, src.type() );
        filter2D( Up1, dst1, -1, lowFilter );
        filter2D( Up2, dst2, -1, highFilter );
     
        /// 结果相加
        dst1 = dst1 + dst2;
     
        return dst1;
     
    }
  • 相关阅读:
    【BZOJ】1552/3506 [Cerc2007]robotic sort
    【BZOJ】1014 [JSOI2008]火星人prefix
    【BZOJ】1500: [NOI2005]维修数列
    【51NOD-0】1046 A^B Mod C
    【51NOD-0】1019 逆序数
    【51NOD-0】1018 排序
    【51NOD-0】1012 最小公倍数LCM
    The Grove(poj 3182)
    Iahub and Permutations(codeforces 314c)
    多边形之战(bzoj 2927)
  • 原文地址:https://www.cnblogs.com/yymn/p/4589615.html
Copyright © 2011-2022 走看看