FFT

原理就不说了 我相信代码可以说明一切。另外如果像素不够,可以读颜色表。。。代码自己去搜索,

 

#include "stdio.h"
#include "Windows.h"

#include "math.h"
#define PI 3.1415926
//几个全局变量,存放读入图像的位图数据、宽、高、颜色表及每像素所占位数(比特) 
//此处定义全局变量主要为了后面的图像数据访问及图像存储作准备
unsigned char *pBmpBufIn=NULL;//读入图像数据的指针
unsigned char *pBmpBufOut=NULL;//输出图像数据的指针

int bmpWidthIn;//输入图像的宽
int bmpHeightIn;//输入图像的高
int bmpWidthOut;
int bmpHeightOut;

RGBQUAD *pColorTable;//颜色表指针
int biBitCountIn;//输入图像类型


int biBitCountOut;//输出图像类型

struct ComplexNumber
{
 float imag;// imaginary虚部
 float real;//实部
};

ComplexNumber *m_pFFTBuf;

/***********************************************************************
* 函数名称:
* readBmp()
*
*函数参数:
*  char *bmpName -文件名字及路径
*
*返回值:
*   0为失败,1为成功
*
*说明:给定一个图像文件名及其路径,读图像的位图数据、宽、高、颜色表及每像素
*      位数等数据进内存,存放在相应的全局变量中
***********************************************************************/
bool readBmp(char *bmpName)
{
 //二进制读方式打开指定的图像文件
    FILE *fp=fopen(bmpName,"rb");
 if(fp==0) return 0;
 
 
 //跳过位图文件头结构BITMAPFILEHEADER
 fseek(fp, sizeof(BITMAPFILEHEADER),0);
 
 
 //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中
 BITMAPINFOHEADER head;  
 fread(&head, sizeof(BITMAPINFOHEADER), 1,fp); 
 
 //获取图像宽、高、每像素所占位数等信息
 bmpWidthIn = head.biWidth;
 bmpHeightIn = head.biHeight;
 biBitCountIn = head.biBitCount;
 
 //定义变量,计算图像每行像素所占的字节数(必须是4的倍数)
 int lineByte=(bmpWidthIn * biBitCountIn/8+3)/4*4;
 
 //灰度图像有颜色表,且颜色表表项为256
 if(biBitCountIn==8){
  //申请颜色表所需要的空间,读颜色表进内存
  pColorTable=new RGBQUAD[256];
  fread(pColorTable,sizeof(RGBQUAD),256,fp);
 }
 
 //申请位图数据所需要的空间,读位图数据进内存
 if(pBmpBufIn==NULL)
  pBmpBufIn=new unsigned char[lineByte * bmpHeightIn];
    fread(pBmpBufIn,1,lineByte * bmpHeightIn,fp);
 
 //关闭文件
 fclose(fp);
 
 return 1;
}

/***********************************************************************
* 函数名称:
* saveBmp()
*
*函数参数:
*  char *bmpName -文件名字及路径
*  unsigned char *imgBuf  -待存盘的位图数据
*  int width   -像素为单位待存盘位图的宽
*  int  height  -像素为单位待存盘位图高
*  int biBitCount   -每像素所占位数
*  RGBQUAD *pColorTable  -颜色表指针

*返回值:
*   0为失败,1为成功
*
*说明:给定一个图像位图数据、宽、高、颜色表指针及每像素所占的位数等信息,
*      将其写到指定文件中
***********************************************************************/
bool saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height, 
    int biBitCount, RGBQUAD *pColorTable)
{
 //如果位图数据指针为0,则没有数据传入,函数返回
 if(!imgBuf)
  return 0;
 
 //颜色表大小,以字节为单位,灰度图像颜色表为1024字节,彩色图像颜色表大小为0
 int colorTablesize=0;
 if(biBitCount==8)
  colorTablesize=1024;

 //待存储图像数据每行字节数为4的倍数
 int lineByte=(width * biBitCount/8+3)/4*4;
 
 //以二进制写的方式打开文件
 FILE *fp=fopen(bmpName,"wb");
 if(fp==0) return 0;
 
 //申请位图文件头结构变量,填写文件头信息
 BITMAPFILEHEADER fileHead;
 fileHead.bfType = 0x4D42;//bmp类型
 
 //bfSize是图像文件4个组成部分之和
 fileHead.bfSize= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
  + colorTablesize + lineByte*height;
 fileHead.bfReserved1 = 0;
 fileHead.bfReserved2 = 0;
 
 //bfOffBits是图像文件前三个部分所需空间之和
 fileHead.bfOffBits=54+colorTablesize;
 
 //写文件头进文件
 fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp);
 
 //申请位图信息头结构变量,填写信息头信息
 BITMAPINFOHEADER head; 
 head.biBitCount=biBitCount;
 head.biClrImportant=0;
 head.biClrUsed=0;
 head.biCompression=0;
 head.biHeight=height;
 head.biPlanes=1;
 head.biSize=40;
 head.biSizeImage=lineByte*height;
 head.biWidth=width;
 head.biXPelsPerMeter=0;
 head.biYPelsPerMeter=0;
 //写位图信息头进内存
 fwrite(&head, sizeof(BITMAPINFOHEADER),1, fp);
 
 //如果灰度图像,有颜色表,写入文件 
 if(biBitCount==8)
  fwrite(pColorTable, sizeof(RGBQUAD),256, fp);
 
 //写位图数据进文件
 fwrite(imgBuf, height*lineByte, 1, fp);
 
 //关闭文件
 fclose(fp);
 
 return 1;
}


void FFT1D(ComplexNumber *arrayBuf, int n)
{
 //循环变量
 int i, k, r;

 //申请临时复数缓冲区buf1,长度为n
 ComplexNumber *buf1=new ComplexNumber[n];

 //将arrayBuf拷贝进buf1
 memcpy(buf1,arrayBuf,sizeof(ComplexNumber)*n);

 //申请临时复数缓冲区buf2,长度为n
 ComplexNumber *buf2=new ComplexNumber[n];

 //将arrayBuf数组元素基2抽取并重新排列
 //若0、1、2、3、4、5、6、7八点序列对调后变作0、4、2、6、1、5、3、7
 int t1,t2;
 for(r=1;pow(double(2),r)<n;r++){
  t1=pow(double(2),r);
  t2=pow(double(2),r-1);
  for(k=0;k<t1;k++){
   for(i=0;i<n/t1;i++){
    buf2[k*n/t1+i].real=buf1[k/2*n/t2+i*2+k%2].real;
    buf2[k*n/t1+i].imag=buf1[k/2*n/t2+i*2+k%2].imag;
   }
  }
  memcpy(buf1,buf2,sizeof(ComplexNumber)*n);
 }


 //采用蝶型算法进行快速傅立叶变换
 //buf1是第r级的输入,buf2存放第r级的输出
 float c,s;
 for(r=1;pow(double(2),r)<=n;r++){
  t1=pow(double(2),r);
  for(k=0;k<n/t1;k++){
   for(i=t1/2;i<t1;i++){
    //加权因子
    c=cos(-2*PI*(i-t1/2)/t1);
    s=sin(-2*PI*(i-t1/2)/t1);
    buf1[k*t1+i].real= buf2[k*t1+i].real*c - buf2[k*t1+i].imag*s;
    buf1[k*t1+i].imag=buf2[k*t1+i].imag*c+buf2[k*t1+i].real*s;
   }
  }
  for(k=0; k<n/t1; k++){
   for(i=0;i<t1/2;i++){
    buf2[k*t1+i].real= buf1[k*t1+i].real+buf1[k*t1+i+t1/2].real;
    buf2[k*t1+i].imag= buf1[k*t1+i].imag+buf1[k*t1+i+t1/2].imag;
   }
   for(i=t1/2;i<t1;i++){
    buf2[k*t1+i].real= buf1[k*t1+i-t1/2].real-buf1[k*t1+i].real;
    buf2[k*t1+i].imag= buf1[k*t1+i-t1/2].imag-buf1[k*t1+i].imag;
   }
  }

  //第r级的输出存入buf1,作为下一级的输入数据
  memcpy(buf1,buf2,sizeof(ComplexNumber)*n);
 }
 

 //傅立叶变换的结果存入arrayBuf
 memcpy(arrayBuf,buf2,sizeof(ComplexNumber)*n);

 //释放缓冲区
 delete[]buf2;
 delete[]buf1;

 

}

 

 

 

void  ImgFFT2D(unsigned char* imgBuf, int width, int height,
        unsigned char *imgBufOut)
{

 //循环变量
 int i, j, u, v;

 //图像数据变成复数类型存入m_pFFTBuf
 for(i=0;i<width*height;i++){
  m_pFFTBuf[i].real=imgBuf[i];
  m_pFFTBuf[i].imag=0;
 }

 //申请ComplexNumber结构体数组,长度为height
 ComplexNumber *array=new ComplexNumber[height];

 //先纵向一维快速傅立叶变换
 for(u=0;u<width;u++){
  for(v=0;v<height;v++){
   array[v].real=m_pFFTBuf[v*width+u].real;
   array[v].imag=m_pFFTBuf[v*width+u].imag;
  }
  FFT1D(array, height);
  for(v=0;v<height;v++){
   m_pFFTBuf[v*width+u].real=array[v].real;
   m_pFFTBuf[v*width+u].imag=array[v].imag;
  }
 }
 delete []array;

 //再横向一维快速傅立叶变换
 for(v=0;v<height;v++){
  FFT1D(m_pFFTBuf+v*width, width);
 }

 //将频谱图以图像形式存入imgBufOut
 float t;
 int i0,j0;
 for(i=0;i<height;i++){
  //i0 = i;
  //j0 = j;
  for(j=0;j<width;j++){
   if(i<height/2)
    i0=i+height/2;
   else
    i0=i-height/2;
   if(j<width/2)
    j0=j+width/2;
   else
    j0=j-width/2;
   
   t=sqrt(m_pFFTBuf[i0*width+j0].real*m_pFFTBuf[i0*width+j0].real
    +m_pFFTBuf[i0*width+j0].imag*m_pFFTBuf[i0*width+j0].imag);
   t=t/500;
   if(t>255)
    imgBufOut[i*width+j]=255;
   else 
    imgBufOut[i*width+j]=t;
  }
 }

 


}

 

 

 

void Fourier()
{
   char readPath[100];
   strcpy(readPath,"lena.bmp");
   readBmp(readPath);
   bmpWidthOut=bmpWidthIn;
   bmpHeightOut=bmpHeightIn;
   biBitCountOut=biBitCountIn;
   pBmpBufOut=new unsigned char[bmpHeightOut*bmpWidthOut];
   memset(pBmpBufOut,0,bmpHeightOut*bmpWidthOut);
   m_pFFTBuf=new ComplexNumber[bmpHeightOut*bmpWidthOut];
   memset(m_pFFTBuf,0,sizeof(ComplexNumber)*bmpWidthOut*bmpHeightOut);
   ImgFFT2D(pBmpBufIn,bmpWidthOut,bmpHeightOut,pBmpBufOut);

 


}

 

 

 

void main()
{
 
 Fourier();

    //将图像数据存盘
 char writePath[]="22.BMP";
 saveBmp(writePath, pBmpBufOut, bmpWidthOut, bmpHeightOut, biBitCountOut, pColorTable);
    
 //清除缓冲区,pBmpBuf和pColorTable是全局变量,在文件读入时申请的空间
 delete []pBmpBufIn;
 delete []pBmpBufOut;
 delete []pColorTable;
}


 
 
 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值