图像处理之基础---不同小波基的小波变换(卷积)

#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 = 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

posted @ 2014-10-17 12:06  midu  阅读(1453)  评论(0编辑  收藏  举报