DWT.CPP
上传用户:wangchdtw
上传日期:2014-04-02
资源大小:329k
文件大小:11k
源码类别:

波变换

开发平台:

Visual C++

  1. // 文件DWT.cpp存放的是有关小波变换的函数
  2. #include "stdafx.h"
  3. #include "cdib.h"
  4. #include "math.h"
  5. #include "GlobalApi.h"
  6. /*************************************************************************
  7.  *
  8.  * 函数名称:
  9.  *   DWT_1D()
  10.  *
  11.  * 输入参数:
  12.  *   double * pDbSrc - 指向源数据的指针
  13.  *   int nMaxLevel - 最大可分解的层数
  14.  *   int nDWTSteps - 需要分界的层数
  15.  *   int nInv - 是否为DWT,1表示为IDWT,0表示DWT
  16.  *   int nStep - 当前的计算层数
  17.  *   int nSupp - 小波基的紧支集的长度
  18.  *
  19.  * 返回值:
  20.  *   BOOL - 成功则返回TRUE,否则返回FALSE
  21.  *
  22.  * 说明:
  23.  *   该函数用对存放在pDBSrc中的数据进行一维DWT或者IDWT。其中,nInv为表示进行
  24.  *   DWT或者IDWT的标志。nStep为当前已经分界的层数。计算后数据仍存放在pDbSrc中
  25.  *
  26.  *************************************************************************
  27.  */
  28. BOOL DWT_1D(double* pDbSrc, int nMaxLevel,
  29. int nDWTSteps, int nInv, int nStep, int nSupp )
  30. {
  31. // 计算最小可分界的层数
  32. int MinLevel = nMaxLevel-nDWTSteps;
  33. // 判断是否为DWT
  34. if (!nInv)
  35. { // DWT
  36. int n = nMaxLevel;
  37. while (n>MinLevel)
  38. // 调用DWTStep_1D进行第n层的DWT
  39. if (!DWTStep_1D(pDbSrc, n--, nInv, nStep, nSupp)) 
  40. return FALSE;
  41. }
  42. // nInv为1则进行IDWT
  43. else
  44. { // IDWT
  45. int n = MinLevel;
  46. while (n<nMaxLevel)
  47. // 调用DWTStep_1D进行第n层的IDWT
  48. if (!DWTStep_1D(pDbSrc, n++, nInv, nStep, nSupp)) 
  49. return FALSE;
  50. }
  51. return TRUE;
  52. }
  53. /*************************************************************************
  54.  *
  55.  * 函数名称:
  56.  *   DWTStep_1D()
  57.  *
  58.  * 输入参数:
  59.  *   double * pDbSrc - 指向源数据的指针
  60.  *   int nCurLevel - 当前分界的层数
  61.  *   int nInv - 是否为DWT,1表示为IDWT,0表示DWT
  62.  *   int nStep - 当前的计算层数
  63.  *   int nSupp - 小波基的紧支集的长度
  64.  *
  65.  * 返回值:
  66.  *   BOOL - 成功则返回TRUE,否则返回FALSE
  67.  *
  68.  * 说明:
  69.  *   该函数用对存放在pDBSrc中的数据进行一层的一维DWT或者IDWT。其中,nInv为表示进行
  70.  *   DWT或者IDWT的标志。nCurLevel为当前需要进行分界的层数。nStep为已经分界的层数
  71.  *   计算后数据仍存放在pDbSrc中
  72.  *
  73.  *************************************************************************
  74.  */
  75. BOOL DWTStep_1D(double* pDbSrc, int nCurLevel,
  76. int nInv, int nStep,int nSupp)
  77. {
  78. double s = sqrt(2);
  79. // 获得小波基的指针
  80. double* h = (double*)hCoef[nSupp-1];
  81. // 确认当前层数有效
  82. ASSERT(nCurLevel>=0);
  83. // 计算当前层数的长度
  84. int CurN = 1<<nCurLevel;
  85. if (nInv) CurN <<= 1;
  86. // 确认所选择的小波基和当前层数的长度有效
  87. if (nSupp<1 || nSupp>10 || CurN<2*nSupp) 
  88. return FALSE;
  89. // 分配临时内存用于存放结果
  90. double *ptemp = new double[CurN];
  91. if (!ptemp) return FALSE;
  92. double s1, s2;
  93. int Index1, Index2;
  94. // 判断是进行DWT还是IDWT
  95. if (!nInv)
  96. { // DWT
  97. Index1=0;
  98. Index2=2*nSupp-1;
  99. // 进行卷积,其中s1为低频部分,s2为高频部分的结果
  100. for (int i=0; i<CurN/2; i++)
  101. {
  102. s1 = s2 = 0;
  103. double t = -1;
  104. for (int j=0; j<2*nSupp; j++, t=-t)
  105. {
  106. s1 += h[j]*pDbSrc[(Index1 & CurN-1) * nStep];
  107. s2 += t*h[j]*pDbSrc[(Index2 & CurN-1) * nStep];
  108. Index1++;
  109. Index2--;
  110. }
  111. // 将结果存放在临时内存中
  112. ptemp[i] = s1/s;
  113. ptemp[i+CurN/2] = s2/s;
  114. Index1 -= 2*nSupp;
  115. Index2 += 2*nSupp;
  116. Index1 += 2;
  117. Index2 += 2;
  118. }
  119. }
  120. // 否则进行IDWT
  121. else
  122. { // IDWT
  123. Index1 = CurN/2;
  124. Index2 = CurN/2-nSupp+1;
  125. // 进行卷积,其中其中s1为低频部分,s2为高频部分的结果
  126. for (int i=0; i<CurN/2; i++)
  127. {
  128. s1 = s2 = 0;
  129. int Index3 = 0;
  130. for (int j=0; j<nSupp; j++)
  131. {
  132. s1 += h[Index3]*pDbSrc[(Index1 & CurN/2-1) * nStep]
  133.  +h[Index3+1]*pDbSrc[((Index2 & CurN/2-1) + CurN/2) * nStep];
  134. s2 += h[Index3+1]*pDbSrc[(Index1 & CurN/2-1) * nStep]
  135.  -h[Index3]*pDbSrc[((Index2 & CurN/2-1) + CurN/2) * nStep];
  136. Index3+=2;
  137. Index1--, Index2++;
  138. }
  139. // 将结果存入临时内存
  140. ptemp[2*i] = s1*s;
  141. ptemp[2*i+1] = s2*s;
  142. Index1 += nSupp;
  143. Index2 -= nSupp;
  144. Index1++;
  145. Index2++;
  146. }
  147. }
  148. // 将结果存入源图象中
  149. for (int i=0; i<CurN; i++)
  150. pDbSrc[i*nStep] = ptemp[i];
  151. // 释放临时内存,并返回
  152. delete[] ptemp;
  153. return TRUE;
  154. }
  155. /*************************************************************************
  156.  *
  157.  * 函数名称:
  158.  *   DWT_2D()
  159.  *
  160.  * 输入参数:
  161.  *   double * pDbSrc - 指向源数据的指针
  162.  *   int nMaxWLevel - X方向最大可分解的层数
  163.  *   int nMaxHLevel - Y方向最大可分解的层数
  164.  *   int nDWTSteps - 需要分界的层数
  165.  *   int nInv - 是否为DWT,1表示为IDWT,0表示DWT
  166.  *   int nStep - 当前的计算层数
  167.  *   int nSupp - 小波基的紧支集的长度
  168.  *
  169.  * 返回值:
  170.  *   BOOL - 成功则返回TRUE,否则返回FALSE
  171.  *
  172.  * 说明:
  173.  *   该函数用对存放在pDBSrc中的二维数据进行二维DWT或者IDWT。其中,nDWTSteps表示
  174.  *   需要分解的层数,nInv为表示进行DWT或者IDWT的标志。nStep为当前已经分界的层数
  175.  *   计算后数据仍存放在pDbSrc中
  176.  *
  177.  *************************************************************************
  178.  */
  179. BOOL DWT_2D(double* pDbSrc, int nMaxWLevel, int nMaxHLevel,
  180. int nDWTSteps, int nInv, int nStep, int nSupp)
  181. {
  182. // 计算X,Y方向上最小的分界层数
  183. int MinWLevel = nMaxWLevel - nDWTSteps;
  184. int MinHLevel = nMaxHLevel - nDWTSteps;
  185. // 判断是进行DWT,还是IDWT
  186. if (!nInv)
  187. { // DWT
  188. int n = nMaxWLevel, m = nMaxHLevel;
  189. // 调用DWTStep_2D进行分解,分解的层数为nDWTSteps
  190. while (n>MinWLevel)
  191. if (!DWTStep_2D(pDbSrc, n--, m--, nMaxWLevel, nMaxHLevel, nInv, nStep, nSupp)) 
  192. return FALSE;
  193. }
  194. // 否则进行IDWT
  195. else
  196. { // IDWT
  197. int n = MinWLevel, m = MinHLevel;
  198. // 调用DWTStep_2D进行IDWT,进行恢复的层数为nDWTSteps
  199. while (n<nMaxWLevel)
  200. if (!DWTStep_2D(pDbSrc, n++, m++, nMaxWLevel, nMaxHLevel, nInv, nStep, nSupp)) 
  201. return FALSE;
  202. }
  203. // 返回
  204. return TRUE;
  205. }
  206. /*************************************************************************
  207.  *
  208.  * 函数名称:
  209.  *   DWTStep_2D()
  210.  *
  211.  * 输入参数:
  212.  *   double * pDbSrc - 指向源数据的指针
  213.  *   int nCurWLevel - X方向上当前分解的层数
  214.  *   int nCurHLevel - Y方向上当前分解的层数
  215.  *   int nMaxWLevel - X方向上最大可分解的层数
  216.  *   int nMaxHLevel - Y方向上最大可分解的层数
  217.  *   int nInv - 是否为DWT,1表示为IDWT,0表示DWT
  218.  *   int nStep - 当前的计算层数
  219.  *   int nSupp - 小波基的紧支集的长度
  220.  *
  221.  * 返回值:
  222.  *   BOOL - 成功则返回TRUE,否则返回FALSE
  223.  *
  224.  * 说明:
  225.  *   该函数用对存放在pDBSrc中的数据进行一层的二维DWT或者IDWT。
  226.  *   计算后数据仍存放在pDbSrc中
  227.  *
  228.  *************************************************************************
  229.  */
  230. BOOL DWTStep_2D(double* pDbSrc, int nCurWLevel, int nCurHLevel,
  231. int nMaxWLevel, int nMaxHLevel, int nInv, int nStep, int nSupp)
  232. {
  233. // 计算图象的长度和宽度(2次幂对齐)
  234. int W = 1<<nMaxWLevel, H = 1<<nMaxHLevel;
  235. // 计算当前分解的图象的长度和宽度
  236. int CurW = 1<<nCurWLevel, CurH = 1<<nCurHLevel;
  237. // 判断是进行DWT还是IDWT
  238. if (!nInv)
  239. { // 对行进行一维DWT
  240. for (int i=0; i<CurH; i++)
  241. if (!DWTStep_1D(pDbSrc+(int)i*W*nStep, nCurWLevel, nInv, nStep, nSupp)) return FALSE;
  242. // 对列进行一维DWT
  243. for (i=0; i<CurW; i++)
  244. if (!DWTStep_1D(pDbSrc+i*nStep, nCurHLevel, nInv, W*nStep, nSupp)) return FALSE;
  245. }
  246. // 否则进行IDWT
  247. else
  248. {
  249. // 计算当前变换的图象的长度和宽度
  250. CurW <<= 1;
  251. CurH <<= 1;
  252. // 对列进行IDWT
  253. for (int i=0; i<CurW; i++)
  254. if (!DWTStep_1D(pDbSrc+i*nStep, nCurHLevel, nInv, W*nStep, nSupp)) return FALSE;
  255. // 对行进行IDWT
  256. for (i=0; i<CurH; i++)
  257. if (!DWTStep_1D(pDbSrc+(int)i*W*nStep, nCurWLevel, nInv, nStep, nSupp)) return FALSE;
  258. }
  259. // 返回
  260. return TRUE;
  261. }
  262. /*************************************************************************
  263.  *
  264.  * 函数名称:
  265.  *   ImageDWT()
  266.  *
  267.  * 输入参数:
  268.  *   CDib* pDibSrc - 指向源数据的指针
  269.  *   int nMaxWLevel - X方向上最大可分解的层数
  270.  *   int nMaxHLevel - Y方向上最大可分解的层数
  271.  *   int nDWTSteps - 需要进行变换的层数
  272.  *   int nInv - 是否为DWT,1表示为IDWT,0表示DWT
  273.  *   int nStep - 当前的计算层数
  274.  *   int nSupp - 小波基的紧支集的长度
  275.  *
  276.  * 返回值:
  277.  *   BOOL - 成功则返回TRUE,否则返回FALSE
  278.  *
  279.  * 说明:
  280.  *   该函数用对存放在pDBSrc中的数据进行一层的二维DWT或者IDWT。
  281.  *   计算后数据仍存放在pDbSrc中
  282.  *
  283.  *************************************************************************
  284.  */
  285. BOOL ImageDWT(LPBYTE lpImage, int nMaxWLevel, int nMaxHLevel,
  286. int nDWTSteps, int nInv, int nStep, int nSupp)
  287. {
  288. // 判断变换的层数以及当前层数是否有效
  289. if (nDWTSteps>nMaxWLevel || nDWTSteps>nMaxHLevel || nStep<=0)
  290. return FALSE;
  291. // 获得X,Y方向上的最大象素数(2次幂对齐)
  292. int W = 1<<nMaxWLevel, H = 1<<nMaxHLevel;
  293. // 获得X,Y方向上变换时最小的象素数
  294. int minW = W>>nDWTSteps, minH = H>>nDWTSteps;
  295. int i, j, index;
  296. // 分配临时内存存放结果
  297. double* pDbTemp = new double[W*H];
  298. if (!pDbTemp) return FALSE;
  299. // 判断是进行DWT还是IDWT,然后将数据存放到临时内存中,需要注意的是,需要进行采样
  300. if (!nInv) // DWT
  301. for (index=0; index<W*H; index++) pDbTemp[index] = lpImage[index*nStep];
  302. else // IDWT
  303. {
  304. index = 0;
  305. for (i=0; i<minH; i++)
  306. {
  307. for (j=0; j<minW; j++, index++)
  308. pDbTemp[index] = lpImage[index*nStep];
  309. for (; j<W; j++, index++)
  310. pDbTemp[index] = (char)lpImage[index*nStep];
  311. }
  312. for (; index<W*H; index++)
  313. pDbTemp[index] = (char)lpImage[index*nStep];
  314. }
  315. // 调用DWT_2D进行小波变换
  316. if(!DWT_2D(pDbTemp, nMaxWLevel, nMaxHLevel, nDWTSteps, nInv, nStep, nSupp))
  317. {
  318. delete []pDbTemp;
  319. return FALSE;
  320. }
  321. // 将数据存入原始的内存中,需要注意的是,存储时需要进行类型转换
  322. if (!nInv) // DWT
  323. {
  324. index = 0;
  325. for (i=0; i<minH; i++)
  326. {
  327. for (j=0; j<minW; j++, index++)
  328. lpImage[index*nStep] = FloatToByte(pDbTemp[index]);
  329. for (; j<W; j++, index++)
  330. lpImage[index*nStep] = (BYTE)FloatToChar(pDbTemp[index]);
  331. // lpImage[index*nStep] = (BYTE)FloatToByte(pDbTemp[index]);
  332. }
  333. for (; index<W*H; index++)
  334. lpImage[index*nStep] = (BYTE)FloatToChar(pDbTemp[index]);
  335. //lpImage[index*nStep] = (BYTE)FloatToByte(pDbTemp[index]);
  336. }
  337. else // IDWT
  338. for (index=0; index<W*H; index++) 
  339. lpImage[index*nStep] = FloatToByte(pDbTemp[index]);
  340. // 释放内存
  341. delete []pDbTemp;
  342. // 返回
  343. return TRUE;
  344. }
  345. /*************************************************************************
  346.  *
  347.  * 函数名称:
  348.  *   FloatToByte()
  349.  *
  350.  * 输入参数:
  351.  *   double  f - 输入双精度变量
  352.  *
  353.  * 返回值:
  354.  *   BYTE - 返回比特型变量
  355.  *
  356.  * 说明:
  357.  *   该函数将输入的双精度变量转换为BYTE型的变量
  358.  *
  359.  *************************************************************************
  360.  */
  361. BYTE FloatToByte(double f)
  362. {
  363. if (f<=0) return (BYTE)0;
  364. else if (f>=255) return (BYTE)255;
  365. else return (BYTE)(f+0.5);
  366. }
  367. /*************************************************************************
  368.  *
  369.  * 函数名称:
  370.  *   FloatToChar()
  371.  *
  372.  * 输入参数:
  373.  *   double  f - 输入双精度变量
  374.  *
  375.  * 返回值:
  376.  *   Char - 返回字符变量
  377.  *
  378.  * 说明:
  379.  *   该函数将输入的双精度变量转换为Char型的变量
  380.  *
  381.  *************************************************************************
  382.  */
  383. char FloatToChar(double f)
  384. {
  385. if (f>=0)
  386. if (f>=127.0)
  387. return (char)127;
  388. else return (char)(f+0.5);
  389. else
  390. if (f<=-128)
  391. return (char)-128;
  392. else return -(char)(-f+0.5);
  393. }
  394. /*************************************************************************
  395.  *
  396.  * 函数名称:
  397.  *   Log2()
  398.  *
  399.  * 输入参数:
  400.  *   int  n - 输入整型变量
  401.  *
  402.  * 返回值:
  403.  *   int - 返回输入参数的对数
  404.  *
  405.  * 说明:
  406.  *   该函数求取输入参数的以2为底的对数,并转换为整型输出。
  407.  *
  408.  *************************************************************************
  409.  */
  410. int Log2(int n)
  411. {
  412. int rsl = 0;
  413. while (n >>= 1) rsl++;
  414. return rsl;
  415. }