?? dwt.cpp
字號:
// 文件DWT.cpp存放的是有關小波變換的函數
#include "stdafx.h"
#include "cdib.h"
#include "math.h"
#include "GlobalApi.h"
/*************************************************************************
*
* \函數名稱:
* DWT_1D()
*
* \輸入參數:
* double * pDbSrc - 指向源數據的指針
* int nMaxLevel - 最大可分解的層數
* int nDWTSteps - 需要分界的層數
* int nInv - 是否為DWT,1表示為IDWT,0表示DWT
* int nStep - 當前的計算層數
* int nSupp - 小波基的緊支集的長度
*
* \返回值:
* BOOL - 成功則返回TRUE,否則返回FALSE
*
* \說明:
* 該函數用對存放在pDBSrc中的數據進行一維DWT或者IDWT。其中,nInv為表示進行
* DWT或者IDWT的標志。nStep為當前已經分界的層數。計算后數據仍存放在pDbSrc中
*
*************************************************************************
*/
BOOL DWT_1D(double* pDbSrc, int nMaxLevel,
int nDWTSteps, int nInv, int nStep, int nSupp )
{
// 計算最小可分界的層數
int MinLevel = nMaxLevel-nDWTSteps;
// 判斷是否為DWT
if (!nInv)
{ // DWT
int n = nMaxLevel;
while (n>MinLevel)
// 調用DWTStep_1D進行第n層的DWT
if (!DWTStep_1D(pDbSrc, n--, nInv, nStep, nSupp))
return FALSE;
}
// nInv為1則進行IDWT
else
{ // IDWT
int n = MinLevel;
while (n<nMaxLevel)
// 調用DWTStep_1D進行第n層的IDWT
if (!DWTStep_1D(pDbSrc, n++, nInv, nStep, nSupp))
return FALSE;
}
return TRUE;
}
/*************************************************************************
*
* \函數名稱:
* DWTStep_1D()
*
* \輸入參數:
* double * pDbSrc - 指向源數據的指針
* int nCurLevel - 當前分界的層數
* int nInv - 是否為DWT,1表示為IDWT,0表示DWT
* int nStep - 當前的計算層數
* int nSupp - 小波基的緊支集的長度
*
* \返回值:
* BOOL - 成功則返回TRUE,否則返回FALSE
*
* \說明:
* 該函數用對存放在pDBSrc中的數據進行一層的一維DWT或者IDWT。其中,nInv為表示進行
* DWT或者IDWT的標志。nCurLevel為當前需要進行分界的層數。nStep為已經分界的層數
* 計算后數據仍存放在pDbSrc中
*
*************************************************************************
*/
BOOL DWTStep_1D(double* pDbSrc, int nCurLevel,
int nInv, int nStep,int nSupp)
{
double s = sqrt(2);
// 獲得小波基的指針
double* h = (double*)hCoef[nSupp-1];
// 確認當前層數有效
ASSERT(nCurLevel>=0);
// 計算當前層數的長度
int CurN = 1<<nCurLevel;
if (nInv) CurN <<= 1;
// 確認所選擇的小波基和當前層數的長度有效
if (nSupp<1 || nSupp>10 || CurN<2*nSupp)
return FALSE;
// 分配臨時內存用于存放結果
double *ptemp = new double[CurN];
if (!ptemp) return FALSE;
double s1, s2;
int Index1, Index2;
// 判斷是進行DWT還是IDWT
if (!nInv)
{ // DWT
Index1=0;
Index2=2*nSupp-1;
// 進行卷積,其中s1為低頻部分,s2為高頻部分的結果
for (int i=0; i<CurN/2; i++)
{
s1 = s2 = 0;
double t = -1;
for (int j=0; j<2*nSupp; j++, t=-t)
{
s1 += h[j]*pDbSrc[(Index1 & CurN-1) * nStep];
s2 += t*h[j]*pDbSrc[(Index2 & CurN-1) * nStep];
Index1++;
Index2--;
}
// 將結果存放在臨時內存中
ptemp[i] = s1/s;
ptemp[i+CurN/2] = s2/s;
Index1 -= 2*nSupp;
Index2 += 2*nSupp;
Index1 += 2;
Index2 += 2;
}
}
// 否則進行IDWT
else
{ // IDWT
Index1 = CurN/2;
Index2 = CurN/2-nSupp+1;
// 進行卷積,其中其中s1為低頻部分,s2為高頻部分的結果
for (int i=0; i<CurN/2; i++)
{
s1 = s2 = 0;
int Index3 = 0;
for (int j=0; j<nSupp; j++)
{
s1 += h[Index3]*pDbSrc[(Index1 & CurN/2-1) * nStep]
+h[Index3+1]*pDbSrc[((Index2 & CurN/2-1) + CurN/2) * nStep];
s2 += h[Index3+1]*pDbSrc[(Index1 & CurN/2-1) * nStep]
-h[Index3]*pDbSrc[((Index2 & CurN/2-1) + CurN/2) * nStep];
Index3+=2;
Index1--, Index2++;
}
// 將結果存入臨時內存
ptemp[2*i] = s1*s;
ptemp[2*i+1] = s2*s;
Index1 += nSupp;
Index2 -= nSupp;
Index1++;
Index2++;
}
}
// 將結果存入源圖象中
for (int i=0; i<CurN; i++)
pDbSrc[i*nStep] = ptemp[i];
// 釋放臨時內存,并返回
delete[] ptemp;
return TRUE;
}
/*************************************************************************
*
* \函數名稱:
* DWT_2D()
*
* \輸入參數:
* double * pDbSrc - 指向源數據的指針
* int nMaxWLevel - X方向最大可分解的層數
* int nMaxHLevel - Y方向最大可分解的層數
* int nDWTSteps - 需要分界的層數
* int nInv - 是否為DWT,1表示為IDWT,0表示DWT
* int nStep - 當前的計算層數
* int nSupp - 小波基的緊支集的長度
*
* \返回值:
* BOOL - 成功則返回TRUE,否則返回FALSE
*
* \說明:
* 該函數用對存放在pDBSrc中的二維數據進行二維DWT或者IDWT。其中,nDWTSteps表示
* 需要分解的層數,nInv為表示進行DWT或者IDWT的標志。nStep為當前已經分界的層數
* 計算后數據仍存放在pDbSrc中
*
*************************************************************************
*/
BOOL DWT_2D(double* pDbSrc, int nMaxWLevel, int nMaxHLevel,
int nDWTSteps, int nInv, int nStep, int nSupp)
{
// 計算X,Y方向上最小的分界層數
int MinWLevel = nMaxWLevel - nDWTSteps;
int MinHLevel = nMaxHLevel - nDWTSteps;
// 判斷是進行DWT,還是IDWT
if (!nInv)
{ // DWT
int n = nMaxWLevel, m = nMaxHLevel;
// 調用DWTStep_2D進行分解,分解的層數為nDWTSteps
while (n>MinWLevel)
if (!DWTStep_2D(pDbSrc, n--, m--, nMaxWLevel, nMaxHLevel, nInv, nStep, nSupp))
return FALSE;
}
// 否則進行IDWT
else
{ // IDWT
int n = MinWLevel, m = MinHLevel;
// 調用DWTStep_2D進行IDWT,進行恢復的層數為nDWTSteps
while (n<nMaxWLevel)
if (!DWTStep_2D(pDbSrc, n++, m++, nMaxWLevel, nMaxHLevel, nInv, nStep, nSupp))
return FALSE;
}
// 返回
return TRUE;
}
/*************************************************************************
*
* \函數名稱:
* DWTStep_2D()
*
* \輸入參數:
* double * pDbSrc - 指向源數據的指針
* int nCurWLevel - X方向上當前分解的層數
* int nCurHLevel - Y方向上當前分解的層數
* int nMaxWLevel - X方向上最大可分解的層數
* int nMaxHLevel - Y方向上最大可分解的層數
* int nInv - 是否為DWT,1表示為IDWT,0表示DWT
* int nStep - 當前的計算層數
* int nSupp - 小波基的緊支集的長度
*
* \返回值:
* BOOL - 成功則返回TRUE,否則返回FALSE
*
* \說明:
* 該函數用對存放在pDBSrc中的數據進行一層的二維DWT或者IDWT。
* 計算后數據仍存放在pDbSrc中
*
*************************************************************************
*/
BOOL DWTStep_2D(double* pDbSrc, int nCurWLevel, int nCurHLevel,
int nMaxWLevel, int nMaxHLevel, int nInv, int nStep, int nSupp)
{
// 計算圖象的長度和寬度(2次冪對齊)
int W = 1<<nMaxWLevel, H = 1<<nMaxHLevel;
// 計算當前分解的圖象的長度和寬度
int CurW = 1<<nCurWLevel, CurH = 1<<nCurHLevel;
// 判斷是進行DWT還是IDWT
if (!nInv)
{ // 對行進行一維DWT
for (int i=0; i<CurH; i++)
if (!DWTStep_1D(pDbSrc+(int)i*W*nStep, nCurWLevel, nInv, nStep, nSupp)) return FALSE;
// 對列進行一維DWT
for (i=0; i<CurW; i++)
if (!DWTStep_1D(pDbSrc+i*nStep, nCurHLevel, nInv, W*nStep, nSupp)) return FALSE;
}
// 否則進行IDWT
else
{
// 計算當前變換的圖象的長度和寬度
CurW <<= 1;
CurH <<= 1;
// 對列進行IDWT
for (int i=0; i<CurW; i++)
if (!DWTStep_1D(pDbSrc+i*nStep, nCurHLevel, nInv, W*nStep, nSupp)) return FALSE;
// 對行進行IDWT
for (i=0; i<CurH; i++)
if (!DWTStep_1D(pDbSrc+(int)i*W*nStep, nCurWLevel, nInv, nStep, nSupp)) return FALSE;
}
// 返回
return TRUE;
}
/*************************************************************************
*
* \函數名稱:
* ImageDWT()
*
* \輸入參數:
* CDib* pDibSrc - 指向源數據的指針
* int nMaxWLevel - X方向上最大可分解的層數
* int nMaxHLevel - Y方向上最大可分解的層數
* int nDWTSteps - 需要進行變換的層數
* int nInv - 是否為DWT,1表示為IDWT,0表示DWT
* int nStep - 當前的計算層數
* int nSupp - 小波基的緊支集的長度
*
* \返回值:
* BOOL - 成功則返回TRUE,否則返回FALSE
*
* \說明:
* 該函數用對存放在pDBSrc中的數據進行一層的二維DWT或者IDWT。
* 計算后數據仍存放在pDbSrc中
*
*************************************************************************
*/
BOOL ImageDWT(LPBYTE lpImage, int nMaxWLevel, int nMaxHLevel,
int nDWTSteps, int nInv, int nStep, int nSupp)
{
// 判斷變換的層數以及當前層數是否有效
if (nDWTSteps>nMaxWLevel || nDWTSteps>nMaxHLevel || nStep<=0)
return FALSE;
// 獲得X,Y方向上的最大象素數(2次冪對齊)
int W = 1<<nMaxWLevel, H = 1<<nMaxHLevel;
// 獲得X,Y方向上變換時最小的象素數
int minW = W>>nDWTSteps, minH = H>>nDWTSteps;
int i, j, index;
// 分配臨時內存存放結果
double* pDbTemp = new double[W*H];
if (!pDbTemp) return FALSE;
// 判斷是進行DWT還是IDWT,然后將數據存放到臨時內存中,需要注意的是,需要進行采樣
if (!nInv) // DWT
for (index=0; index<W*H; index++) pDbTemp[index] = lpImage[index*nStep];
else // IDWT
{
index = 0;
for (i=0; i<minH; i++)
{
for (j=0; j<minW; j++, index++)
pDbTemp[index] = lpImage[index*nStep];
for (; j<W; j++, index++)
pDbTemp[index] = (char)lpImage[index*nStep];
}
for (; index<W*H; index++)
pDbTemp[index] = (char)lpImage[index*nStep];
}
// 調用DWT_2D進行小波變換
if(!DWT_2D(pDbTemp, nMaxWLevel, nMaxHLevel, nDWTSteps, nInv, nStep, nSupp))
{
delete []pDbTemp;
return FALSE;
}
// 將數據存入原始的內存中,需要注意的是,存儲時需要進行類型轉換
if (!nInv) // DWT
{
index = 0;
for (i=0; i<minH; i++)
{
for (j=0; j<minW; j++, index++)
lpImage[index*nStep] = FloatToByte(pDbTemp[index]);
for (; j<W; j++, index++)
lpImage[index*nStep] = (BYTE)FloatToChar(pDbTemp[index]);
// lpImage[index*nStep] = (BYTE)FloatToByte(pDbTemp[index]);
}
for (; index<W*H; index++)
lpImage[index*nStep] = (BYTE)FloatToChar(pDbTemp[index]);
//lpImage[index*nStep] = (BYTE)FloatToByte(pDbTemp[index]);
}
else // IDWT
for (index=0; index<W*H; index++)
lpImage[index*nStep] = FloatToByte(pDbTemp[index]);
// 釋放內存
delete []pDbTemp;
// 返回
return TRUE;
}
/*************************************************************************
*
* \函數名稱:
* FloatToByte()
*
* \輸入參數:
* double f - 輸入雙精度變量
*
* \返回值:
* BYTE - 返回比特型變量
*
* \說明:
* 該函數將輸入的雙精度變量轉換為BYTE型的變量
*
*************************************************************************
*/
BYTE FloatToByte(double f)
{
if (f<=0) return (BYTE)0;
else if (f>=255) return (BYTE)255;
else return (BYTE)(f+0.5);
}
/*************************************************************************
*
* \函數名稱:
* FloatToChar()
*
* \輸入參數:
* double f - 輸入雙精度變量
*
* \返回值:
* Char - 返回字符變量
*
* \說明:
* 該函數將輸入的雙精度變量轉換為Char型的變量
*
*************************************************************************
*/
char FloatToChar(double f)
{
if (f>=0)
if (f>=127.0)
return (char)127;
else return (char)(f+0.5);
else
if (f<=-128)
return (char)-128;
else return -(char)(-f+0.5);
}
/*************************************************************************
*
* \函數名稱:
* Log2()
*
* \輸入參數:
* int n - 輸入整型變量
*
* \返回值:
* int - 返回輸入參數的對數
*
* \說明:
* 該函數求取輸入參數的以2為底的對數,并轉換為整型輸出。
*
*************************************************************************
*/
int Log2(int n)
{
int rsl = 0;
while (n >>= 1) rsl++;
return rsl;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -