wiki链接:http://en.wikipedia.org/wiki/Haar_wavelet

可用SSE2实现HAAR小波变换,达到实时,关于HAAR小波的介绍可参考以上维基链接

参考MATLAB中dwt2与idwt2的函数原型,基于OpenCV的框架进行了汇编优化实现

HAAR小波也可用于图像的压缩,将CH,CV,CD中的分量值小于某一阈值则归为0,从而这三个矩阵将成为稀疏矩阵(Sparse Matrix),反变换后的图像的质量将取决于选择阈值的大小。

实际实现时,可选择使用浮点数(单精度或双精度)进行矩阵计算,使用整数计算能得到更快的速度但不能进行完整的压缩与解压缩。

附代码:

[cpp] view plain copy
  1. inline void dwt2_row(__out double* ca0,
  2. __out double* ch0,
  3. __out double* cv0,
  4. __out double* cd0,
  5. __in unsigned char* row0,
  6. __in unsigned char* row1,
  7. __in int col)
  8. {
  9. __asm
  10. {
  11. mov         eax_ptr, ca0;
  12. mov         ebx_ptr, ch0;
  13. mov         ecx_ptr, cv0;
  14. mov         edx_ptr, cd0;
  15. mov         esi_ptr, row0;
  16. mov         edi_ptr, row1;
  17. pxor        xmm3, xmm3;
  18. movapd      xmm7, g_halfd;
  19. sub         col, 4;
  20. jl          loop_2;
  21. loop_4:
  22. movd        xmm1, [esi_ptr];
  23. movd        xmm5, [edi_ptr];
  24. punpcklbw   xmm1, xmm3;
  25. punpcklbw   xmm5, xmm3;
  26. punpcklwd   xmm1, xmm3;
  27. punpcklwd   xmm5, xmm3;
  28. cvtdq2pd    xmm0, xmm1;
  29. cvtdq2pd    xmm4, xmm5;
  30. shufpd      xmm1, xmm1, 1;
  31. shufpd      xmm5, xmm5, 1;
  32. cvtdq2pd    xmm1, xmm1;
  33. cvtdq2pd    xmm5, xmm5;
  34. addpd       xmm4, xmm0;
  35. addpd       xmm5, xmm1;
  36. mulpd       xmm4, xmm7;
  37. mulpd       xmm5, xmm7;
  38. subpd       xmm0, xmm4;
  39. subpd       xmm1, xmm5;
  40. movapd      xmm6, xmm4;
  41. movapd      xmm2, xmm0;
  42. shufpd      xmm4, xmm5, 0;
  43. shufpd      xmm6, xmm5, 3;
  44. shufpd      xmm0, xmm1, 0;
  45. shufpd      xmm2, xmm1, 3;
  46. addpd       xmm6, xmm4;
  47. addpd       xmm2, xmm0;
  48. mulpd       xmm6, xmm7;
  49. mulpd       xmm2, xmm7;
  50. subpd       xmm4, xmm6;
  51. subpd       xmm0, xmm2;
  52. movupd      [eax_ptr], xmm6;
  53. movupd      [ebx_ptr], xmm4;
  54. movupd      [ecx_ptr], xmm2;
  55. movupd      [edx_ptr], xmm0;
  56. add         esi_ptr, 4;
  57. add         edi_ptr, 4;
  58. add         eax_ptr, 0x10;
  59. add         ebx_ptr, 0x10;
  60. add         ecx_ptr, 0x10;
  61. add         edx_ptr, 0x10;
  62. sub         col, 4;
  63. jge         loop_4;
  64. loop_2:
  65. cmp         col, -2;
  66. jl          loop_end;
  67. pinsrw      xmm0, [esi_ptr], 0;
  68. pinsrw      xmm4, [edi_ptr], 0;
  69. punpcklbw   xmm0, xmm3;
  70. punpcklbw   xmm4, xmm3;
  71. punpcklwd   xmm0, xmm3;
  72. punpcklwd   xmm4, xmm3;
  73. cvtdq2pd    xmm0, xmm0;
  74. cvtdq2pd    xmm4, xmm4;
  75. addpd       xmm4, xmm0;
  76. mulpd       xmm4, xmm7;
  77. subpd       xmm0, xmm4;
  78. movapd      xmm5, xmm4;
  79. shufpd      xmm4, xmm0, 0;
  80. shufpd      xmm5, xmm0, 3;
  81. addpd       xmm5, xmm4;
  82. mulpd       xmm5, xmm7;
  83. subpd       xmm4, xmm5;
  84. movsd       [eax_ptr], xmm5;
  85. shufpd      xmm5, xmm5, 1;
  86. movsd       [ebx_ptr], xmm4;
  87. shufpd      xmm4, xmm4, 1;
  88. movsd       [ecx_ptr], xmm5;
  89. movsd       [edx_ptr], xmm4;
  90. loop_end:
  91. }
  92. }
  93. inline void idwt2_row(__out unsigned char* row0,
  94. __out unsigned char* row1,
  95. __in double* ca0,
  96. __in double* ch0,
  97. __in double* cv0,
  98. __in double* cd0,
  99. __in int col)
  100. {
  101. __asm
  102. {
  103. mov         eax_ptr, ca0;
  104. mov         ebx_ptr, ch0;
  105. mov         ecx_ptr, cv0;
  106. mov         edx_ptr, cd0;
  107. mov         esi_ptr, row0;
  108. mov         edi_ptr, row1;
  109. sub         col, 4;
  110. jl          loop_2;
  111. loop_4:
  112. movupd      xmm0, [eax_ptr];
  113. movupd      xmm1, [ebx_ptr];
  114. movupd      xmm4, [ecx_ptr];
  115. movupd      xmm5, [edx_ptr];
  116. addpd       xmm1, xmm0;
  117. addpd       xmm5, xmm4;
  118. addpd       xmm0, xmm0;
  119. addpd       xmm4, xmm4;
  120. subpd       xmm0, xmm1;
  121. subpd       xmm4, xmm5;
  122. movapd      xmm2, xmm1;
  123. movapd      xmm6, xmm5;
  124. shufpd      xmm1, xmm0, 0;
  125. shufpd      xmm2, xmm0, 3;
  126. shufpd      xmm5, xmm4, 0;
  127. shufpd      xmm6, xmm4, 3;
  128. addpd       xmm5, xmm1;
  129. addpd       xmm6, xmm2;
  130. addpd       xmm1, xmm1;
  131. addpd       xmm2, xmm2;
  132. subpd       xmm1, xmm5;
  133. subpd       xmm2, xmm6;
  134. cvttpd2dq   xmm5, xmm5;
  135. cvttpd2dq   xmm6, xmm6;
  136. cvttpd2dq   xmm1, xmm1;
  137. cvttpd2dq   xmm2, xmm2;
  138. shufpd      xmm5, xmm6, 0;
  139. shufpd      xmm1, xmm2, 0;
  140. packssdw    xmm5, xmm1;
  141. packuswb    xmm5, xmm5;
  142. pshufd      xmm1, xmm5, 1;
  143. movd        [esi_ptr], xmm5;
  144. movd        [edi_ptr], xmm1;
  145. add         esi_ptr, 4;
  146. add         edi_ptr, 4;
  147. add         eax_ptr, 0x10;
  148. add         ebx_ptr, 0x10;
  149. add         ecx_ptr, 0x10;
  150. add         edx_ptr, 0x10;
  151. sub         col, 4;
  152. jge         loop_4;
  153. loop_2:
  154. cmp         col, -2;
  155. jl          loop_end;
  156. movsd       xmm0, [eax_ptr];
  157. movsd       xmm1, [ebx_ptr];
  158. movsd       xmm4, [ecx_ptr];
  159. movsd       xmm5, [edx_ptr];
  160. addpd       xmm1, xmm0;
  161. addpd       xmm5, xmm4;
  162. addpd       xmm0, xmm0;
  163. addpd       xmm4, xmm4;
  164. subpd       xmm0, xmm1;
  165. subpd       xmm4, xmm5;
  166. shufpd      xmm1, xmm0, 0;
  167. shufpd      xmm5, xmm4, 0;
  168. addpd       xmm5, xmm1;
  169. addpd       xmm1, xmm1;
  170. subpd       xmm1, xmm5;
  171. cvttpd2dq   xmm5, xmm5;
  172. cvttpd2dq   xmm1, xmm1;
  173. packssdw    xmm5, xmm1;
  174. packuswb    xmm5, xmm5;
  175. movd        eax_ptr, xmm5;
  176. mov         [esi_ptr], ax;
  177. shr         eax_ptr, 16;
  178. stosw;
  179. loop_end:
  180. }
  181. }
  182. inline void dwt2(__out cv::Mat& CA,
  183. __out cv::Mat& CH,
  184. __out cv::Mat& CV,
  185. __out cv::Mat& CD,
  186. __in cv::Mat const& I)
  187. {
  188. if(CA.type() != CV_64FC1 || CH.type() != CV_64FC1 || CV.type() != CV_64FC1 || CD.type() != CV_64FC1 || I.channels() != 1)
  189. return;
  190. double* ca = reinterpret_cast<double*>(CA.data);
  191. double* ch = reinterpret_cast<double*>(CH.data);
  192. double* cv = reinterpret_cast<double*>(CV.data);
  193. double* cd = reinterpret_cast<double*>(CD.data);
  194. unsigned char* row = reinterpret_cast<unsigned char*>(I.data);
  195. for(int i=0; i<I.rows; i+=2)
  196. {
  197. dwt2_row(ca, ch, cv, cd, row, row+I.cols, I.cols);
  198. ca += CA.cols;
  199. ch += CH.cols;
  200. cv += CV.cols;
  201. cd += CD.cols;
  202. row += I.cols*2;
  203. }
  204. }
  205. inline void idwt2(__out cv::Mat& I,
  206. __in cv::Mat const& CA,
  207. __in cv::Mat const& CH,
  208. __in cv::Mat const& CV,
  209. __in cv::Mat const& CD)
  210. {
  211. if(CA.type() != CV_64FC1 || CH.type() != CV_64FC1 || CV.type() != CV_64FC1 || CD.type() != CV_64FC1 || I.channels() != 1)
  212. return;
  213. double* ca = reinterpret_cast<double*>(CA.data);
  214. double* ch = reinterpret_cast<double*>(CH.data);
  215. double* cv = reinterpret_cast<double*>(CV.data);
  216. double* cd = reinterpret_cast<double*>(CD.data);
  217. unsigned char* row = reinterpret_cast<unsigned char*>(I.data);
  218. for(int i=0; i<I.rows; i+=2)
  219. {
  220. idwt2_row(row, row+I.cols, ca, ch, cv, cd, I.cols);
  221. ca += CA.cols;
  222. ch += CH.cols;
  223. cv += CV.cols;
  224. cd += CD.cols;
  225. row += I.cols*2;
  226. }
  227. }

版权归作者所有,转载请注明出处!

SSE2实现HAAR小波变换(dwt2与idwt2)相关推荐

  1. haar小波变换学习笔记

    本篇很大一部分内容借鉴了篇末所引用的优质博客~~ 小波可以认为是一个带通滤波器,只允许频率和小波基函数频率相近的信号通过.小波变换的基本思想是用一组小波函数和基函数表示一个函数或者信号. haar小波 ...

  2. Haar小波变换的快速实现

    Haar小波变换的快速实现 2014年3月12日renjihe发表评论阅读评论 先举个例子,有a=[100,12,43,39]四个数,并使用b[4]数组来保存结果. 一级Haar小波变换的结果为: b ...

  3. 使用CUDA计算Haar小波变换

    在<Haar小波变换的快速实现>一文里我们提到了Haar小波变换的计算,在这里我们使用CUDA实现文中提到的计算方式. 01 __global__ void 02 _cuda_haar(f ...

  4. Haar小波变换基本原理

    另外参见俄罗斯写的http://www.codeproject.com/Articles/22243/Real-Time-Object-Tracker-in-C Haar小波在图像处理和数字水印等方面 ...

  5. 二维图像haar小波变换的分解与重构

    二维图像haar小波变换的分解与重构 二维离散小波的理论推导和一维小波类似,但是以其尺度函数生成的尺度函数集作为标准正交基的尺度空间Vi的正交补空间Wi不能直接得到,而是可以证明,正交补空间Wi是由三 ...

  6. 图像Haar小波变换

    说起小波变换就需要提起傅里叶变换.傅里叶变换就是把波进行分解,可以认为任意一个周期波都可以有足够多的正弦(余弦)波组成,这里足够多的正弦波对应的频率不同,把这些足够的正弦波放在频域中,就是傅里叶变换, ...

  7. 哈尔(Haar)小波变换的原理及opencv源代码

    1. 小波分析 小波分析是对傅里叶变换的继承,总结和重大突破.小波分析的优势在于可以同时进行时频域分析,比傅里叶变换更适合处理非平稳信号. 小波分析所用的波称为小波,小波的能量有限,有限长且会衰减,集 ...

  8. 一维的Haar小波变换

    本文转载自:http://blog.csdn.net/liulina603/article/details/8649339 小波变换的基本思想是用一组小波函数或者基函数表示一个函数或者信号,例如图像信 ...

  9. Haar小波变换代码实现

    代码1:以图像的形式显示. # include<opencv2/opencv.hpp> # include<iostream> using namespace std; usi ...

最新文章

  1. 卷积Convolution
  2. 35张图,看懂肠道和大脑的魔性关系,绝对涨知识!
  3. selenium--字符串/整型问题Can't convert 'int' object to str implicitly提示解决方法
  4. Docker之镜像、容器、仓库概念
  5. 用Python求出:1到某个数的奇数序列里一共出现了多少个3
  6. gifcam录制动态图后导入photoshop出现透明格子怎么办?
  7. 卡尔曼滤波与组合导航原理_卫星知识科普:一种基于卫星共视的卡尔曼滤波算法!...
  8. Java基础知识(二)之控制语句
  9. html5难点,学习HTML5的难点是什么?
  10. python 判断该地址 文件创建时间2020年10月14日14时25分32秒 文件最后一次访问时间 文件最后一次修改时间
  11. 201521123061 《Java程序设计》第六周学习总结
  12. 分享一个echart 广州地图的demo
  13. 安装Linux操作系统Ubuntu 22.04 LTS并配置拨号连接
  14. 开发谷歌浏览器插件会上瘾,搞了一个JSONViewer,一个页面格式化多条JSON,提升工作效率...
  15. SpringBoot+Dubbo整合
  16. 2022-03-30 StackOverflowError与OutOfMemoryError详解
  17. 二十六、 对偶问题(※※※)
  18. ansi是什么编码_ANSI的完整形式是什么?
  19. QS世界大学 计算机科学与信息系统学科排名!中国高校表现如何?
  20. 计算机专业研究生西安就业,计算机专业需要考研吗?毕业之后该怎么发展?

热门文章

  1. xampp访问php显示空白,运行PHP项目显示空白
  2. 架构设计器_MySQL:数据库结构优化、高可用架构设计、数据库索引优化
  3. logrotate机制和原理
  4. leetcode算法题--不同路径
  5. js路由在php上面使用,React中路由使用详解
  6. C++ 20的悲叹,未出世就被群嘲“劝退”
  7. Kubernetes 安装
  8. 【Python】*args 和 **kwargs的用法
  9. 【转】linux tar 压缩
  10. phonegap工程中修改app的名字