博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
小波变换 C++ opencv 实现
阅读量:4959 次
发布时间:2019-06-12

本文共 5954 字,大约阅读时间需要 19 分钟。

小波简介: 

 

源码:

 
///  小波变换
Mat WDT( const Mat &_src, const string _wname, const int _level )const
{
int reValue = THID_ERR_NONE;
Mat src = Mat_
(_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
(0,j) = src.at
(i,j);
}
oneRow = waveletDecompose( oneRow, lowFilter, highFilter );
/// 将src这一行置为oneRow中的数据
for ( int j=0; j
{
dst.at
(i,j) = oneRow.at
(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
(i,0) = dst.at
(i,j);
}
oneCol = ( waveletDecompose( oneCol.t(), lowFilter, highFilter ) ).t();
 
for ( int i=0; i
{
dst.at
(i,j) = oneCol.at
(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_
(_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
(i,0) = src.at
(i,j);
}
oneCol = ( waveletReconstruct( oneCol.t(), lowFilter, highFilter ) ).t();
 
for ( int i=0; i
{
dst.at
(i,j) = oneCol.at
(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
(0,j) = dst.at
(i,j);
}
oneRow = waveletReconstruct( oneRow, lowFilter, highFilter );
/// 将src这一行置为oneRow中的数据
for ( int j=0; j
{
dst.at
(i,j) = oneRow.at
(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
(0, 0) = 1/sqrtf(N);
_lowFilter.at
(0, 1) = 1/sqrtf(N);
 
_highFilter.at
(0, 0) = -1/sqrtf(N);
_highFilter.at
(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
(0, i) = l[i];
_highFilter.at
(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_
(_src);
 
int D = src.cols;
 
Mat &lowFilter = Mat_
(_lowFilter);
Mat &highFilter = Mat_
(_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
(0, i) = downDst1.at
( 0, i );
src.at
(0, i+D/2) = downDst2.at
( 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_
(_src);
 
int D = src.cols;
 
Mat &lowFilter = Mat_
(_lowFilter);
Mat &highFilter = Mat_
(_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;
 
}

转载于:https://www.cnblogs.com/yymn/p/4589615.html

你可能感兴趣的文章
通过用户模型,对数据库进行增删改查操作。
查看>>
去除数组中重复的元素
查看>>
Nginx配置文件nginx.conf中文详解(转)
查看>>
POJ 1988 Cube Stacking
查看>>
POJ 1308 Is It A Tree?(并查集)
查看>>
N进制到M进制的转换问题
查看>>
Android------三种监听OnTouchListener、OnLongClickListener同时实现即其中返回值true或者false的含义...
查看>>
MATLAB实现多元线性回归预测
查看>>
Mac xcode 配置OpenGL
查看>>
利用sed把一行的文本文件改成每句一行
查看>>
使用Asyncio的Coroutine来实现一个有限状态机
查看>>
Android应用开发:核心技术解析与最佳实践pdf
查看>>
python——爬虫
查看>>
2.2 标识符
查看>>
孤荷凌寒自学python第五天初识python的列表
查看>>
孤荷凌寒自学python第五十八天成功使用python来连接上远端MongoDb数据库
查看>>
求一个字符串中最长回文子串的长度(承接上一个题目)
查看>>
简单权限管理系统原理浅析
查看>>
springIOC第一个课堂案例的实现
查看>>
求输入成绩的平均分
查看>>