📄 globalapi.cpp
字号:
* 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 + -