www.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;// 返回
}