小波变换 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;
}
小波变换 C++ opencv 实现的更多相关文章
- 基于opencv的小波变换
基于opencv的小波变换 提供函数DWT()和IDWT(),前者完成任意层次的小波变换,后者完成任意层次的小波逆变换.输入图像要求必须是单通道浮点图像,对图像大小也有要求(1层变换:w,h必须是2的 ...
- 基于opencv的小波变换代码和图像结果
#include "stdafx.h" #include "WaveTransform.h" #include <math.h> #include ...
- 学习OpenCV——Gabor函数的应用
原文:http://blog.csdn.net/yao_zhuang/article/details/2532279 下载cvgabor.cpp和cvgabor.h到你的C/C++工程目录下 注:在我 ...
- 【转】opencv检测运动物体的基础_特征提取
特征提取是计算机视觉和图像处理中的一个概念.它指的是使用计算机提取图像信息,决定每个图像的点是否属于一个图像特征.特征提取的结果是把图像上的点分为不同的子集,这些子集往往属于孤立的点.连续的曲线或者连 ...
- OpenCV——SIFT特征检测与匹配
SIFT特征和SURF特征比较 比较项目 SIFT SURF 尺度空间极值检测 使用高斯滤波器,根据不同尺度的高斯差(DOG)图像寻找局部极值 使用方形滤波器,利用海森矩阵的行列式值检测极值,并利用积 ...
- 基于OpenCV进行图像拼接原理解析和编码实现(提纲 代码和具体内容在课件中)
一.背景 1.1概念定义 我们这里想要实现的图像拼接,既不是如题图1和2这样的"图片艺术拼接",也不是如图3这样的"显示拼接",而是实现类似"BaiD ...
- 目标检测之harr---角点检测harr 的opencv实现
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/29356187 作者:毛星云(浅墨) ...
- OpenCV开发笔记(六十四):红胖子8分钟带你深入了解SURF特征点(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- C++vector and opencv Mat
转载:https://blog.csdn.net/u012507022/article/details/50979011?utm_source=blogxgwz5 最近在写Opencv程序,用到离散小 ...
随机推荐
- 瀑布流AJAX无刷新加载数据列表--当页面滚动到Id时再继续加载数据
瀑布流加载显示数据,在当下已经用的很普遍,尤其是我们在做网上商城时,在产品列表页面已经被普遍使用. 对于实现瀑布流布局的解决方案主要有以下两种方式: 1.对每一条显示数据使用绝对定位+浮动的方式,这样 ...
- oh-my-zsh配置 alias 指定指令别名
# vim ~/.zshrc alias ydocx="/Users/wanglili/work/mfe/ydoc/bin/ydoc" # source ~/.zshrc
- asp.net分页控件库
AspNetPager分页控件 AspNetPager分页控件解决了分页中的很多问题,直接采用该控件进行分页处理,会将繁琐的分页工作变得简单化,下面是我如何使用AspNetPager控件进行分页处理的 ...
- linux下安装apache2.4
linux安装Apache2步骤如下 apr 下载地址 http://mirrors.cnnic.cn/apache//apr/apr-1.5.2.tar.gz 安装过程 tar -xzvf apr- ...
- §12 循环101-while循环
§12 循环101-while循环 While和for具有一定的可替换性.语法如下: while test body continue终止当次循环,break退出整个循环. 注意while之后要用 ...
- DevExpres.XtraLayout控件运行时动态设置数据项
问题分析: 通常.我们使用XtraLayout控件,是需要做以下的几个步骤来实现的: 1. 在窗体上拖拉一个 LayoutControl控件,设置它的填充属性: 2. 拖拉一些常规编辑控件到Lay ...
- jasper2
package jasper; import java.io.File;import java.io.FileOutputStream;import java.io.OutputStream;impo ...
- 网易游戏QA工程师笔试回忆-2012.9【个人题解】
========================转帖======================== 网易游戏QA工程师笔试回忆-2012.9 刚刚从武大回来,趁热回忆下题目,给以后的XDJMs参考. ...
- iOS开发——文本高度
1.简单的计算文本高度 // 要计算的文本内容 NSString *testString = @"刘成利,软件工程专业毕业,iOS开发者,目前工作于北京,在证券金融领域从事iOS App开发 ...
- WPF动画之关键帧动画(2)
XAML代码: <Window x:Class="关键帧动画.MainWindow" xmlns="http://schemas.microsoft.com/win ...