⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fft.cpp

📁 fft傅立叶快速变换在图象处理方面的应用
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	bPlus=true;bNeg=true;
	//startPlus=base+offset+nCenterPlus;
	//startNeg=base+offset-nCenterNeg;

	if(meanPlus-theshold<0.00001 )
	{
		//peakPlus=0;
		startPlus=base+offset+20;
		//bPlus=false;
	}
	else
	{
		startPlus=base+offset+nCenterPlus;
		//bPlus=true;
		
	}
	if(meanNeg-theshold<0.00001)
	{
		//peakNeg=0;
		startNeg=base+offset;
		//bNeg=false;
	}
	else
	{
		startNeg=base+offset-nCenterNeg;
		//bNeg=true;
		
	}

	//3.峰值分析,点包络,从质心位置开始搜索,当前仅求正向包络,注意:算法要避免死循环
	cntPlus=0,cntNeg=0;
	if(bPlus)
	{
		//peakPlus=nCenterPlus;
		for(i=startPlus;i<255;i++)
		{
			if(cntPlus>5)
			{
				peakPlus=i-(base+offset)-cntPlus;//包络点到基线的距离
				break;
			}
			else
			{
				peakPlus=i-(base+offset);
			}
			
			if(smooth[i]-meanPlus*1.3<0.000001)//阈值如何选取
			{
				cntPlus++;
			}
			else//保证检测的是连续点
			{
				if(--cntPlus<0)
					cntPlus=0;
			}
			
		}

	}
	if(bNeg)
	{
		//for(i=base+offset;i>=/*base+offset-nCenterNeg*/0;i--)
		for(i=startNeg;i>=0;i--)
		{
			if(cntNeg>5)
			{
				peakNeg=(base+offset)-(i+cntNeg);
				break;
			}
			else
			{
				peakNeg=(base+offset)-i;
			}
			if(smooth[i]-meanNeg*1.3<0.000001)
			{
				cntNeg++;
			}
			else
			{
				if(--cntNeg<0)
					cntNeg=0;
			}
		}
	}
	//cover=((nCenterPlus&0xffff)<<8)+nCenterNeg;
	cover=((peakPlus&0xffff)<<8)+peakNeg;
	return cover;
}

/**************************************************************************************
                    包络中值滤波算法  by Jim Fang at 2007

  对前后的七个包络点和前一运算的中值点,共8点进行中值滤波
**************************************************************************************/
int WINAPI Jim_Mean(int *pTemp,int no)
{
	int tmp[8];

	int m,k,j,i,d;
	k=0; 
	m=no-1;
	for(i=0;i<8;i++)
	{
		tmp[i]=pTemp[i];
	}
	while (k<m)
	{ 
		j=m-1; m=0;
		for (i=k; i<=j; i++)
			if (tmp[i]>tmp[i+1])
			{ 
				d=tmp[i]; tmp[i]=tmp[i+1]; tmp[i+1]=d; m=i;
			}
		j=k+1; k=0;
		for (i=m; i>=j; i--)
			if (tmp[i-1]>tmp[i])
			{ 
				d=tmp[i]; tmp[i]=tmp[i-1]; tmp[i-1]=d; k=i;
			}
	}
	//取中值输出,用于滤除包络点的奇异点
	//return tmp[4];
	return int((tmp[2]+tmp[3]+tmp[4]+tmp[5])/4.0);
}

/**************************************************************************************
                    图像增强算法  by Jim Fang at 2007

	根据包络的位置,增强包络内的图像,消弱包络外的图像
	实际检测中会出现双向血流的情况,为避免误操作,需要对基线上下的能量进行对比
**************************************************************************************/
void WINAPI	Jim_Boost(void *pSrcData,void *pDstData,int coverP,int coverN,int base,int splus,int image,double dnr,int method)
{
	unsigned char *srcPtr =(unsigned char *)pSrcData;
	unsigned char *dstPtr =(unsigned char *)pDstData;
	int i,nBoostDir;
	double nZoom,temp;
	double powerPlus=0.0,powerNeg=0.0;

	for(i=base-coverN;i<base;i++)
		powerNeg+=srcPtr[i];
	for(i=base;i<base+coverP;i++)
		powerPlus+=srcPtr[i];

	//判断需要增强的是正向还是负向
	if(powerPlus/powerNeg>dnr)
		nBoostDir=1;
	else if(powerPlus/powerNeg>(1.0/dnr))
		nBoostDir=0;
	else
		nBoostDir=2;


	if(nBoostDir==1)
	{
		for(i=0;i<fft_point;i++)
		{
			if(i>base+coverP)
			{
				dstPtr[i]=srcPtr[i];
			}
			
			else if(i>=base)
			{
				nZoom=1+splus*0.1;
				//注意数制转换存在的bug
				temp=srcPtr[i]*nZoom;
				if(temp-255>0.000001)
					dstPtr[i]=255;
				else
					dstPtr[i]=unsigned char(temp);
				
			}
			else//图象增强,将包络外的能量衰减,包络内的能量不变
			{
				nZoom=1-image*0.1;
				//注意数制转换存在的bug
				temp=srcPtr[i]*nZoom;
				if(temp-255>0.000001)
					dstPtr[i]=255;
				else
					dstPtr[i]=unsigned char(temp);
				
			}
		}
	}
	else if(nBoostDir==2)
	{
		for(i=0;i<fft_point;i++)
		{
			if(i<base-coverN)
			{
				dstPtr[i]=srcPtr[i];
			}
			
			else if(i<=base)
			{
				nZoom=1+splus*0.1;
				//注意数制转换存在的bug
				temp=srcPtr[i]*nZoom;
				if(temp-255>0.000001)
					dstPtr[i]=255;
				else
					dstPtr[i]=unsigned char(temp);
				
			}
			else//图象增强,将包络外的能量衰减,包络内的能量不变
			{
				nZoom=1-image*0.1;
				//注意数制转换存在的bug
				temp=srcPtr[i]*nZoom;
				if(temp-255>0.000001)
					dstPtr[i]=255;
				else
					dstPtr[i]=unsigned char(temp);
				
			}
		}
	}
	else
	{
		for(i=0;i<fft_point;i++)
		{
			dstPtr[i]=srcPtr[i];
		}
	}
	
}

/**************************************************************************************
                    趋势包络算法  by Jim Fang at 2007

	判断目标点dst和源点src的关系,控制包络的变化率
**************************************************************************************/
int WINAPI Jim_TrendCover(int src,int dst,double scale,int nTrend)
{
	int k;
	//scale=1.0;
	int varRise,varFall,nTrendLimit=5;
	varRise=int(50*scale);
	varFall=int(5.0*scale);//int(3*scale);

	if(nTrend>=0)
	{
		k=src+(nTrend+1)*varRise;
		//限制变化率
		if(dst>k)
		{
			dst=k;
		}
		else if(dst<src-varRise)
		{
			dst=src-varRise;
		}
	}
	else 
	{
		k = src + (nTrend-1) * varFall ;
		if ( dst < k ) 
		{
			dst = k ;
		} 
		else if ( dst > src + varFall )
		{
			dst = src + varFall ;
		}
	}
/*
	if ( src > dst ) 
	{
		if ( --nTrend < -1*nTrendLimit ) 
		{
			nTrend = -1*nTrendLimit ;
		}
	} 
	else if (src < dst) 
	{
		if ( ++nTrend > nTrendLimit )
		{
			nTrend = nTrendLimit ;
		}
	}
*/
	return dst;
}

/**************************************************************************************
                    FFT算法(Fourier Transform)  by Jim Fang at 2007
							    (Based on the priciple of Coolkey-Tukey)
	pr---双精度实型一维数组,长度为n
	     当l=0时,存放n个采样输入的实部,返回时存放离散傅立叶变换的模
		 当l=1时,存放傅立叶变换的n个实部,返回时存放逆傅立叶变换的模
	pi---双精度实型一维数组,长度为n
		 当l=0时,存放n个采样输入的虚部,返回时存放离散傅立叶变换的幅角
		 当l=1时,存放傅立叶变换的n个虚部,返回时存放逆傅立叶变换的幅角(幅角单位为度)
	n----整型变量,输入的点数
	k----整型变量,满足n=2^k
	fr---双精度实型一维数组,长度为n
		 当l=0时,返回傅立叶变换的实部
		 当l=1时,返回逆傅立叶变换的实部
	fi---双精度实型一维数组,长度为n
		 当l=0时,返回傅立叶变换的虚部
		 当l=1时,返回逆傅立叶变换的虚部
	l----整型变量
		 当l=0时,表示要求本函数计算傅立叶变换
		 当l=1时,表示要求本函数计算逆傅立叶变换
	il---整型变量
		 若il=0,表示不要求本函数计算傅立叶变换或逆变换的模与幅角
		 若il=1,表示要求本函数计算傅立叶变换或逆变换的模与幅角
**************************************************************************************/
void WINAPI Jim_FFT(double* pr,double* pi,int n,int k,int l,int il)
{ 

	int it,m,is,i,j,nv,l0;
	double p,q,s,vr,vi,poddr,poddi;
	double fr[256],fi[256];
	for (it=0; it<=n-1; it++)
	{ 
		m=it; is=0;
		for (i=0; i<=k-1; i++)
		{ 
			j=m/2; is=2*is+(m-2*j); m=j;
		}
		fr[it]=pr[is]; fi[it]=pi[is];
	}
	pr[0]=1.0; 
	pi[0]=0.0;
	
	p=(2*PI)/(1.0*n);
	pr[1]=cos(p); 
	pi[1]=-sin(p);
	
	//计算逆傅立叶变换
	if (l!=0) 
		pi[1]=-pi[1];
	for (i=2; i<=n-1; i++)
	{ 
		p=pr[i-1]*pr[1]; q=pi[i-1]*pi[1];
		s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);
		pr[i]=p-q; pi[i]=s-p-q;
	}
	for (it=0; it<=n-2; it=it+2)
	{ 
		vr=fr[it]; vi=fi[it];
		fr[it]=vr+fr[it+1]; fi[it]=vi+fi[it+1];
		fr[it+1]=vr-fr[it+1]; fi[it+1]=vi-fi[it+1];
	}
	m=n/2; nv=2;
	for (l0=k-2; l0>=0; l0--)
	{ 
		m=m/2; nv=2*nv;
		for (it=0; it<=(m-1)*nv; it=it+nv)
			for (j=0; j<=(nv/2)-1; j++)
			{ 
				p=pr[m*j]*fr[it+j+nv/2];
				q=pi[m*j]*fi[it+j+nv/2];
				s=pr[m*j]+pi[m*j];
				s=s*(fr[it+j+nv/2]+fi[it+j+nv/2]);
				poddr=p-q; poddi=s-p-q;
				fr[it+j+nv/2]=fr[it+j]-poddr;
				fi[it+j+nv/2]=fi[it+j]-poddi;
				fr[it+j]=fr[it+j]+poddr;
				fi[it+j]=fi[it+j]+poddi;
			}
	}
	//计算逆傅立叶变换
	if (l!=0)
	{
		for (i=0; i<=n-1; i++)
		{ 
			fr[i]=fr[i]/(1.0*n);
			fi[i]=fi[i]/(1.0*n);
		}
	}
	//计算傅立叶变换或逆变换的模pr[i]与幅角pi[i]
	if (il!=0)
	{
		for (i=0; i<=n-1; i++)
		{ 
			pr[i]=sqrt(fr[i]*fr[i]+fi[i]*fi[i]);
			if (fabs(fr[i])<0.000001*fabs(fi[i]))
			{ 
				if ((fi[i]*fr[i])>0) 
					pi[i]=90.0;
				else 
					pi[i]=-90.0;
			}
			else
				pi[i]=atan(fi[i]/fr[i])*360.0/(2*PI);
		}
	}
	return;
}

//计算400个点里的峰值、谷值、心率
void WINAPI Jim_CaculateParam(int *data,int *param,int point,int nParam)
{
	int		i,tmp=0;
	int		*result=(int *)param;
	int		peak=0,valley=128,middle=0,hr=0;
	int		offsetRise=0,offsetFall1=0,offsetFall2=0,offsetRiseLimit=20,offsetFallLimit=20; //控制下降幅度的检测
	bool    bFindPeak=false,bFindValley=false;
	int     pFirstPeak=0,pSecondPeak=0,pFirstValley=0;

	for(i=0;i<point;i++)
	{
		//寻找第一个峰值
		if(data[i]>peak)
			peak=data[i];
		if(data[i]<valley)
			valley=data[i];
	}
	middle=int((peak-valley)/3+valley);
	//找到起始搜索点
	for(i=0;i<point;i++)
	{
		if(data[i]==middle || data[i]-middle<3)
		{
			tmp=i;
			break;
		}
	}
	for(i=tmp;i<point;i++)
	{
	}
	result[0]=peak;
	result[1]=valley;
		//result[5]=pFirstValley;

}
/**************************************************************************************
             第一类整数阶贝塞尔函数算法(Bessel Function)  by Jim Fang at 2007

	n----整型变量,第一类贝塞尔函数的阶数,n>=0时
		 当n<0时,本函数按|n|计算
	x----双精度实型变量,自变量值

**************************************************************************************/
double WINAPI Jim_Bessel0(int n,double x)
{ 
	int i,m;
    double t,y,z,p,q,s,b0,b1;
    static double a[6]={ 57568490574.0,-13362590354.0,
             651619640.7,-11214424.18,77392.33017,
            -184.9052456};
    static double b[6]={ 57568490411.0,1029532985.0,
             9494680.718,59272.64853,267.8532712,1.0};
    static double c[6]={ 72362614232.0,-7895059235.0,
             242396853.1,-2972611.439,15704.4826,
             -30.16036606};
    static double d[6]={ 144725228443.0,2300535178.0,
             18583304.74,99447.43394,376.9991397,1.0};
    static double e[5]={ 1.0,-0.1098628627e-02,
             0.2734510407e-04,-0.2073370639e-05,
             0.2093887211e-06};
    static double f[5]={ -0.1562499995e-01,
             0.1430488765e-03,-0.6911147651e-05,
             0.7621095161e-06,-0.934935152e-07};
    static double g[5]={ 1.0,0.183105e-02,
             -0.3516396496e-04,0.2457520174e-05,
             -0.240337019e-06};
    static double h[5]={ 0.4687499995e-01,
             -0.2002690873e-03,0.8449199096e-05,
             -0.88228987e-06,0.105787412e-06};
    t=fabs(x);
    if (n<0) 
		n=-n;
    if (n!=1)
	{ 
		if (t<8.0)
		{ 
			y=t*t; p=a[5]; q=b[5];
			for (i=4; i>=0; i--)
			{ 
				p=p*y+a[i]; q=q*y+b[i];
			}
            p=p/q;
		}
        else
		{ 
			z=8.0/t; y=z*z;
            p=e[4]; q=f[4];
            for (i=3; i>=0; i--)
			{ 
				p=p*y+e[i]; q=q*y+f[i];
			}
            s=t-0.785398164;
            p=p*cos(s)-z*q*sin(s);
            p=p*sqrt(0.636619772/t);
		}
	}
    if (n==0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -