参考《Visual C++数字图像处理典型算法及实现 》中的源代码,按照matlab中的程序做了修改,并用matlab进行了分解及重构的验证。
局限性:该算法仅对输入数据长度为2的指数的情况有效。
int Log2(int x)
{//求最大可分解尺度,不要随便用math.h中的函数,因为各种重载过于复杂,极可能出错
int k=1;
while((1<<k)<=x) k++;
k--;
return k;
}
BOOL DWTStep_1D(double* data,int nCurLevel,int nInv,int nStep,int nSupp)
{
//double s=sqrt((double)2);
//获得小波基的指针
double* h=(double*)hCoef[nSupp-1];//系数为Lo_R
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
//对称延拓
int ExtN=2*nSupp+CurN;//延拓后的长度
double* pdata=new double[ExtN];
for(int i=0;i<nSupp;i++)
{
pdata[i]=data[nSupp-1-i];
pdata[ExtN-nSupp+i]=data[CurN-1-i];
}
for(int i=nSupp;i<ExtN-nSupp;i++)
pdata[i]=data[i-nSupp];
//分解及系数提取
Index1=0;
Index2=2*nSupp-1;
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]*pdata[(Index1)*nStep];
s2+=t*h[j]*pdata[(Index2)*nStep];
Index1++;
Index2--;
}
ptemp[i]=s1;
ptemp[i+CurN/2]=s2;
Index1-=2*nSupp;
Index2+=2*nSupp;
Index1+=2;//downsample,隔一个采样一次
Index2+=2;
}
delete[] pdata;
}
else
{//IDWT
//卷积零延拓
double* pdatal=new double[nSupp+CurN/2+1];
double* pdatah=new double[nSupp+CurN/2+1];
int bn=nSupp/2;
for(int i=0;i<bn;i++)
{//零延拓数据前端
pdatal[i]=0;
pdatah[i]=0;
}
for(int i=CurN/2+bn;i<nSupp+CurN/2+1;i++)
{//零延拓数据后端
pdatal[i]=0;
pdatah[i]=0;
}
for(int i=0;i<CurN/2;i++)
{//拷贝中间数据
pdatal[bn+i]=data[i];
pdatah[bn+i]=data[CurN/2+i];
}
//重构并提取系数
Index1=nSupp;//逆序乘积(正序卷积)
for(int i=0;i<CurN/2;i++)
{
s1=s2=0;
int Index3=0;
int Index4=2*nSupp-2;
if(nSupp%2==0)
{
for(int j=0;j<nSupp;j++)
{
s1+=h[Index3]*pdatal[Index1*nStep]+h[Index4+1]*pdatah[Index1*nStep];
s2+=h[Index3+1]*pdatal[Index1*nStep]-h[Index4]*pdatah[Index1*nStep];
Index3+=2;
Index4-=2;
Index1--;
}
ptemp[2*i]=s1;
ptemp[2*i+1]=s2;
}
if(nSupp%2==1)
{
for(int j=0;j<nSupp;j++)
{
s1+=h[Index3]*pdatal[Index1*nStep]+h[Index4+1]*pdatah[Index1*nStep];
s2+=h[Index3+1]*pdatal[(Index1-1)*nStep]-h[Index4]*pdatah[(Index1-1)*nStep];
Index3+=2;
Index4-=2;
Index1--;
}
ptemp[2*i]=s2;
ptemp[2*i+1]=s1;
}
Index1+=nSupp;
Index1++;
}
delete[] pdatal;
delete[] pdatah;
}
for(int i=0;i<CurN;i++)
data[i*nStep]=ptemp[i];
//删除分配的临时内存
delete[] ptemp;
return TRUE;
}
BOOL DWT_1D(double* data,int nMaxLevel,int nDWTSteps,int nInv,int nStep,int nSupp)
{
//计算最小可分解的层数
int MinLevel=nMaxLevel-nDWTSteps;
//判断是否为DWT
if(!nInv)
{//DWT
int n=nMaxLevel;
while(n>MinLevel)
if(!DWTStep_1D(data,n--,nInv,nStep,nSupp))
return FALSE;
}
else
{//IDWT
int n=MinLevel;
while(n<nMaxLevel)
if(!DWTStep_1D(data,n++,nInv,nStep,nSupp))
return FALSE;
}
return TRUE;
}