SSE2实现HAAR小波变换(dwt2与idwt2)
wiki链接:http://en.wikipedia.org/wiki/Haar_wavelet
可用SSE2实现HAAR小波变换,达到实时,关于HAAR小波的介绍可参考以上维基链接
参考MATLAB中dwt2与idwt2的函数原型,基于OpenCV的框架进行了汇编优化实现
HAAR小波也可用于图像的压缩,将CH,CV,CD中的分量值小于某一阈值则归为0,从而这三个矩阵将成为稀疏矩阵(Sparse Matrix),反变换后的图像的质量将取决于选择阈值的大小。
实际实现时,可选择使用浮点数(单精度或双精度)进行矩阵计算,使用整数计算能得到更快的速度但不能进行完整的压缩与解压缩。
附代码:
- inline void dwt2_row(__out double* ca0,
- __out double* ch0,
- __out double* cv0,
- __out double* cd0,
- __in unsigned char* row0,
- __in unsigned char* row1,
- __in int col)
- {
- __asm
- {
- mov eax_ptr, ca0;
- mov ebx_ptr, ch0;
- mov ecx_ptr, cv0;
- mov edx_ptr, cd0;
- mov esi_ptr, row0;
- mov edi_ptr, row1;
- pxor xmm3, xmm3;
- movapd xmm7, g_halfd;
- sub col, 4;
- jl loop_2;
- loop_4:
- movd xmm1, [esi_ptr];
- movd xmm5, [edi_ptr];
- punpcklbw xmm1, xmm3;
- punpcklbw xmm5, xmm3;
- punpcklwd xmm1, xmm3;
- punpcklwd xmm5, xmm3;
- cvtdq2pd xmm0, xmm1;
- cvtdq2pd xmm4, xmm5;
- shufpd xmm1, xmm1, 1;
- shufpd xmm5, xmm5, 1;
- cvtdq2pd xmm1, xmm1;
- cvtdq2pd xmm5, xmm5;
- addpd xmm4, xmm0;
- addpd xmm5, xmm1;
- mulpd xmm4, xmm7;
- mulpd xmm5, xmm7;
- subpd xmm0, xmm4;
- subpd xmm1, xmm5;
- movapd xmm6, xmm4;
- movapd xmm2, xmm0;
- shufpd xmm4, xmm5, 0;
- shufpd xmm6, xmm5, 3;
- shufpd xmm0, xmm1, 0;
- shufpd xmm2, xmm1, 3;
- addpd xmm6, xmm4;
- addpd xmm2, xmm0;
- mulpd xmm6, xmm7;
- mulpd xmm2, xmm7;
- subpd xmm4, xmm6;
- subpd xmm0, xmm2;
- movupd [eax_ptr], xmm6;
- movupd [ebx_ptr], xmm4;
- movupd [ecx_ptr], xmm2;
- movupd [edx_ptr], xmm0;
- add esi_ptr, 4;
- add edi_ptr, 4;
- add eax_ptr, 0x10;
- add ebx_ptr, 0x10;
- add ecx_ptr, 0x10;
- add edx_ptr, 0x10;
- sub col, 4;
- jge loop_4;
- loop_2:
- cmp col, -2;
- jl loop_end;
- pinsrw xmm0, [esi_ptr], 0;
- pinsrw xmm4, [edi_ptr], 0;
- punpcklbw xmm0, xmm3;
- punpcklbw xmm4, xmm3;
- punpcklwd xmm0, xmm3;
- punpcklwd xmm4, xmm3;
- cvtdq2pd xmm0, xmm0;
- cvtdq2pd xmm4, xmm4;
- addpd xmm4, xmm0;
- mulpd xmm4, xmm7;
- subpd xmm0, xmm4;
- movapd xmm5, xmm4;
- shufpd xmm4, xmm0, 0;
- shufpd xmm5, xmm0, 3;
- addpd xmm5, xmm4;
- mulpd xmm5, xmm7;
- subpd xmm4, xmm5;
- movsd [eax_ptr], xmm5;
- shufpd xmm5, xmm5, 1;
- movsd [ebx_ptr], xmm4;
- shufpd xmm4, xmm4, 1;
- movsd [ecx_ptr], xmm5;
- movsd [edx_ptr], xmm4;
- loop_end:
- }
- }
- inline void idwt2_row(__out unsigned char* row0,
- __out unsigned char* row1,
- __in double* ca0,
- __in double* ch0,
- __in double* cv0,
- __in double* cd0,
- __in int col)
- {
- __asm
- {
- mov eax_ptr, ca0;
- mov ebx_ptr, ch0;
- mov ecx_ptr, cv0;
- mov edx_ptr, cd0;
- mov esi_ptr, row0;
- mov edi_ptr, row1;
- sub col, 4;
- jl loop_2;
- loop_4:
- movupd xmm0, [eax_ptr];
- movupd xmm1, [ebx_ptr];
- movupd xmm4, [ecx_ptr];
- movupd xmm5, [edx_ptr];
- addpd xmm1, xmm0;
- addpd xmm5, xmm4;
- addpd xmm0, xmm0;
- addpd xmm4, xmm4;
- subpd xmm0, xmm1;
- subpd xmm4, xmm5;
- movapd xmm2, xmm1;
- movapd xmm6, xmm5;
- shufpd xmm1, xmm0, 0;
- shufpd xmm2, xmm0, 3;
- shufpd xmm5, xmm4, 0;
- shufpd xmm6, xmm4, 3;
- addpd xmm5, xmm1;
- addpd xmm6, xmm2;
- addpd xmm1, xmm1;
- addpd xmm2, xmm2;
- subpd xmm1, xmm5;
- subpd xmm2, xmm6;
- cvttpd2dq xmm5, xmm5;
- cvttpd2dq xmm6, xmm6;
- cvttpd2dq xmm1, xmm1;
- cvttpd2dq xmm2, xmm2;
- shufpd xmm5, xmm6, 0;
- shufpd xmm1, xmm2, 0;
- packssdw xmm5, xmm1;
- packuswb xmm5, xmm5;
- pshufd xmm1, xmm5, 1;
- movd [esi_ptr], xmm5;
- movd [edi_ptr], xmm1;
- add esi_ptr, 4;
- add edi_ptr, 4;
- add eax_ptr, 0x10;
- add ebx_ptr, 0x10;
- add ecx_ptr, 0x10;
- add edx_ptr, 0x10;
- sub col, 4;
- jge loop_4;
- loop_2:
- cmp col, -2;
- jl loop_end;
- movsd xmm0, [eax_ptr];
- movsd xmm1, [ebx_ptr];
- movsd xmm4, [ecx_ptr];
- movsd xmm5, [edx_ptr];
- addpd xmm1, xmm0;
- addpd xmm5, xmm4;
- addpd xmm0, xmm0;
- addpd xmm4, xmm4;
- subpd xmm0, xmm1;
- subpd xmm4, xmm5;
- shufpd xmm1, xmm0, 0;
- shufpd xmm5, xmm4, 0;
- addpd xmm5, xmm1;
- addpd xmm1, xmm1;
- subpd xmm1, xmm5;
- cvttpd2dq xmm5, xmm5;
- cvttpd2dq xmm1, xmm1;
- packssdw xmm5, xmm1;
- packuswb xmm5, xmm5;
- movd eax_ptr, xmm5;
- mov [esi_ptr], ax;
- shr eax_ptr, 16;
- stosw;
- loop_end:
- }
- }
- inline void dwt2(__out cv::Mat& CA,
- __out cv::Mat& CH,
- __out cv::Mat& CV,
- __out cv::Mat& CD,
- __in cv::Mat const& I)
- {
- if(CA.type() != CV_64FC1 || CH.type() != CV_64FC1 || CV.type() != CV_64FC1 || CD.type() != CV_64FC1 || I.channels() != 1)
- return;
- double* ca = reinterpret_cast<double*>(CA.data);
- double* ch = reinterpret_cast<double*>(CH.data);
- double* cv = reinterpret_cast<double*>(CV.data);
- double* cd = reinterpret_cast<double*>(CD.data);
- unsigned char* row = reinterpret_cast<unsigned char*>(I.data);
- for(int i=0; i<I.rows; i+=2)
- {
- dwt2_row(ca, ch, cv, cd, row, row+I.cols, I.cols);
- ca += CA.cols;
- ch += CH.cols;
- cv += CV.cols;
- cd += CD.cols;
- row += I.cols*2;
- }
- }
- inline void idwt2(__out cv::Mat& I,
- __in cv::Mat const& CA,
- __in cv::Mat const& CH,
- __in cv::Mat const& CV,
- __in cv::Mat const& CD)
- {
- if(CA.type() != CV_64FC1 || CH.type() != CV_64FC1 || CV.type() != CV_64FC1 || CD.type() != CV_64FC1 || I.channels() != 1)
- return;
- double* ca = reinterpret_cast<double*>(CA.data);
- double* ch = reinterpret_cast<double*>(CH.data);
- double* cv = reinterpret_cast<double*>(CV.data);
- double* cd = reinterpret_cast<double*>(CD.data);
- unsigned char* row = reinterpret_cast<unsigned char*>(I.data);
- for(int i=0; i<I.rows; i+=2)
- {
- idwt2_row(row, row+I.cols, ca, ch, cv, cd, I.cols);
- ca += CA.cols;
- ch += CH.cols;
- cv += CV.cols;
- cd += CD.cols;
- row += I.cols*2;
- }
- }
版权归作者所有,转载请注明出处!
SSE2实现HAAR小波变换(dwt2与idwt2)相关推荐
- haar小波变换学习笔记
本篇很大一部分内容借鉴了篇末所引用的优质博客~~ 小波可以认为是一个带通滤波器,只允许频率和小波基函数频率相近的信号通过.小波变换的基本思想是用一组小波函数和基函数表示一个函数或者信号. haar小波 ...
- Haar小波变换的快速实现
Haar小波变换的快速实现 2014年3月12日renjihe发表评论阅读评论 先举个例子,有a=[100,12,43,39]四个数,并使用b[4]数组来保存结果. 一级Haar小波变换的结果为: b ...
- 使用CUDA计算Haar小波变换
在<Haar小波变换的快速实现>一文里我们提到了Haar小波变换的计算,在这里我们使用CUDA实现文中提到的计算方式. 01 __global__ void 02 _cuda_haar(f ...
- Haar小波变换基本原理
另外参见俄罗斯写的http://www.codeproject.com/Articles/22243/Real-Time-Object-Tracker-in-C Haar小波在图像处理和数字水印等方面 ...
- 二维图像haar小波变换的分解与重构
二维图像haar小波变换的分解与重构 二维离散小波的理论推导和一维小波类似,但是以其尺度函数生成的尺度函数集作为标准正交基的尺度空间Vi的正交补空间Wi不能直接得到,而是可以证明,正交补空间Wi是由三 ...
- 图像Haar小波变换
说起小波变换就需要提起傅里叶变换.傅里叶变换就是把波进行分解,可以认为任意一个周期波都可以有足够多的正弦(余弦)波组成,这里足够多的正弦波对应的频率不同,把这些足够的正弦波放在频域中,就是傅里叶变换, ...
- 哈尔(Haar)小波变换的原理及opencv源代码
1. 小波分析 小波分析是对傅里叶变换的继承,总结和重大突破.小波分析的优势在于可以同时进行时频域分析,比傅里叶变换更适合处理非平稳信号. 小波分析所用的波称为小波,小波的能量有限,有限长且会衰减,集 ...
- 一维的Haar小波变换
本文转载自:http://blog.csdn.net/liulina603/article/details/8649339 小波变换的基本思想是用一组小波函数或者基函数表示一个函数或者信号,例如图像信 ...
- Haar小波变换代码实现
代码1:以图像的形式显示. # include<opencv2/opencv.hpp> # include<iostream> using namespace std; usi ...
最新文章
- 卷积Convolution
- 35张图,看懂肠道和大脑的魔性关系,绝对涨知识!
- selenium--字符串/整型问题Can't convert 'int' object to str implicitly提示解决方法
- Docker之镜像、容器、仓库概念
- 用Python求出:1到某个数的奇数序列里一共出现了多少个3
- gifcam录制动态图后导入photoshop出现透明格子怎么办?
- 卡尔曼滤波与组合导航原理_卫星知识科普:一种基于卫星共视的卡尔曼滤波算法!...
- Java基础知识(二)之控制语句
- html5难点,学习HTML5的难点是什么?
- python 判断该地址 文件创建时间2020年10月14日14时25分32秒 文件最后一次访问时间 文件最后一次修改时间
- 201521123061 《Java程序设计》第六周学习总结
- 分享一个echart 广州地图的demo
- 安装Linux操作系统Ubuntu 22.04 LTS并配置拨号连接
- 开发谷歌浏览器插件会上瘾,搞了一个JSONViewer,一个页面格式化多条JSON,提升工作效率...
- SpringBoot+Dubbo整合
- 2022-03-30 StackOverflowError与OutOfMemoryError详解
- 二十六、 对偶问题(※※※)
- ansi是什么编码_ANSI的完整形式是什么?
- QS世界大学 计算机科学与信息系统学科排名!中国高校表现如何?
- 计算机专业研究生西安就业,计算机专业需要考研吗?毕业之后该怎么发展?