📄 vf_getminutia.h
字号:
if(n != 3)
{
continue;
}
// 找到叉点三个方向纹线上距离为8的点
for(k = 0; k < 3; k++)
{
GetByDis(tempPtr[k+1], &disPtr[k], 8);
}
for(k = 0; k < 4; k++)
{
*tempPtr[k] = 0;
}
// 求该三个点两两间的距离
d0 = sqrt((double)((PX(disPtr[1]) - PX(disPtr[2]))*(PX(disPtr[1]) - PX(disPtr[2])) +
(PY(disPtr[1]) - PY(disPtr[2]))*(PY(disPtr[1]) - PY(disPtr[2]))));
d1 = sqrt((double)((PX(disPtr[0]) - PX(disPtr[2]))*(PX(disPtr[0]) - PX(disPtr[2])) +
(PY(disPtr[0]) - PY(disPtr[2]))*(PY(disPtr[0]) - PY(disPtr[2]))));
d2 = sqrt((double)((PX(disPtr[1]) - PX(disPtr[0]))*(PX(disPtr[1]) - PX(disPtr[0])) +
(PY(disPtr[1]) - PY(disPtr[0]))*(PY(disPtr[1]) - PY(disPtr[0]))));
// 距离最短的边对应的是叉线方向
if(d0 < d1 && d0 < d2)
{
x11 = PX(disPtr[1]);
y11 = PY(disPtr[1]);
x21 = PX(disPtr[2]);
y21 = PY(disPtr[2]);
lpDis = disPtr[0];
}
else if(d1 < d0 && d1 < d2)
{
x11 = PX(disPtr[0]);
y11 = PY(disPtr[0]);
x21 = PX(disPtr[2]);
y21 = PY(disPtr[2]);
lpDis = disPtr[1];
}
else
{
x11 = PX(disPtr[0]);
y11 = PY(disPtr[0]);
x21 = PX(disPtr[1]);
y21 = PY(disPtr[1]);
lpDis = disPtr[2];
}
// 求最短边中点与叉点连线的方向与该点方向场方向的夹角
angle1 = GetAngle(ForkArr[i].x, ForkArr[i].y, (x11+x21)/2, (y11+y21)/2);
angle2 = *(g_lpOrient + ForkArr[i].y*IMGW + ForkArr[i].x);
angle3 = GetAngleDis(angle1, angle2);
// 如果成钝角,则表示该特征点方向与该点方向场方向相反
if(angle3 > 90 && angle3 < 270)
{
g_Feature.MinutiaArr[EndNum + j].Direction = angle2 + 180;
}
else // 如果成锐角,则表示该特征点方向与该点方向场方向相同
{
g_Feature.MinutiaArr[EndNum + j].Direction = angle2;
}
// 纪录以特征点为中心外接圆半径为trilen的正三角形三个顶点的方向
a = g_Feature.MinutiaArr[EndNum + j].Direction / EPI + PI/4.0;
x11 = EndArr[i].x + (sint32)(trilen*cos(a)+ 0.5);
y11 = EndArr[i].y + (sint32)(trilen*sin(a)+ 0.5);
g_Feature.MinutiaArr[EndNum + j].Triangle[0] = *(g_lpOrient + y11*IMGW + x11);
a += PI*2/3.0;
x11 = EndArr[i].x + (sint32)(trilen*cos(a)+ 0.5);
y11 = EndArr[i].y + (sint32)(trilen*sin(a)+ 0.5);
g_Feature.MinutiaArr[EndNum + j].Triangle[1] = *(g_lpOrient + y11*IMGW + x11);
a += PI*2/3.0;
x11 = EndArr[i].x + (sint32)(trilen*cos(a)+ 0.5);
y11 = EndArr[i].y + (sint32)(trilen*sin(a)+ 0.5);
g_Feature.MinutiaArr[EndNum + j].Triangle[2] = *(g_lpOrient + y11*IMGW + x11);
g_Feature.MinutiaArr[EndNum + j].x = ForkArr[i].x; //横坐标
g_Feature.MinutiaArr[EndNum + j].y = ForkArr[i].y; //纵坐标
g_Feature.MinutiaArr[EndNum + j].Type = VF_MINUTIA_FORK; // 类型
j++;
}
ForkNum = j; // 叉点数目
}
// 如果循环32次都不能得到理想结果,则表示图像质量差,返回错误
if(loopnum >= 32)
{
EndNum = 0;
ForkNum = 0;
return 1;
}
// 特征点数目等于端点数加叉点数
g_Feature.MinutiaNum = (uint8)(EndNum+ForkNum);
// 特征点数目太少则返回错误
if(ForkNum + EndNum < 8)
{
EndNum = 0;
ForkNum = 0;
return 1;
}
return 0;
}
/*
//
// getSingular: 提取中心点三角点
//
void getSingular()
{
sint32 x, y, i, j;
sint32 DSite8[8][8];
sint32 DSiteR1[8] = {-1, BOW-1, BOW, BOW+1, 1, -BOW+1, -BOW, -BOW-1};
bool flag, flag2, flag3, fg;
sint32 temp;
uint8 *lpDir;
uint8 *lpCore;
sint32 asum;
sint32 mina;
sint32 minindex;
sint32 DAngleSum[8];
sint32 ad;
double dis;
VF_MINUTIAPTR core;
VF_MINUTIAPTR delta;
sint32 CoreNum, DeltaNum;
// 半径为15的圆上100个点相对于圆心的地址偏移
sint32 SiteR15[100] = {
0*IMGW-15, 1*IMGW-15, 2*IMGW-15, 3*IMGW-15, 4*IMGW-15, 4*IMGW-14, 5*IMGW-14,
6*IMGW-14, 7*IMGW-13, 8*IMGW-13, 8*IMGW-12, 9*IMGW-12, 10*IMGW-11, 11*IMGW-11,
11*IMGW-10, 12*IMGW-9, 12*IMGW-8, 13*IMGW-8, 13*IMGW-7, 14*IMGW-6, 14*IMGW-5,
14*IMGW-4, 15*IMGW-4, 15*IMGW-3, 15*IMGW-2, 15*IMGW-1, 15*IMGW+0, 15*IMGW+1,
15*IMGW+2, 15*IMGW+3, 14*IMGW+3, 14*IMGW+4, 14*IMGW+5, 13*IMGW+6, 13*IMGW+7,
12*IMGW+7, 12*IMGW+8, 11*IMGW+9, 11*IMGW+10, 10*IMGW+10, 9*IMGW+11, 8*IMGW+11,
8*IMGW+12, 7*IMGW+12, 6*IMGW+13, 5*IMGW+13, 4*IMGW+13, 4*IMGW+14, 3*IMGW+14,
2*IMGW+14, 1*IMGW+14, 0*IMGW+14, -1*IMGW+14, -2*IMGW+14, -3*IMGW+14, -3*IMGW+13,
-4*IMGW+13, -5*IMGW+13, -6*IMGW+12, -7*IMGW+12, -7*IMGW+11, -8*IMGW+11, -9*IMGW+10,
-10*IMGW+10, -10*IMGW+9, -11*IMGW+8, -11*IMGW+7, -12*IMGW+7, -12*IMGW+6, -13*IMGW+5,
-13*IMGW+4, -13*IMGW+3, -14*IMGW+3, -14*IMGW+2, -14*IMGW+1, -14*IMGW+0, -14*IMGW-1,
-14*IMGW-2, -14*IMGW-3, -14*IMGW-4, -13*IMGW-4, -13*IMGW-5, -13*IMGW-6, -12*IMGW-7,
-12*IMGW-8, -11*IMGW-8, -11*IMGW-9, -10*IMGW-10, -10*IMGW-11, -9*IMGW-11, -8*IMGW-12,
-7*IMGW-12, -7*IMGW-13, -6*IMGW-13, -5*IMGW-14, -4*IMGW-14, -3*IMGW-14, -3*IMGW-15,
-2*IMGW-15, -1*IMGW-15
};
// 圆上100个点与圆心连线的角度(圆与水平线相交左边的交点为起始点)
sint32 OriR15[100] = {
180, 176, 172, 168, 165, 164, 160, 156, 151, 148, 146, 143, 137, 135,
132, 126, 123, 121, 118, 113, 109, 105, 104, 101, 97, 93, 90, 86,
82, 78, 77, 74, 70, 65, 61, 59, 56, 50, 47, 45, 39, 36,
33, 30, 24, 21, 17, 15, 12, 8, 4, 0, 355, 351, 347, 347,
342, 338, 333, 329, 327, 323, 318, 314, 311, 306, 302, 300, 296, 291,
287, 282, 282, 278, 274, 269, 265, 261, 257, 254, 252, 248, 245, 239,
236, 233, 230, 224, 222, 219, 213, 210, 208, 204, 199, 195, 192, 191,
187, 183
};
core = (VF_MINUTIAPTR)(g_lpMemory + sizeof(VF_FEATURE));
delta = (VF_MINUTIAPTR)(g_lpMemory + sizeof(VF_FEATURE) +
sizeof(VF_MINUTIA)*5);
// 量化的8个方向上的8个点的地址偏移
for(i = 0; i < 8; i++)
{
DSite8[0][i] = i+1;
DSite8[1][i] = (i+1)*(IMGW + 1);
DSite8[2][i] = (i+1)*(IMGW);
DSite8[3][i] = (i+1)*(IMGW - 1);
DSite8[4][i] = -(i+1);
DSite8[5][i] = -(i+1)*(IMGW + 1);
DSite8[6][i] = -(i+1)*(IMGW);
DSite8[7][i] = (i+1)*(-IMGW + 1);
}
CoreNum = 0;
DeltaNum = 0;
flag2 = true;
flag3 = true;
temp = VF_BW*IMGW;
for(y = VF_BW; y <= IMGH-VF_BW; y++)
{
for(x = VF_BW; x <= IMGW-VF_BW; x++)
{
// 检查是否为边缘部分
lpDir = g_lpBlockOrient + (y/VF_BW)*BOW + x/VF_BW;
if(*lpDir == 255)
{
continue;
}
flag = true;
for(i = 0; i < 8; i++)
{
if(*(lpDir + DSiteR1[i]) == 255)
{
flag = false;
break;
}
}
if(!flag)
{
continue;
}
// 检查是否该点方向变化剧烈,变化剧烈才有可能是奇异点
asum = 0;
for(i = 0; i < 8; i++)
{
ad = GetJiajiao((sint32)(*(lpDir+DSiteR1[(i+1)%8])),
(sint32)(*(lpDir+DSiteR1[i])));
asum += ad;
}
if(abs(asum - 180) > 60)
{
continue;
}
// 检查8八个量化方向上的8个点是否为无效区域内
lpDir = g_lpOrient + temp + x;
if(*lpDir == 255)
{
continue;
}
flag = true;
for(i = 0; i < 8 && flag; i++)
{
for(j = 0; j < 8 && flag; j++)
{
if(*(lpDir + DSite8[i][j]) == 255)
{
flag = false;
break;
}
}
}
if(!flag)
{
continue;
}
// 检查第二圈上的夹角和是否比较大,如果是奇异点这个值应该较大
asum = 0;
for(i = 0; i < 8; i++)
{
asum += GetJiajiao((sint32)(*(lpDir+DSite8[(i+1)%8][2])),
(sint32)(*(lpDir+DSite8[i][2])));
}
if(asum < 90)
{
continue;
}
// 求7个圈上8个方向上的角度变化和。中心点角度变化和应该为180,三角点为-180
for(i = 0; i < 8; i++)
{
DAngleSum[i] = 0;
}
for(j = 1; j < 8; j++)
{
for(i = 0; i < 8; i++)
{
ad = AngleSub((sint32)(*(lpDir+DSite8[(i+1)%8][j])),
(sint32)(*(lpDir+DSite8[i][j])));
if(ad > 90 || ad < -90)
{
continue;
}
DAngleSum[j] += ad;
}
}
// 判断是否为中心点。要求7个圈上的角度变化和都是180
flag = true;
for(i = 1; i < 8; i++)
{
if(DAngleSum[i] != 180)
{
flag = false;
break;
}
}
//是的话则记录下来其坐标
if(flag && flag2)
{
if(CoreNum == 0)
{
core[CoreNum].x = x;
core[CoreNum].y = y;
core[CoreNum].Type = 1;
CoreNum++;
}
else
{
// 检查在小距离内是否有中心点,有的话将它们坐标做平均做为中心点坐标
fg = true;
for(i = 0; i < CoreNum; i++)
{
dis = sqrt((double)((core[i].x/core[i].Type - x)*
(core[i].x/core[i].Type - x) +
(core[i].y/core[i].Type - y)*
(core[i].y/core[i].Type - y)));
if(dis < 8)
{
core[i].x += x;
core[i].y += y;
core[i].Type++;
fg = false;
break;
}
}
if(fg)
{
core[CoreNum].x = x;
core[CoreNum].y = y;
core[CoreNum].Type = 1;
CoreNum++;
if(CoreNum > VF_MAXCORENUM)
{
flag2 = false;
}
}
}
continue;
}
// 判断是否为三角点。要求7个圈上的角度变化和都是-180
flag = true;
for(i = 1; i < 8; i++)
{
if(DAngleSum[i] != -180)
{
flag = false;
break;
}
}
if(flag && flag3)
{
//*lpTemp = 255;
if(DeltaNum == 0)
{
delta[DeltaNum].x = x;
delta[DeltaNum].y = y;
delta[DeltaNum].Type = 1;
DeltaNum++;
}
else
{
// 检查在小距离内是否有三角点,有的话将它们坐标做平均做为三角点坐标
fg = true;
for(i = 0; i < DeltaNum; i++)
{
dis = sqrt((double)((delta[i].x/delta[i].Type - x)*
(delta[i].x/delta[i].Type - x) +
(delta[i].y/delta[i].Type - y)*
(delta[i].y/delta[i].Type - y)));
if(dis < 8)
{
delta[i].x += x;
delta[i].y += y;
delta[i].Type++;
fg = false;
break;
}
}
if(fg)
{
delta[DeltaNum].x = x;
delta[DeltaNum].y = y;
delta[DeltaNum].Type = 1;
DeltaNum++;
if(DeltaNum > VF_MAXDELTANUM)
{
flag3 = false;
}
}
}
}
}
temp += IMGW;
}
// 中心点太多则去掉多余的
if(DeltaNum > VF_MAXDELTANUM)
{
DeltaNum = VF_MAXDELTANUM;
}
// 三角点太多则去掉多余的
if(CoreNum > VF_MAXCORENUM)
{
CoreNum = VF_MAXCORENUM;
}
// 求中心点方向. 圆心与圆上所有点的连线与该点方向夹角最小,则中心点方向为该点方向
for(i = 0; i < CoreNum; i++)
{
core[i].x /= core[i].Type;
core[i].y /= core[i].Type;
core[i].Type = VF_MINUTIA_CORE;
lpCore = g_lpOrient + core[i].y*IMGW + core[i].x;
mina = 360;
for(j = 0; j < 100; j++)
{
lpDir = lpCore + SiteR15[j];
temp = OriR15[j];
if(temp >= 180)
temp -=180;
temp = GetJiajiao(temp, *lpDir);
if(temp < mina)
{
mina = temp;
minindex = j;
}
}
// 夹角最小值要小于6度
if(mina < 6)
{
lpDir = lpCore + SiteR15[minindex];
if(OriR15[minindex] >= 180)
core[i].Direction = (*lpDir + 180);
else
core[i].Direction = *lpDir;
}
else
{
core[i].Direction = 400;
}
}
for(i = 0; i < DeltaNum; i++)
{
delta[i].x /= delta[i].Type;
delta[i].y /= delta[i].Type;
delta[i].Type = VF_MINUTIA_DELTA;
}
g_lpFeature->CoreNum = (uint8)CoreNum;
g_lpFeature->DeltaNum = (uint8)DeltaNum;
memcpy((void *)g_lpFeature->CoreArr, (void *)&core[0], CoreNum*sizeof(VF_MINUTIA));
memcpy((void *)g_lpFeature->DeltaArr, (void *)&delta[0], DeltaNum*sizeof(VF_MINUTIA));
}
*/
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -