最近用Opencv做图像处理需要用到离散小波变换,但是Opencv没有提供小波变换函数。本人能力有限,自己也没写。其实用MATLAB就是分分钟的事,但是对于图像处理,MATLAB倾向于搞研究, Opencv实用性更广。在网上找点资源,发现资源很多,但是代码单一,基本上就是这两种:
链接1:http://shijuanfeng.blogbus.com/logs/221385402.html
链接2: http://www.cnblogs.com/zhangzhi/archive/2009/09/19/1569888.html
链接1的程序好像有点小bug(评论这么说);本人也运行了程序,效果不是很理想。
链接2的程序应该是opencv1.0,作者用的IplImage数据类型,现在OpenCV升级到opencv3了。Mat数据类型比较流行。
对于离散小波变换的原理,链接3讲的很好,也有代码。对于初学者值得一看。
链接3: http://blog.csdn.net/u010006643/article/details/50493566
链接4的代码写得很好,通俗易懂,但只能进行一级小波分解。
链接4:http://answers.opencv.org/question/42273/wavelet-transform/
小波简介: 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
{/// 取出src中要处理的数据的一行
Mat oneRow = Mat::zeros( 1,col, src.type() );for ( int j=0; j {oneRow.at<float>(0,j) = src.at<float>(i,j);}oneRow = waveletDecompose( oneRow, lowFilter, highFilter );/// 将src这一行置为oneRow中的数据
for ( int j=0; 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 {/// 取出src数据的一行输入
Mat oneCol = Mat::zeros( row, 1, src.type() );for ( int i=0; i
{oneCol.at<float>(i,0) = dst.at<float>(i,j);}oneCol = ( waveletDecompose( oneCol.t(), lowFilter, highFilter ) ).t();for ( int i=0; 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 {/// 取出src数据的一行输入
Mat oneCol = Mat::zeros( row, 1, src.type() );for ( int i=0; i
{oneCol.at<float>(i,0) = src.at<float>(i,j);}oneCol = ( waveletReconstruct( oneCol.t(), lowFilter, highFilter ) ).t();for ( int i=0; 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
{/// 取出src中要处理的数据的一行
Mat oneRow = Mat::zeros( 1,col, src.type() );for ( int j=0; j {oneRow.at<float>(0,j) = dst.at<float>(i,j);}oneRow = waveletReconstruct( oneRow, lowFilter, highFilter );/// 将src这一行置为oneRow中的数据
for ( int j=0; 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 {_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 {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
//{
// Up1.at
( 0, cnt ) = src.at ( 0, i ); ///< 前一半 // Up2.at
( 0, cnt ) = src.at ( 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;
}
原文地址:http://blog.csdn.net/u012507022/article/details/50979009