首页 > 代码库 > 图像处理之基础---不同小波基的小波变换(卷积)
图像处理之基础---不同小波基的小波变换(卷积)
#include <stdio.h>
#include <stdlib.h>
#include <cv.h>
#include <highgui.h>
#include <math.h>
#define WIN_WIDTH 1//1~10,选择小波基
double *Ld = new double[2*WIN_WIDTH]; //分解尺度函数
double *Hd = new double[2*WIN_WIDTH]; //分解母函数
double *Lr = new double[2*WIN_WIDTH]; //重建尺度函数
double *Hr = new double[2*WIN_WIDTH]; //重建母函数
int m_preoffset;
int m_aftoffset;
double m_GrayMax=0;
double m_GrayMin=255;
BOOL Wavelet(double *image,int FWidth,int nLevel, int width, int hight);
BOOL DisWavelet(double *image,int FWidth,int nLevel, int width, int hight);
void main()
{
int FWidth =2*WIN_WIDTH;
// 小波变换层数
int nLayer = 1;
// 输入彩色图像
IplImage *pSrc = http://www.mamicode.com/cvLoadImage("1.bmp", CV_LOAD_IMAGE_GRAYSCALE);
if(!pSrc)
exit(1);
//cvSaveImage("222.bmp",pSrc);
// 计算小波图象大小
int height = ((pSrc->height)>>nLayer)<<nLayer;
int width = ((pSrc->width)>>nLayer)<<nLayer;
// 创建小波图象
cvNamedWindow("1",1);
cvShowImage("1",pSrc);
//cvWaitKey(0);
IplImage *pWavelet = cvCreateImage(cvGetSize(pSrc), IPL_DEPTH_32F, 1);
IplImage *image = cvCreateImage(cvGetSize(pSrc), IPL_DEPTH_8U, 1);
double *pMatrix = new double[height*width];
int temp = 0;
int temp1 = 0;
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
pMatrix[i*width + j] = 0.0;
temp1 = (unsigned char)(*(pSrc->imageData+i*pSrc->widthStep+j));
pMatrix[i*width + j] = (double)(temp1);
}
}
{
Wavelet(pMatrix, FWidth,1, width, height);
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
temp = (int)(pMatrix[i*width + j]);
if(temp < 0)
temp = 0;//abs(temp);
if(temp > 255)
temp = 255;
*(image->imageData+i*image->widthStep+j) = (unsigned char)temp;
}
}
cvNamedWindow("12",1);
cvShowImage("12",image);
cvWaitKey(0);
DisWavelet(pMatrix, FWidth,1, width, height);
}
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
temp = (int)(pMatrix[i*width + j]);
if(temp < 0)
temp = 0;//abs(temp);
if(temp > 255)
temp = 255;
*(image->imageData+i*image->widthStep+j) = (unsigned char)temp;
}
}
delete pMatrix;
cvNamedWindow("123",1);
cvShowImage("123",image);
cvWaitKey(0);
cvReleaseImage(&pWavelet);
return ;
}
/*************************************************************************
*
* 函数名称:
* Convolution()
*
* 参数:
* double * LF HF - 指向小波的指针,是常量
* FR - 小波窗的宽度
* double * f - 指向时域值的指针和返回的小波变换频域的指针
* fr -原图象宽
* 说明:
* 该函数用来实现卷积运算。
*
************************************************************************/
void 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 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()
* 参数:
* double *LF - 使用的小波尺度函数,是常量
* double *HF - 使用的小波母函数,是常量
* int FWidth - 小波窗的宽度
* int nLevel - 小波分解的层数
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来对图像进行小波变换分解。
************************************************************************/
BOOL Wavelet( double *f,int FWidth,int nLevel, int width, int hight)
{
//生成小波分解和重建的尺度函数和母函数
switch(FWidth)
{
case 2:
Ld[0]=1/sqrt(2.0f); Ld[1]=1/sqrt(2.0f);
m_preoffset=0;
m_aftoffset=1;
break;
case 4:
Ld[0]=0.4829629131445341; Ld[1]=0.8365163037378077; Ld[2]=0.2241438680420134;
Ld[3]=-0.1294095225512603;
m_preoffset=1;
m_aftoffset=2;
break;
case 6:
Ld[0]=0.3326705529500825; Ld[1]=0.8068915093110924; Ld[2]=0.4598775021184914;
Ld[3]=-0.1350110200102546; Ld[4]=-0.0854412738820267; Ld[5]=0.035226218857095;
m_preoffset=2;
m_aftoffset=3;
break;
case 8:
Ld[0]=-0.107148901418/sqrt(2.0); Ld[1]=-0.041910965126/sqrt(2.0); Ld[2]=0.703739068656/sqrt(2.0);
Ld[3]=1.136658243409/sqrt(2.0); Ld[4]=0.421234534204/sqrt(2.0); Ld[5]=-0.140317624179/sqrt(2.0);
Ld[6]=-0.017824701442/sqrt(2.0); Ld[7]=0.045570345896/sqrt(2.0);
m_preoffset=3;
m_aftoffset=4;
break;
case 10:
Ld[0]=0.038654795955/sqrt(2.0); Ld[1]=0.041746864422/sqrt(2.0); Ld[2]=-0.055344186117/sqrt(2.0);
Ld[3]=0.281990696854/sqrt(2.0); Ld[4]=1.023052966894/sqrt(2.0); Ld[5]=0.896581648380/sqrt(2.0);
Ld[6]=0.023478923136/sqrt(2.0); Ld[7]=-0.247951362613/sqrt(2.0); Ld[8]=-0.029842499869/sqrt(2.0);
Ld[9]=0.027632152958/sqrt(2.0);
m_preoffset=4;
m_aftoffset=5;
break;
case 12:
Ld[0]=0.021784700327/sqrt(2.0); Ld[1]=0.004936612372/sqrt(2.0); Ld[2]=-0.166863215412/sqrt(2.0);
Ld[3]=-0.068323121587/sqrt(2.0); Ld[4]=0.0694457972958/sqrt(2.0); Ld[5]=1.113892783926/sqrt(2.0);
Ld[6]=0.477904371333/sqrt(2.0); Ld[7]=-0.102724969862/sqrt(2.0); Ld[8]=-0.029783751299/sqrt(2.0);
Ld[9]=0.063250562660/sqrt(2.0); Ld[10]=0.002499922093/sqrt(2.0); Ld[11]=-0.011031867509/sqrt(2.0);
m_preoffset=5;
m_aftoffset=6;
break;
case 14:
Ld[0]=0.003792658534/sqrt(2.0); Ld[1]=-0.001481225915/sqrt(2.0); Ld[2]=-0.017870431651/sqrt(2.0);
Ld[3]=0.043155452582/sqrt(2.0); Ld[4]=0.096014767936/sqrt(2.0); Ld[5]=-0.070078291222/sqrt(2.0);
Ld[6]=0.024665659489/sqrt(2.0); Ld[7]=0.758162601964/sqrt(2.0); Ld[8]=1.085782709814/sqrt(2.0);
Ld[9]=0.408183939725/sqrt(2.0); Ld[10]=-0.198056706807/sqrt(2.0); Ld[11]=-0.152463872896/sqrt(2.0);
Ld[12]=0.005671342686/sqrt(2.0); Ld[13]=0.014521394762/sqrt(2.0);
m_preoffset=7;
m_aftoffset=6;
break;
case 16:
Ld[0]=0.002672793393/sqrt(2.0); Ld[1]=-0.000428394300/sqrt(2.0); Ld[2]=-0.021145686528/sqrt(2.0);
Ld[3]=0.005386388754/sqrt(2.0); Ld[4]=0.069490465911/sqrt(2.0); Ld[5]=-0.038493521263/sqrt(2.0);
Ld[6]=-0.073462508761/sqrt(2.0); Ld[7]=0.515398670374/sqrt(2.0); Ld[8]=1.099106630537/sqrt(2.0);
Ld[9]=0.680745347190/sqrt(2.0); Ld[10]=-0.086653615406/sqrt(2.0); Ld[11]=-0.202648655286/sqrt(2.0);
Ld[12]=0.010758611751/sqrt(2.0); Ld[13]=0.044823623042/sqrt(2.0); Ld[14]=-0.000766690896/sqrt(2.0);
Ld[15]=-0.004783458512/sqrt(2.0);
m_preoffset=8;
m_aftoffset=7;
break;
case 18:
Ld[0]=0.001512487309/sqrt(2.0); Ld[1]=-0.000669141509/sqrt(2.0); Ld[2]=-0.014515578553/sqrt(2.0);
Ld[3]=0.012528896242/sqrt(2.0); Ld[4]=0.087791251554/sqrt(2.0); Ld[5]=-0.025786445930/sqrt(2.0);
Ld[6]=-0.270893783503/sqrt(2.0); Ld[7]=0.049882830959/sqrt(2.0); Ld[8]=0.873048407349/sqrt(2.0);
Ld[9]=1.015259790832/sqrt(2.0); Ld[10]=0.337658923602/sqrt(2.0); Ld[11]=-0.077172161097/sqrt(2.0);
Ld[12]=0.000825140929/sqrt(2.0); Ld[13]=0.042744433602/sqrt(2.0); Ld[14]=-0.016303351226/sqrt(2.0);
Ld[15]=-0.018769396836/sqrt(2.0); Ld[16]=0.000876502539/sqrt(2.0); Ld[17]=0.001981193736/sqrt(2.0);
m_preoffset=8;
m_aftoffset=9;
break;
case 20:
Ld[0]=0.001089170447/sqrt(2.0); Ld[1]=0.000135245020/sqrt(2.0); Ld[2]=-0.012220642630/sqrt(2.0);
Ld[3]=-0.002072363923/sqrt(2.0); Ld[4]=0.064950924579/sqrt(2.0); Ld[5]=0.016418869426/sqrt(2.0);
Ld[6]=-0.225558972234/sqrt(2.0); Ld[7]=-0.100240215031/sqrt(2.0); Ld[8]=0.667071338154/sqrt(2.0);
Ld[9]=1.088251530500/sqrt(2.0); Ld[10]=0.542813011213/sqrt(2.0); Ld[11]=-0.050256540092/sqrt(2.0);
Ld[12]=-0.045240772218/sqrt(2.0); Ld[13]=0.070703567550/sqrt(2.0); Ld[14]=0.008152816799/sqrt(2.0);
Ld[15]=-0.028786231926/sqrt(2.0); Ld[16]=-0.001137535314/sqrt(2.0); Ld[17]=0.006495728375/sqrt(2.0);
Ld[18]=0.000080661204/sqrt(2.0); Ld[19]=-0.000649589896/sqrt(2.0);
m_preoffset=9;
m_aftoffset=10;
break;
default:
printf("错误的窗口尺寸\n");
//break;
}
for(int i=0;i<FWidth;i++)
{
Hd[i]=pow(-1.0,i+1)*Ld[-i-1+FWidth];
}
for(int i=0;i<FWidth;i++)
{
Lr[i]=Ld[-i-1+FWidth];
Hr[i]=Hd[-i-1+FWidth];
}
//小波分解
LONG lWidth, lHeight;
lWidth=width;
lHeight=hight;
LONG i,j;//循环变量
{
int n;//层数循环变量
//小波变换分解过程循环
for(n=0;n<nLevel;n++)
{
LONG Height,Width;//第n层图象的高度和宽度
Height=long(lHeight>>n);
Width=long(lWidth>>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( Ld,Hd, 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( Ld,Hd, FWidth,LH, Height);// 对y方向进行卷积运算
for(j=0;j<Height;j++)
{
f[i+j*lWidth]=LH[j];
}
}
delete LH;//释放内存
}
{//显示小波变换后的图像需要将数值归一化
//将分解后的值规划处理
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];
}
}
// 更新源图像
double Temp;// 中间变量
Temp=255.0/(m_GrayMax-m_GrayMin);
for(i = 0; i < lHeight; i++)// 每列
{
for(j = 0; j < lWidth; j++)// 每行
{
double dTemp;// 中间变量
dTemp = f[i * lWidth + j]; // 计算频谱
dTemp=Temp*(dTemp-m_GrayMin);
f[i * lWidth + j] = dTemp;// 更新源图像
}
}
}
}
return TRUE;// 返回
}
/*************************************************************************
*
* 函数名称:
* DIBDisWavelet()
* 参数:
* double *LF - 使用的小波尺度函数,是常量
* double *HF - 使用的小波母函数,是常量
* int FWidth - 小波窗的宽度
* int nLevel - 小波分解的层数
* 说明:
* 该函数用来对图像进行小波变换重建。
************************************************************************/
BOOL DisWavelet(double *f,int FWidth,int nLevel, int width, int hight)
{
double dTemp;// 中间变量
LONG lWidth,lHeight;
lWidth=width;
lHeight=hight;
LONG i,j;//循环变量
{
// 从源图像中读取数据。
for(i = 0; i < lHeight; i++)// 每列
{
for(j = 0; j < lWidth; j++)// 每行
{
//f[i*lWidth+j] = image[i*lWidth+j];// 给时域赋值
//将规划处理后的值变回原样
f[i*lWidth+j]=(m_GrayMax-m_GrayMin)/255*f[i*lWidth+j]+m_GrayMin;
}
}
int n = 0;//层数循环变量
{
LONG Height,Width;
Height=long(lHeight>>n);
Width=long(lWidth>>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( Lr,Hr, 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( Lr,Hr, 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( Lr,Hr, FWidth,H0,H1, Width);// 对x方向进行解卷积运算
for(j=0;j<Width;j++)
{
f[i*lWidth+j]=H0[j];
}
}
delete H0,H1;
}
}
return TRUE;// 返回
}
http://blog.csdn.net/songhhll/article/details/8129849
http://blog.csdn.net/songhhll/article/category/1207475
图像处理之基础---不同小波基的小波变换(卷积)