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

📄 globalapi.cpp

📁 虹膜图像预处理
💻 CPP
📖 第 1 页 / 共 3 页
字号:
 *   int Gao_temp3                              - 记录瞳孔半径
 *   int Gao_temp4                              - 记录虹膜圆心纵坐标
 *   int Gao_temp5                              - 记录虹膜圆心横坐标
 *   int Gao_temp6                              - 记录虹膜半径
 *   double  x			                        - 插值元素的x坐标
 *   double  y		                            - 插值元素的y坐标
 ************************************************************************/
void Normalization(unsigned char *NormalizeImage,unsigned char *HoughImage,
				   int Gao_temp1,int Gao_temp2,int Gao_temp3,int Gao_temp4,
				   int Gao_temp5,int Gao_temp6,int nWidth,int nHeight)
{
	double alfa = 0.0;
	double Theta ;
    double angle_OIA = 0.0;
	double angle_OAI = 0.0;
	double angle_IOA = 0.0;
    
	double OI = 0.0;
	double IA = 0.0;
	double r = 0.0;
		
	double xp = 0.0;
	double yp = 0.0;
	double xi = 0.0;
	double yi = 0.0;

	double x = 0.0;
	double y = 0.0;

	for(Theta=0.0001; Theta<2*pi; Theta+=2*pi/1024)
	{
		alfa = atan(fabs((double)(Gao_temp1-Gao_temp4)/(double)(Gao_temp2-Gao_temp5)));
		if(Theta<pi/3||Theta>2*pi/3)
		{
		if(Theta==alfa||Theta==alfa+pi)
		{
			xp = Gao_temp2+Gao_temp3*cos(Theta);
			yp = Gao_temp1+Gao_temp3*sin(Theta);
            xi = Gao_temp5+Gao_temp6*cos(Theta);
			yi = Gao_temp4+Gao_temp6*sin(Theta);
		}
		else
		{
			 angle_OIA = pi- Theta + alfa;
		     OI = sqrt((Gao_temp1-Gao_temp4)*(Gao_temp1-Gao_temp4)+(Gao_temp2-Gao_temp5)*(Gao_temp2-Gao_temp5));
		     angle_OAI = asin(OI*sin(angle_OIA)/Gao_temp6);
		     angle_IOA = pi - angle_OIA - angle_OAI;
		     IA = sqrt(OI*OI+Gao_temp6*Gao_temp6-2*OI*Gao_temp6*cos(angle_IOA));

		     xp = Gao_temp2 + Gao_temp3 * cos(Theta);
             yp = Gao_temp1 + Gao_temp3 * sin(Theta);
	        
		     xi = Gao_temp2 + IA * cos(Theta);
             yi = Gao_temp1 + IA * sin(Theta);

		}		
        for(r=0.0;r<1.0;r+=1.0/128)
		{

			x = (1-r)*xp + r*xi;
	        y = (1-r)*yp + r*yi;
            NormalizeImage[int(128*r)*1024+int(Theta*1024/(2*pi))] = Interpolation(HoughImage, nWidth, nHeight, x, y);
		}
		}
		
	}
}
/*************************************************************************
 *  函数名称:
 *  Interpolation()
 *  输入参数:
 *   unsigned char *InterpolaImage      - 记录插值图像的缓冲区
 *   int    nWidth                      - 图象数据宽度
 *   int    nHeight                     - 图象数据高度
 *   float  x			                - 插值元素的x坐标
 *   float  y		                    - 插值元素的y坐标
 ************************************************************************/
unsigned char Interpolation(unsigned char *InterpolaImage, int nWidth, int nHeight, double x, double y)
{
	// 四个最临近象素的坐标(i1, j1), (i2, j1), (i1, j2), (i2, j2)
	int	i1, i2;
	int	j1, j2;
	// 四个最临近象素值
	char	f1,f2,f3,f4;
	// 二个插值中间值
	char f12, f34;
	// 计算四个最临近象素的坐标
	i1 = (int) x;
	i2 = i1 + 1;
	j1 = (int) y;
	j2 = j1 + 1;
	
	// 根据不同情况分别处理
	if( (x < 0) || (x > nWidth - 1) || (y < 0) || (y > nHeight - 1))
	{
		return 255;
	}
	else
	{
		if (x == nWidth - 1)
		{
			// 要计算的点在图像右边缘上
			if (y == 0)
			{
				// 要计算的点正好是图像最右下角那一个象素,直接返回该点象素值
				f1 = InterpolaImage[j1*nWidth+i1];
				return f1;
			}
			else
			{
				// 在图像右边缘上且不是最后一点,直接一次插值即可
				f1 = InterpolaImage[j1*nWidth+i1];
				f3 = InterpolaImage[j1*nWidth+i2];
				// 返回插值结果
				return ((unsigned char)(f1 + (y -j1) * (f3 - f1)));
			}
		}
		else if (y == 0)
		{
			// 要计算的点在图像下边缘上且不是最后一点,直接一次插值即可
			f1 = InterpolaImage[j1*nWidth+i1];
			f2 = InterpolaImage[j2*nWidth+i1];
			// 返回插值结果
			return ((unsigned char)(f1 + (x -i1) * (f2 - f1)));
		}
		else
		{
			// 计算四个最临近象素值
			f1 = InterpolaImage[j1*nWidth+i1];
			f2 = InterpolaImage[j2*nWidth+i1];
			f3 = InterpolaImage[j1*nWidth+i2];
			f4 = InterpolaImage[j2*nWidth+i2];
			// 插值1
			f12 = (unsigned char) (f1 + (x - i1) * (f2 - f1));
			// 插值2
			f34 = (unsigned char) (f3 + (x - i1) * (f4 - f3));
			// 插值3
			return ((unsigned char) (f12 + (y -j1) * (f34 - f12)));
		}
	}
}
/*************************************************************************
 *   函数名称:
 *   InteEqualize()
 *   参数:
 *   InteEqualizeImg              - 指向图象数据的指针
 *   int nWidth			          - 图象数据宽度
 *   int nHeight			      - 图象数据高度
 ************************************************************************/
void InteEqualize(unsigned char *InteEqualizeImg, int nWidth,int nHeight)
{
	
	// 循环变量
	int i = 0;
	int j = 0;
	// 临时变量
	int	Temp = 0;	
	// 灰度映射表
	BYTE	bMap[256];	
	// 灰度映射表
	int	Count[256];
	// 清零
	for (i = 0; i < 256;i++)
	{
		Count[i] = 0;
	}	
	// 计算各个灰度值的计数
	for (i = 0; i < nHeight; i ++)
	{
		for (j = 0; j < nWidth; j ++)
		{
			Count[InteEqualizeImg[i*nWidth+j]]++;
		}
	}	
	// 计算灰度映射表
	for (i = 0; i < 256; i++)
	{
		// 初始为0
		Temp = 0;
		for (j = 0; j <= i ;j++)
		{
			Temp += Count[j];
		}		
		// 计算对应的新灰度值
		bMap[i] = (BYTE) (Temp * 255 / nHeight / nWidth);
	}
	for(i = 0; i < nHeight; i++)
	{
		for(j = 0; j < nWidth; j++)
		{
			// 计算新的灰度值
			InteEqualizeImg[i*nWidth+j] = bMap[InteEqualizeImg[i*nWidth+j]];
		}
	}
	
}
/*************************************************************************
 *   函数名称:
 *   FFT()
 *   输入参数:
 *   Cdib *FourierImg	- 图像对象
 *************************************************************************/
void FFT( unsigned char *FourierImg)
{
	// 循环控制变量
	int y;
	int x;	
	
	int nWidth = 1024;
	int nHeight= 128;

	// 临时变量
	double	dTmpOne;
	double  dTmpTwo;
	
	// 傅立叶变换竖直方向点数
	int nTransHeight;

	// 傅立叶变换水平方向点数
	int nTransWidth;		
	// 计算进行傅立叶变换的点数	(2的整数次幂)
	dTmpOne = log(nWidth)/log(2);
	dTmpTwo = ceil(dTmpOne);
	dTmpTwo = pow(2,dTmpTwo);
	nTransWidth = (int) dTmpTwo;	
	// 计算进行傅立叶变换的点数 (2的整数次幂)
	dTmpOne = log(nHeight)/log(2);
	dTmpTwo = ceil(dTmpOne);
	dTmpTwo = pow(2,dTmpTwo);
	nTransHeight = (int) dTmpTwo;
	// 计算图象数据存储每行需要的字节数
	// BMP文件的每行数据存储是DWORD对齐的
	int		nSaveWidth;
	nSaveWidth = ( (nWidth << 3) + 31)/32 * 4;
	
	// 图象象素值
	unsigned char unchValue;

	
	// 指向时域数据的指针
	complex<double> * pCTData;

	// 指向频域数据的指针
	complex<double> * pCFData;

	// 分配内存
	pCTData=new complex<double>[nTransWidth * nTransHeight];
	pCFData=new complex<double>[nTransWidth * nTransHeight];

	// 初始化
	// 图象数据的宽和高不一定是2的整数次幂,所以pCTData
	// 有一部分数据需要补0
	for(y=0; y<nTransHeight; y++)
	{
		for(x=0; x<nTransWidth; x++)
		{
			pCTData[y*nTransWidth + x]=complex<double>(0,0);
		}
	}

	// 把图象数据传给pCTData
	for(y=0; y<nHeight; y++)
	{
		for(x=0; x<nWidth; x++)
		{
			unchValue = FourierImg[y*nSaveWidth +x];
			pCTData[y*nTransWidth + x]=complex<double>(unchValue,0);
		}
	}

	// 傅立叶正变换
	DIBFFT_2D(pCTData, nWidth, nHeight, pCFData) ;
	
	// 临时变量
	double dTmp;
	for(y=0; y<nHeight; y++)
	{
		for(x=0; x<nWidth; x++)
		{
			dTmp = pCFData[y * nTransWidth + x].real() 
				   * pCFData[y * nTransWidth + x].real()
				 + pCFData[y * nTransWidth + x].imag() 
				   * pCFData[y * nTransWidth + x].imag();
			
			dTmp = sqrt(dTmp);

			// 为了显示,需要对幅度的大小进行伸缩
			dTmp /= 100;

			// 限制图象数据的大小
			dTmp = min(dTmp, 255);

			FourierImg[y*nSaveWidth+x] = (unsigned char)(int)dTmp;
		}
	}
	
}
/*************************************************************************
 *   函数名称:
 *   DIBFFT_2D()
 *   输入参数:
 *   complex<double> * pCTData	- 图像数据
 *   int    nWidth				- 数据宽度
 *   int    nHeight				- 数据高度
 *   complex<double> * pCFData	- 傅立叶变换后的结果
 *************************************************************************/
VOID WINAPI DIBFFT_2D(complex<double> * pCTData, int nWidth, int nHeight, complex<double> * pCFData)
{
	
	// 循环控制变量
	int	x;
	int	y;
	
	// 临时变量
	double	dTmpOne;
	double  dTmpTwo;
	
	// 进行傅立叶变换的宽度和高度,(2的整数次幂)
	// 图像的宽度和高度不一定为2的整数次幂
	int		nTransWidth;
	int 	nTransHeight;

	// 计算进行傅立叶变换的宽度	(2的整数次幂)
	dTmpOne = log(nWidth)/log(2);
	dTmpTwo = ceil(dTmpOne)		   ;
	dTmpTwo = pow(2,dTmpTwo)	   ;
	nTransWidth = (int) dTmpTwo	   ;
	
	// 计算进行傅立叶变换的高度 (2的整数次幂)
	dTmpOne = log(nHeight)/log(2);
	dTmpTwo = ceil(dTmpOne)		   ;
	dTmpTwo = pow(2,dTmpTwo)	   ;
	nTransHeight = (int) dTmpTwo	   ;	
	
	// x,y(行列)方向上的迭代次数
	int		nXLev;
	int		nYLev;

	// 计算x,y(行列)方向上的迭代次数
	nXLev = (int) ( log(nTransWidth)/log(2) +  0.5 );
	nYLev = (int) ( log(nTransHeight)/log(2) + 0.5 );
	
	for(y = 0; y < nTransHeight; y++)
	{
		// x方向进行快速傅立叶变换
		FFT_1D(&pCTData[nTransWidth * y], &pCFData[nTransWidth * y], nXLev);
	}
	
	// pCFData中目前存储了pCTData经过行变换的结果
	// 为了直接利用FFT_1D,需要把pCFData的二维数据转置,再一次利用FFT_1D进行
	// 傅立叶行变换(实际上相当于对列进行傅立叶变换)
	for(y = 0; y < nTransHeight; y++)
	{
		for(x = 0; x < nTransWidth; x++)
		{
			pCTData[nTransHeight * x + y] = pCFData[nTransWidth * y + x];
		}
	}
	
	for(x = 0; x < nTransWidth; x++)
	{
		// 对x方向进行快速傅立叶变换,实际上相当于对原来的图象数据进行列方向的
		// 傅立叶变换
		FFT_1D(&pCTData[x * nTransHeight], &pCFData[x * nTransHeight], nYLev);
	}

	// pCFData中目前存储了pCTData经过二维傅立叶变换的结果,但是为了方便列方向
	// 的傅立叶变换,对其进行了转置,现在把结果转置回来
	for(y = 0; y < nTransHeight; y++)
	{
		for(x = 0; x < nTransWidth; x++)
		{
			pCTData[nTransWidth * y + x] = pCFData[nTransHeight * x + y];
		}
	}

	memcpy(pCTData, pCFData, sizeof(complex<double>) * nTransHeight * nTransWidth );
}
/*************************************************************************
 *   函数名称:
 *   FFT_1D()
 *
 *   输入参数:
 *   complex<double> * pCTData	- 指向时域数据的指针,输入的需要变换的数据
 *   complex<double> * pCFData	- 指向频域数据的指针,输出的经过变换的数据
 *   nLevel						-傅立叶变换蝶形算法的级数,2的幂数,
 **************************************************************************/
VOID WINAPI FFT_1D(complex<double> * pCTData, complex<double> * pCFData, int nLevel)
{	
	// 循环控制变量
	int		i;
	int     j;
	int     k;

	double PI = 3.1415926; 

	// 傅立叶变换点数
	int	nCount =0 ;

	// 计算傅立叶变换点数
	nCount =(int)pow(2,nLevel) ;
	
	// 某一级的长度
	int		nBtFlyLen;
	nBtFlyLen = 0 ;
	
	// 变换系数的角度 =2 * PI * i / nCount
	double	dAngle;
	
	complex<double> *pCW ;
	
	// 分配内存,存储傅立叶变化需要的系数表
	pCW  = new complex<double>[nCount / 2];

    // 计算傅立叶变换的系数
	for(i = 0; i < nCount / 2; i++)
	{
		dAngle = -2 * PI * i / nCount;
		pCW[i] = complex<double> ( cos(dAngle), sin(dAngle) );
	}

	// 变换需要的工作空间
	complex<double> *pCWork1,*pCWork2; 
	
	// 分配工作空间
	pCWork1 = new complex<double>[nCount];

	pCWork2 = new complex<double>[nCount];

	
	// 临时变量
	complex<double> *pCTmp;
	
	// 初始化,写入数据
	memcpy(pCWork1, pCTData, sizeof(complex<double>) * nCount);

	// 临时变量
	int nInter; 
	nInter = 0;

	// 蝶形算法进行快速傅立叶变换
	for(k = 0; k < nLevel; k++)
	{
		for(j = 0; j < (int)pow(2,k); j++)
		{
			//计算长度
			nBtFlyLen = (int)pow( 2,(nLevel-k) );
			
			//倒序重排,加权计算
			for(i = 0; i < nBtFlyLen/2; i++)
			{
				nInter = j * nBtFlyLen;
				pCWork2[i + nInter] = 
					pCWork1[i + nInter] + pCWork1[i + nInter + nBtFlyLen / 2];
				pCWork2[i + nInter + nBtFlyLen / 2] =
					(pCWork1[i + nInter] - pCWork1[i + nInter + nBtFlyLen / 2]) 
					* pCW[(int)(i * pow(2,k))];
			}
		}

		// 交换 pCWork1和pCWork2的数据
		pCTmp   = pCWork1	;
		pCWork1 = pCWork2	;
		pCWork2 = pCTmp		;
	}
	
	// 重新排序
	for(j = 0; j < nCount; j++)
	{
		nInter = 0;
		for(i = 0; i < nLevel; i++)
		{
			if ( j&(1<<i) )
			{
				nInter += 1<<(nLevel-i-1);
			}
		}
		pCFData[j]=pCWork1[nInter];
	}
	
	// 释放内存空间
	delete pCW;
	delete pCWork1;
	delete pCWork2;
	pCW		=	NULL;
	pCWork1 =	NULL;
	pCWork2 =	NULL;

}

⌨️ 快捷键说明

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