📄 minutiaextract.h
字号:
// MinutiaExtract.h: interface for the MinutiaExtract class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_MINUTIAEXTRACT_H__F76D271A_F5FD4_4DBA_B826_7B57F2574483__INCLUDED_)
#define AFX_MINUTIAEXTRACT_H__F76D271A_F5FD4_4DBA_B826_7B57F2574483__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//#include "UtilityFunction.h"
#include "math.h"
// 为节省时间,短距离的两点间距离采用查表法
// DisTbl[m][n] = (int)(sqrt(m*m+n*n)+0.5)
int DisTbl[10][10] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
1, 1, 2, 3, 4, 5, 6, 7, 8, 9,
2, 2, 2, 3, 4, 5, 6, 7, 8, 9,
3, 3, 3, 4, 5, 5, 6, 7, 8, 9,
4, 4, 4, 5, 5, 6, 7, 8, 8, 9,
5, 5, 5, 5, 6, 7, 7, 8, 9, 10,
6, 6, 6, 6, 7, 7, 8, 9, 10, 10,
7, 7, 7, 7, 8, 8, 9, 9, 10, 11,
8, 8, 8, 8, 8, 9, 10, 10, 11, 12,
9, 9, 9, 9, 9, 10, 10, 11, 12, 12
};
/*
void verify(FEATUREPTR lpFeature, FEATUREPTR lpTemplate, PMATCHRESULT lpMatchResult, VF_FLAG matchMode);
void globalMatch(FEATUREPTR lpFeature, FEATUREPTR lpTemplate, PMATCHRESULT lpMatchResult, VF_FLAG matchMode);
void alignMatch(FEATUREPTR lpAlignFeature, FEATUREPTR lpTemplate, PMATCHRESULT lpMatchResult, VF_FLAG matchMode);
void align(FEATUREPTR lpFeature, FEATUREPTR lpAlignedFeature, MINUTIAPTR lpFeatureCore, int rotation, int transx, int transy);
*/
int getOriChange(int angle1, int angle2, char flag)
{
int d;
d = angle2 - angle1;
if(flag >= 1)
{
if(d < 0)
{
d += 10;
}
}
else if(flag <= -1)
{
if(d > 0)
{
d -= 10;
}
}
return d;
}
int getSingular(BYTE *lpOrient, int Width, int Height, int *lpNum, PPOINT lpArr, char flag)
{
int x, y, i;
int num;
int sum1, sum2;
int d;
unsigned char *pOriMap;
int oriV;
int a1, a2;
DBLPOINT singuArr[30];
int value;
double dis;
bool bFound = false;
bool fg = false;
int D3[8][2] = {
-1,-1, -1,0, -1,1, 0,1, 1,1, 1,0, 1,-1, 0,-1
};
int D5[12][2] = {
-2,-1, -2,0, -2,1, -1,2, 0,2, 1,2, 2,1, 2,0, 2,-1, 1,-2, 0,-2, -1,-2
};
int D7[24][2] = {
-3,-3, -3,-2, -3,-1, -3,0, -3,1, -3,2, -3,3, -2,3, -1,3, 0,3, 1,3, 2,3, 3,3, 3,2, 3,1, 3,0,
3,-1, 3,-2, 3,-3, 2,-3, 1,-3, 0,-3, -1,-3, -2,-3
};
num = 0;
memset(singuArr, 0, sizeof(singuArr)); //初始化奇异点数组,清零
for(y = 3; y < Height-3; y++)
{
for(x = 3; x < Width-3; x++) //遍历整幅图
{
pOriMap = lpOrient + y*Width + x; //获得某点的方向场指针
oriV = *pOriMap; //获取某点的方向场的值
if(oriV == 255) //若是背景区域,则跳入下一个循环
{
continue;
}
fg = false;
for(i = 0; i < 24; i++)
{
if(pOriMap[D7[i][1]*Width + D7[i][0]]==255)
{
fg = true;
break;
}
}
if(fg)
{
continue;
}
sum1 = 0;
for(i = 0; i < 8; i++)
{
a1 = pOriMap[D3[i][1]*Width + D3[i][0]]/24;
a2 = pOriMap[D3[(i+1)%8][1]*Width + D3[(i+1)%8][0]]/24;
d = getOriChange(a1, a2, flag);
if(abs(d) > 5)
{
break;
}
sum1 += d;
}
sum2 = 0;
for(i = 0; i < 12; i++)
{
a1 = pOriMap[D5[i][1]*Width + D5[i][0]]/24;
a2 = pOriMap[D5[(i+1)%12][1]*Width + D5[(i+1)%12][0]]/24;
d = getOriChange(a1, a2, flag);
if(abs(d) > 5)
{
break;
}
sum2 += d;
}
if(flag == -1) //中心点
{
value = -10;
}
else if(flag == 1) //三角点
{
value = 10;
}
if(sum2 == value && sum1 == value)
{
bFound = false;
for(i = 0; i < num; i++)
{
dis = sqrt((double)((x - singuArr[i].x)*(x - singuArr[i].x) +
(y - singuArr[i].y)*(y - singuArr[i].y)));
if(dis < 4)
{
singuArr[i].x = (singuArr[i].x + x)/2.0;
singuArr[i].y = (singuArr[i].y + y)/2.0;
bFound = true;
break;
}
}
if(!bFound)
{
singuArr[num].x = x;
singuArr[num].y = y;
num++;
if(num >= MAX_SINGULARYNUM) //若奇异点数量超过最大限制,则停止寻找奇异点
{
goto next;
}
}
}
}
}
next:
*lpNum = num; //奇异点的个数
for(i = 0; i < num; i++) //将找到的奇异点存入输入数组
{
lpArr[i].x = (long)singuArr[i].x;
lpArr[i].y = (long)singuArr[i].y;
}
return 0;
}
int getSingularMinutia(BYTE *lpOrient, int Width, int Height, char flag, LPVOID feature)
{
int x, y, i;
int num;
int sum1, sum2;
int d;
unsigned char *pOriMap;
int oriV;
int a1, a2;
DBLPOINT singuArr[30];
int value;
double dis;
bool bFound = false;
bool fg = false;
int D3[8][2] = {
-1,-1, -1,0, -1,1, 0,1, 1,1, 1,0, 1,-1, 0,-1
};
int D5[12][2] = {
-2,-1, -2,0, -2,1, -1,2, 0,2, 1,2, 2,1, 2,0, 2,-1, 1,-2, 0,-2, -1,-2
};
int D7[24][2] = {
-3,-3, -3,-2, -3,-1, -3,0, -3,1, -3,2, -3,3, -2,3, -1,3, 0,3, 1,3, 2,3, 3,3, 3,2, 3,1, 3,0,
3,-1, 3,-2, 3,-3, 2,-3, 1,-3, 0,-3, -1,-3, -2,-3
};
FEATURE *g_Feature = (FEATURE*)(feature);
num = 0;
memset(singuArr, 0, sizeof(singuArr)); //初始化奇异点数组,清零
for(y = 3; y < Height-3; y++)
{
for(x = 3; x < Width-3; x++) //遍历整幅图
{
pOriMap = lpOrient + y*Width + x; //获得某点的方向场指针
oriV = *pOriMap; //获取某点的方向场的值
if(oriV == 255) //若是背景区域,则跳入下一个循环
{
continue;
}
fg = false;
for(i = 0; i < 24; i++)
{
if(pOriMap[D7[i][1]*Width + D7[i][0]]==255)
{
fg = true;
break;
}
}
if(fg)
{
continue;
}
sum1 = 0;
for(i = 0; i < 8; i++)
{
a1 = pOriMap[D3[i][1]*Width + D3[i][0]]/24;
a2 = pOriMap[D3[(i+1)%8][1]*Width + D3[(i+1)%8][0]]/24;
d = getOriChange(a1, a2, flag);
if(abs(d) > 5)
{
break;
}
sum1 += d;
}
sum2 = 0;
for(i = 0; i < 12; i++)
{
a1 = pOriMap[D5[i][1]*Width + D5[i][0]]/24;
a2 = pOriMap[D5[(i+1)%12][1]*Width + D5[(i+1)%12][0]]/24;
d = getOriChange(a1, a2, flag);
if(abs(d) > 5)
{
break;
}
sum2 += d;
}
if(flag == -1) //中心点
{
value = -10;
}
else if(flag == 1) //三角点
{
value = 10;
}
if(sum2 == value && sum1 == value)
{
bFound = false;
for(i = 0; i < num; i++)
{
dis = sqrt((double)((x - singuArr[i].x)*(x - singuArr[i].x) +
(y - singuArr[i].y)*(y - singuArr[i].y)));
if(dis < 4)
{
singuArr[i].x = (singuArr[i].x + x)/2.0;
singuArr[i].y = (singuArr[i].y + y)/2.0;
bFound = true;
break;
}
}
if(!bFound)
{
singuArr[num].x = x;
singuArr[num].y = y;
num++;
if(num >= MAX_SINGULARYNUM) //若奇异点数量超过最大限制,则停止寻找奇异点
{
goto next;
}
}
}
}
}
next:
int trilen = 16;
int N = 0; //奇异点的个数
for(i = 0; i < num; i++) //将找到的奇异点存入输入数组
{
//lpArr[*lpNum + i].x = (long)singuArr[i].x;
//lpArr[*lpNum + i].y = (long)singuArr[i].y;
int x = (long)singuArr[i].x;
int y = (long)singuArr[i].y;
//if (*(g_lpDivide + y * Width + x) == 255) continue;
if (((x + 0.0) / Width < 0.1) || ((x + 0.0) / Width > 0.9))
continue;
if (((y + 0.0) / Height < 0.1 ) || ((y + 0.0) / Height > 0.9))
continue;
g_Feature->MinutiaArr[g_Feature->MinutiaNum + N].x = x;
g_Feature->MinutiaArr[g_Feature->MinutiaNum + N].y = y;
g_Feature->MinutiaArr[g_Feature->MinutiaNum + N].Type = (flag == -1) ? VF_MINUTIA_CORE : VF_MINUTIA_DELTA;
g_Feature->MinutiaArr[g_Feature->MinutiaNum + N].Direction = 0;
N++;
}
g_Feature->MinutiaNum += N;
return 0;
}
int IMGW;
int IMGH;
BYTE *g_lpOrgFinger;
void setup(int W, int H, BYTE *lpData)
{
IMGW = W;
IMGH = H;
g_lpOrgFinger = lpData;
}
//
// IsFork: 判断某点是否为叉点
//
bool IsFork(BYTE *lpNow)
{
/////////////////////////////////////////////////////////////////////////////
// lpNow : [in] 当前点的地址
/////////////////////////////////////////////////////////////////////////////
int i, sum;
// 某点周围8个点的地址偏移
int SiteD8[8] = {IMGW-1, IMGW, IMGW+1, 1, -IMGW+1, -IMGW, -IMGW-1, -1};
// 8个点所有相邻两个点的差的绝对值的和如果为6*255则为叉点
sum = 0;
for(i = 0; i < 8; i++)
{
sum += abs(*(lpNow + SiteD8[(i+1)%8]) - *(lpNow + SiteD8[i]));
}
if(sum == 255*6)
{
return true;
}
else
{
return false;
}
}
//
// IsEnd: 判断某点是否为端点
//
bool IsEnd(BYTE *lpNow)
{
/////////////////////////////////////////////////////////////////////////////
// lpNow : [in] 当前点的地址
/////////////////////////////////////////////////////////////////////////////
int i, sum;
// 某点周围8个点的地址偏移
int SiteD8[8] = {IMGW-1, IMGW, IMGW+1, 1, -IMGW+1, -IMGW, -IMGW-1, -1};
// 8个点所有相邻两个点的差的绝对值的和如果为2*255则为端点
sum = 0;
for(i = 0; i < 8; i++)
{
sum += abs(*(lpNow + SiteD8[(i+1)%8]) - *(lpNow + SiteD8[i]));
}
if(sum == 255*2)
{
return true;
}
else
{
return false;
}
}
//
// GetNext: 在纹线上根据当前点和前驱点地址找到下一个点的地址
//
int GetNext(BYTE *lpNow, BYTE *lpLast, BYTE **lppNext)
{
/////////////////////////////////////////////////////////////////////////////
// lpNow : [in] 当前点的地址
// lpLast : [in] 前驱点的地址
// lppNext : [out] 下一个点的地址的指针
/////////////////////////////////////////////////////////////////////////////
int i;
BYTE *lpSrc = NULL;
int n;
BYTE *Temp[8]; // 某点周围8个点的地址
int SiteD8[8] = {IMGW-1, IMGW, IMGW+1, 1, -IMGW+1, -IMGW, -IMGW-1, -1};
*lppNext = NULL;
// 找到当前点周围的是黑点并且不是前驱点的黑点,保存到数组
n = 0;
for(i = 0; i < 8; i++)
{
lpSrc = lpNow + SiteD8[i];
if(*lpSrc == 0 && lpSrc != lpLast)
{
Temp[n] = lpSrc;
n++;
}
}
if(n == 0) // 没有找到其他黑点则表示没有后继点
{
*lppNext = NULL;
return 1;
}
else if(n == 1) // 找到了一个,则其为后继点
{
*lppNext = Temp[0];
return 0;
}
else // 找到多个点则返回错误
{
*lppNext = NULL;
return 1;
}
return 0;
}
//
// GetByDis: 在纹线上找到距离当前端点为d的点的地址
//
int GetByDis(BYTE *lpEnd, BYTE **lppPos, int d)
{
/////////////////////////////////////////////////////////////////////////////
// lpEnd : [in] 当前端点的地址
// lppPos : [out] 目的点的地址(如果在距离d内有端点或者叉点,则返回他们的邻点)
// d : [in] 距离(点数)
/////////////////////////////////////////////////////////////////////////////
int i, n;
BYTE *lpNow = NULL;
BYTE *lpLast = NULL;
BYTE *lpNext = NULL;
int SiteD8[8] = {IMGW-1, IMGW, IMGW+1, 1, -IMGW+1, -IMGW, -IMGW-1, -1};
*lppPos = NULL;
// 找到当前点周围的是黑点并且不是前驱点的黑点,保存到数组
n = 0;
for(i = 0; i < 8; i++)
{
if(*(lpEnd + SiteD8[i]) == 0)
{
lpNow = lpEnd + SiteD8[i];
n++;
}
}
if(n != 1) // 数目如果不是1则返回错误
{
return 1;
}
// 找到的黑点地址为lpNow
// 端点作为前驱点,地址保存到lpLast
lpLast = lpEnd;
// 循环找d次后继点
for(i = 0; i < d; i++)
{
// 如果是叉点则跳出循环
if(IsFork(lpNow))
{
break;
}
// 成功找到下一个点则更改当前点和前驱点
if(GetNext(lpNow, lpLast, &lpNext) == 0)
{
lpLast = lpNow;
lpNow = lpNext;
}
else
{
break;
}
}
// 如果找到的点为叉点,则返回其前驱点
if(IsFork(lpNow))
{
*lppPos = lpLast;
}
else // 否则返回当前点
{
*lppPos = lpNow;
}
return 0;
}
//
// PX: 根据地址得到当前点的横坐标
//
int PX(BYTE *lpPos)
{
/////////////////////////////////////////////////////////////////////////
// lpPos: [in] 当前点地址
/////////////////////////////////////////////////////////////////////////
return ((lpPos - g_lpOrgFinger) % IMGW);
}
//
// PY: 根据地址得到当前点的纵坐标
//
int PY(BYTE *lpPos)
{
/////////////////////////////////////////////////////////////////////////
// lpPos: [in] 当前点地址
/////////////////////////////////////////////////////////////////////////
return ((lpPos - g_lpOrgFinger) / IMGW);
}
//
// GetJiajiao: 求两个角度的夹角(0 - 90)
//
int GetJiajiao(int angle1, int angle2)
{
/////////////////////////////////////////////////////////////////////////
// angle1: [in] 角度一 (0 - 180)
// angle2: [in] 角度二 (0 - 180)
/////////////////////////////////////////////////////////////////////////
int a;
a = abs(angle1-angle2);
if(a > 90)
{
a = 180-a;
}
return a;
}
//
// AngleAbs360: 求两个角度的夹角(0 - 180)
//
int AngleAbs360(int angle1, int angle2)
{
/////////////////////////////////////////////////////////////////////////
// angle1: [in] 角度一 (0 - 360)
// angle2: [in] 角度二 (0 - 360)
/////////////////////////////////////////////////////////////////////////
int a;
a = abs(angle1 - angle2);
if(a > 180)
{
return (360 - a);
}
else
{
return a;
}
}
//
// GetAngleDis: 两个角度间的距离(0-360) (逆时针方向)
//
int GetAngleDis(int angleBegin, int angleEnd)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -