gusucode.com > VC 实现的二维小波变换用于图像去噪、压缩等源码程序 > WaveTranform.cpp
// WaveTranform.cpp: implementation of the CWaveTranform class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "小波变换.h" #include "WaveTranform.h" #include "DIBAPI.h" #include <math.h> #include <direct.h> #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CWaveTranform::CWaveTranform() { m_GrayMax=255; m_GrayMin=0; for(int i=0;i<3;i++) { m_ColorMax[i]=255;//0蓝1绿2红 m_ColorMin[i]=0; } m_preoffset=0; m_aftoffset=0; } CWaveTranform::~CWaveTranform() { } /************************************************************************* * * 函数名称: * Convolution() * * 参数: * double * LF HF - 指向小波的指针,是常量 * FR - 小波窗的宽度 * double * f - 指向时域值的指针和返回的小波变换频域的指针 * fr -原图象每一行的像素个数 * * 返回值: * 无。 * * 说明: * 该函数用来实现卷积运算。 * ************************************************************************/ void CWaveTranform::Convolution(double *LF,double *HF,int FR, double *f, int fr) { int i,j,m;// 循环变量 double *X; X = new double[fr]; // 分配运算所需的数组 // 卷积运算 for(i=0;i<fr/2;i++) { X[i]=0; X[i+fr/2]=0; for(j=0;j<FR;j++) { m=(2*i+j+fr-m_preoffset)%fr; X[i]+=f[m]*LF[j]; X[i+fr/2]+=f[m]*HF[j]; } } //运算结果反传给f。 for(i= 0; i <fr; i++) { f[i]=X[i]; } delete X;// 释放内存 } /************************************************************************* * * 函数名称: * DisConvolution() * * 参数: * double * F - 指向小波的指针,是常量 * FR - 小波窗的宽度 * double * f - 指向时域值的指针和返回的小波变换频域的指针 * fr -原图象每一行的像素个数 * * 返回值: * 无。 * * 说明: * 该函数用来实现解卷积运算。 * ************************************************************************/ void CWaveTranform::DisConvolution(double *LF,double *HF,int FR, double *f0,double *f1, int fr) { int i,j;// 循环变量 double *X,*Y; // 分配运算所需的数组 X = new double[fr]; Y = new double[fr]; // 解卷积运算 for(i=0;i<fr;i++) { X[i]=0; Y[i]=0; for(j=0;j<FR;j++) { X[i]+=f0[(i+j)%fr]*LF[j]; Y[i]+=f1[(i+j)%fr]*HF[j]; } } //运算结果反传给f0。 for(i= 0; i <fr; i++) { j=(i+fr-m_aftoffset)%fr;//循环移位 f0[i]=X[j]+Y[j]; } delete X,Y; // 释放内存 } /************************************************************************* * * 函数名称: * DIBWavelet() * * 参数: * LPSTR lpDIB - 指向DIB图像指针 * LPSTR lpDIBBits - 指向源DIB象素指针 * double *LF - 使用的小波尺度函数,是常量 * double *HF - 使用的小波母函数,是常量 * int FWidth - 小波窗的宽度 * int nLevel - 小波分解的层数 * * 返回值: * BOOL - 成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数用来对图像进行小波变换分解。于上面不同的是,此处是将二维 * 矩阵转换成一个列向量,然后对该列向量进行一次一维小波变换。 * ************************************************************************/ BOOL CWaveTranform::DIBWavelet(LPSTR lpDIB,LPSTR lpDIBBits,double* LF,double* HF,int FWidth,int nLevel) { unsigned char* lpSrc;// 指向源图像的指针 double dTemp;// 中间变量 LONG lLineBytes; // 图像每行的字节数 LONG lWidth, lHeight; lWidth=::DIBWidth(lpDIB); lHeight=::DIBHeight(lpDIB); LONG i,j;//循环变量 double *f = new double[lWidth*lHeight];// 分配内存 if(::DIBNumColors(lpDIB)==256) { lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数 // 从源图像中读取数据。 for(i = 0; i < lHeight; i++)//每列 { for(j = 0; j < lWidth; j++)// 每行 { lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) +j; // 指向DIB第i行,第j个象素的指针 f[i*lWidth+j] = *(lpSrc);// 给时域赋值 } } int n;//层数循环变量 //小波变换分解过程循环 for(n=0;n<nLevel;n++) { LONG Height,Width;//第n层图象的高度和宽度 Height=long(lHeight/pow(2,n)); Width=long(lWidth/pow(2,n)); double *LH=new double[Width]; //存放每一行元素 for(i = 0; i < Height; i++) { for(j=0;j<Width;j++) { LH[j]=f[i*lWidth+j]; } Convolution( LF,HF, FWidth,LH, Width);// 对x方向进行卷积运算 for(j=0;j<Width;j++) { f[i*lWidth+j]=LH[j]; } } delete LH; LH=new double[Height]; //存放每一列元素 for(i = 0; i < Width; i++) { for(j=0;j<Height;j++) { LH[j]=f[i+j*lWidth]; } Convolution( LF,HF, FWidth,LH, Height);// 对y方向进行卷积运算 for(j=0;j<Height;j++) { f[i+j*lWidth]=LH[j]; } } delete LH;//释放内存 } //将分解后的值规划处理 m_GrayMax=0; m_GrayMin=255; for(i=0;i<lHeight;i++) { for(j=0;j<lWidth;j++) { m_GrayMax=m_GrayMax>f[i * lWidth + j]?m_GrayMax:f[i * lWidth + j]; m_GrayMin=m_GrayMin<f[i * lWidth + j]?m_GrayMin:f[i * lWidth + j]; } } // 更新源图像 for(i = 0; i < lHeight; i++)// 每列 { for(j = 0; j < lWidth; j++)// 每行 { dTemp = f[i * lWidth + j]; // 计算频谱 dTemp=255/(m_GrayMax-m_GrayMin)*(dTemp-m_GrayMin); lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;// 指向DIB第i行,第j个象素的指针 * (lpSrc) = (BYTE)(dTemp);// 更新源图像 } } } //处理真彩色 else { int ncolor;//颜色值循环 for(ncolor=0;ncolor<3;ncolor++) { lLineBytes = WIDTHBYTES(lWidth * 24);// 计算图像每行的字节数 // 从源图像中读取数据。 for(i = 0; i < lHeight; i++)//每列 { for(j = 0; j < lWidth; j++)// 每行 { lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) +3*j+ncolor; // 指向DIB第i行,第j个象素的指针 f[i*lWidth+j] = *(lpSrc);// 给时域赋值 } } int n;//层数循环变量 //小波变换分解过程循环 for(n=0;n<nLevel;n++) { LONG Height,Width;//第n层图象的高度和宽度 Height=long(lHeight/pow(2,n)); Width=long(lWidth/pow(2,n)); double *LH=new double[Width]; //存放每一行元素 for(i = 0; i < Height; i++) { for(j=0;j<Width;j++) { LH[j]=f[i*lWidth+j]; } Convolution( LF,HF, FWidth,LH, Width);// 对x方向进行卷积运算 for(j=0;j<Width;j++) { f[i*lWidth+j]=LH[j]; } } delete LH; LH=new double[Height]; //存放每一列元素 for(i = 0; i < Width; i++) { for(j=0;j<Height;j++) { LH[j]=f[i+j*lWidth]; } Convolution( LF,HF, FWidth,LH, Height);// 对y方向进行卷积运算 for(j=0;j<Height;j++) { f[i+j*lWidth]=LH[j]; } } delete LH;//释放内存 } //将分解后的值规划处理 m_ColorMax[ncolor]=0; m_ColorMin[ncolor]=255; for(i=0;i<lHeight;i++) { for(j=0;j<lWidth;j++) { m_ColorMax[ncolor]=m_ColorMax[ncolor]>f[i * lWidth + j]?m_ColorMax[ncolor]:f[i * lWidth + j]; m_ColorMin[ncolor]=m_ColorMin[ncolor]<f[i * lWidth + j]?m_ColorMin[ncolor]:f[i * lWidth + j]; } } // 更新源图像 for(i = 0; i < lHeight; i++)// 每列 { for(j = 0; j < lWidth; j++)// 每行 { dTemp = f[i * lWidth + j]; // 计算频谱 dTemp=255/(m_ColorMax[ncolor]-m_ColorMin[ncolor])*(dTemp-m_ColorMin[ncolor]); lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + 3*j+ncolor;// 指向DIB第i行,第j个象素的指针 * (lpSrc) = (BYTE)(dTemp);// 更新源图像 } } } } delete f;//释放内存 return TRUE;// 返回 } /************************************************************************* * * 函数名称: * DIBDisWavelet() * * 参数: * LPSTR lpDIB - 指向DIB图像指针 * LPSTR lpDIBBits - 指向源DIB象素指针 * double *LF - 使用的小波尺度函数,是常量 * double *HF - 使用的小波母函数,是常量 * int FWidth - 小波窗的宽度 * int nLevel - 小波分解的层数 * * 返回值: * BOOL - 成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数用来对图像进行小波变换重建。于上面不同的是,此处是将二维 * 矩阵转换成一个列向量,然后对该列向量进行一次一维小波变换。 * ************************************************************************/ BOOL CWaveTranform::DIBDisWavelet(LPSTR lpDIB,LPSTR lpDIBBits,double* LF,double* HF,int FWidth,int nLevel) { unsigned char* lpSrc;// 指向源图像的指针 double dTemp;// 中间变量 LONG lLineBytes; // 图像每行的字节数 LONG lWidth,lHeight; lWidth=::DIBWidth(lpDIB); lHeight=::DIBHeight(lpDIB); LONG i,j;//循环变量 double *f = new double[lWidth*lHeight];// 分配内存 if(::DIBNumColors(lpDIB)==256) { lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数 // 从源图像中读取数据。 for(i = 0; i < lHeight; i++)// 每列 { for(j = 0; j < lWidth; j++)// 每行 { lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) +j; // 指向DIB第i行,第j个象素的指针 f[i*lWidth+j] = *(lpSrc);// 给时域赋值 //将规划处理后的值变回原样 f[i*lWidth+j]=(m_GrayMax-m_GrayMin)/255*f[i*lWidth+j]+m_GrayMin; } } int n;//层数循环变量 //小波变换重建过程循环 for(n=nLevel-1;n>=0;n--) { LONG Height,Width; Height=long(lHeight/pow(2,n)); Width=long(lWidth/pow(2,n)); double *H00=new double[Height]; //按列存放低低元素 double *H01=new double[Height]; //按列存放低高元素 double *H10=new double[Height]; //按列存放高低元素 double *H11=new double[Height]; //按列存放高高元素 for(i = 0; i < Width/2; i++) { for(j=0;j<Height/2;j++) { H00[2*j]=f[i+j*lWidth]; H00[2*j+1]=0; } for(j=Height/2;j<Height;j++) { H01[2*j-Height]=f[i+j*lWidth]; H01[2*j-Height+1]=0; } DisConvolution( LF,HF, FWidth,H00,H01 ,Height);// 对y方向进行解内积运算 for(j=0;j<Height;j++) { f[i+j*lWidth]=H00[j]; } } for(i =Width/2 ; i < Width; i++) { for(j=0;j<Height/2;j++) { H10[2*j]=f[i+j*lWidth]; H10[2*j+1]=0; } for(j=Height/2;j<Height;j++) { H11[2*j-Height]=f[i+j*lWidth]; H11[2*j-Height+1]=0; } DisConvolution( LF,HF, FWidth,H10,H11, Height); // 对y方向进行解内积运算 for(j=0;j<Height;j++) { f[i+j*lWidth]=H10[j]; } } delete H00,H01,H10,H11;//释放内存 double *H0=new double[Width]; //按行存放低元素 double *H1=new double[Width]; //按行存放高元素 for(i = 0; i < Height; i++) { for(j=0;j<Width/2;j++) { H0[2*j]=f[i*lWidth+j]; H0[2*j+1]=0; } for(j=Width/2;j<Width;j++) { H1[2*j-Width]=f[i*lWidth+j]; H1[2*j-Width+1]=0; } DisConvolution( LF,HF, FWidth,H0,H1, Width);// 对x方向进行解卷积运算 for(j=0;j<Width;j++) { f[i*lWidth+j]=H0[j]; } } delete H0,H1; } // 更新源图像 for(i = 0; i < lHeight; i++)// 每列 { for(j = 0; j < lWidth; j++)// 每行 { dTemp = f[i * lWidth + j]; // 计算频谱 if (dTemp > 255) dTemp = 255; if(dTemp < 0) dTemp=0; lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;// 指向DIB第i行,第j个象素的指针 * (lpSrc) = (BYTE)(dTemp);// 更新源图像 } } } else { int ncolor; for(ncolor=0;ncolor<3;ncolor++) { lLineBytes = WIDTHBYTES(lWidth * 24);// 计算图像每行的字节数 // 从源图像中读取数据。 for(i = 0; i < lHeight; i++)// 每列 { for(j = 0; j < lWidth; j++)// 每行 { lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) +3*j+ncolor; // 指向DIB第i行,第j个象素的指针 f[i*lWidth+j] = *(lpSrc);// 给时域赋值 //将规划处理后的值变回原样 f[i*lWidth+j]=(m_ColorMax[ncolor]-m_ColorMin[ncolor])/255*f[i*lWidth+j]+m_ColorMin[ncolor]; } } int n;//层数循环变量 //小波变换重建过程循环 for(n=nLevel-1;n>=0;n--) { LONG Height,Width; Height=long(lHeight/pow(2,n)); Width=long(lWidth/pow(2,n)); double *H00=new double[Height]; //按列存放低低元素 double *H01=new double[Height]; //按列存放低高元素 double *H10=new double[Height]; //按列存放高低元素 double *H11=new double[Height]; //按列存放高高元素 for(i = 0; i < Width/2; i++) { for(j=0;j<Height/2;j++) { H00[2*j]=f[i+j*lWidth]; H00[2*j+1]=0; } for(j=Height/2;j<Height;j++) { H01[2*j-Height]=f[i+j*lWidth]; H01[2*j-Height+1]=0; } DisConvolution( LF,HF, FWidth,H00,H01 ,Height);// 对y方向进行解内积运算 for(j=0;j<Height;j++) { f[i+j*lWidth]=H00[j]; } } for(i =Width/2 ; i < Width; i++) { for(j=0;j<Height/2;j++) { H10[2*j]=f[i+j*lWidth]; H10[2*j+1]=0; } for(j=Height/2;j<Height;j++) { H11[2*j-Height]=f[i+j*lWidth]; H11[2*j-Height+1]=0; } DisConvolution( LF,HF, FWidth,H10,H11, Height); // 对y方向进行解内积运算 for(j=0;j<Height;j++) { f[i+j*lWidth]=H10[j]; } } delete H00,H01,H10,H11;//释放内存 double *H0=new double[Width]; //按行存放低元素 double *H1=new double[Width]; //按行存放高元素 for(i = 0; i < Height; i++) { for(j=0;j<Width/2;j++) { H0[2*j]=f[i*lWidth+j]; H0[2*j+1]=0; } for(j=Width/2;j<Width;j++) { H1[2*j-Width]=f[i*lWidth+j]; H1[2*j-Width+1]=0; } DisConvolution( LF,HF, FWidth,H0,H1, Width);// 对x方向进行解卷积运算 for(j=0;j<Width;j++) { f[i*lWidth+j]=H0[j]; } } delete H0,H1; } // 更新源图像 for(i = 0; i < lHeight; i++)// 每列 { for(j = 0; j < lWidth; j++)// 每行 { dTemp = f[i * lWidth + j]; // 计算频谱 if (dTemp > 255) dTemp = 255; if(dTemp < 0) dTemp=0; lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + 3*j+ncolor;// 指向DIB第i行,第j个象素的指针 * (lpSrc) = (BYTE)(dTemp);// 更新源图像 } } } } delete f;//释放内存 return TRUE;// 返回 } /************************************************************************* * * 函数名称: * DIBQuantize() * * 参数: * LPSTR lpDIB - 指向DIB图像指针 * LPSTR lpDIBBits - 指向源DIB象素指针 * int Thredhold - 小波窗的宽度 * * 返回值: * BOOL - 成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数用来对小波变换后的图像进行量化 * ************************************************************************/ BOOL CWaveTranform::DIBQuantize(LPSTR lpDIB,LPSTR lpDIBBits,int* Thredhold) { unsigned char* lpSrc;// 指向源图像的指针 double dTemp;// 中间变量 LONG lLineBytes; // 图像每行的字节数 LONG lWidth,lHeight; lWidth=::DIBWidth(lpDIB); lHeight=::DIBHeight(lpDIB); LONG i,j;//循环变量 if(::DIBNumColors(lpDIB)==256) { lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数 // 从源图像中读取数据。 for(i = 0; i < lHeight; i++)// 每列 { for(j = 0; j < lWidth; j++)// 每行 { lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) +j; // 指向DIB第i行,第j个象素的指针 dTemp =*(lpSrc) ; dTemp=(m_GrayMax-m_GrayMin)/255*dTemp+m_GrayMin; if(fabs(dTemp) < *Thredhold) dTemp= 0; lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;// 指向DIB第i行,第j个象素的指针 dTemp=255/(m_GrayMax-m_GrayMin)*(dTemp-m_GrayMin); * (lpSrc) = (BYTE)(dTemp);// 更新源图像 } } } else { int ncolor; for(ncolor=0;ncolor<3;ncolor++) { lLineBytes = WIDTHBYTES(lWidth * 24);// 计算图像每行的字节数 // 从源图像中读取数据。 for(i = 0; i < lHeight; i++)// 每列 { for(j = 0; j < lWidth; j++)// 每行 { lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) +3*j+ncolor; // 指向DIB第i行,第j个象素的指针 dTemp = *(lpSrc); dTemp=(m_ColorMax[ncolor]-m_ColorMin[ncolor])/255*dTemp+m_ColorMin[ncolor]; if(fabs(dTemp) < Thredhold[ncolor]) dTemp= 0; lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + 3*j+ncolor;// 指向DIB第i行,第j个象素的指针 dTemp=255/(m_ColorMax[ncolor]-m_ColorMin[ncolor])*(dTemp-m_ColorMin[ncolor]); * (lpSrc) = (BYTE)(dTemp);// 更新源图像 } } } } return TRUE;// 返回 }