指纹模式识别算法及其测试方法
指纹算法需求
指纹特征值生成、比对API库需求:
- 可输出指纹图像。图像格式为bmp,小于等于500DPI,不大于50K。
- 可输出指纹模板。生成模板需要至少采集几次指纹需说明,建议不超过三次。模板大小不超过1K。模板生成时间不大于1秒。
- 可输出指纹特征值(可以是非字符串格式)。特征值大小不超过512B。
- 可输出指纹特征值字符串。字符串为可见字符,长度不超1024。
- 指纹比对时,支持输入指纹特征值字符串比对。
- 指纹比对时,支持输入指纹图像进行比对。
- 指纹比对API支持多线程模式,支持大并发调用。
- 指纹比对支持1:1,即指纹验证。
- 指纹比对支持1:N,即指纹辨识。
- 指纹比对时每枚比对速度要求小于0.1秒。
- 认假率小于0.0001% 。
- 拒真率小于0.75% 。
- 库要求32位,但支持在64位操作系统运行。
- 可提供dll、jar两种形式API的库。
系统列表 |
|
Windows |
2003 server/xp/win7 |
Linux |
>=内核2.6 |
Aix unix |
>=5.2 |
Android |
|
废话不多说,直接上干货,先附上一张指纹算法项目的思路流程图:
一、先讲解一下指纹算法源码的思路
从指纹图像中提取指纹特征:
-
int __
stdcall Analyze(BYTE *lpImage, int Width, int Height, BYTE *lpFeature, int *lpSize)
-
{
-
///////////////////////////////////////////////////////////////////////
-
// Width: [in] 指纹图像宽度
-
// Height: [in] 指纹图像高度
-
// lpImage: [in] 指纹图像数据指针
-
// Resolution: [in] 指纹图像分辨率,默认500
-
// lpFeature: [out] 提取的指纹特征数据指针
-
// lpSize: [out] 指纹特征数据大小
-
-
// TODO: Add your implementation code here
-
VF_RETURN re;
-
-
// 导入指纹图像数据
-
VF_ImportFinger(lpImage, Width, Height);
-
-
// 处理指纹图像,提取指纹特征
-
re = VF_Process();
-
if (re != VF_OK)
-
return re;
-
-
// 对指纹特征进行编码
-
re = VF_FeatureEncode(&g_Feature, lpFeature, lpSize);
-
if (re != VF_OK)
-
return re;
-
-
return
0;
-
}
对两个指纹进行特征比对:
-
int __
stdcall PatternMatch(BYTE *lpFeature1, BYTE *lpFeature2, int *lpScore)
-
{
-
// lpFeature1: [in] 第一个指纹特征
-
// lpFeature2: [in] 第二个指纹特征
-
// lpScore: [out] 比对的相似度
-
// FastMode: [in] 是否进行快速模式比对
-
VF_RETURN re1,re2;
-
MATCHRESULT mr;
-
FEATURE feat1, feat2;
-
-
// 第一个指纹特征的解码
-
re1 = VF_FeatureDecode(lpFeature1, &feat1);
-
if (re1 != VF_OK)
-
{
-
printf(
"图像1解码失败\n");
-
return
0;
-
//return re1;
-
}
-
-
// 第二个指纹特征的解码
-
re2 = VF_FeatureDecode(lpFeature2, &feat2);
-
if (re2 != VF_OK)
-
{
-
printf(
"图像2解码失败\n");
-
return
0;
-
//return re2;
-
}
-
-
*lpScore =
0;
-
-
bool FastMode =
true;
-
-
if (FastMode)
-
{
-
// 快速模式的比对
-
VF_VerifyMatch(&feat1, &feat2, &mr, VF_MATCHMODE_IDENTIFY);
-
}
-
else
-
{
-
// 精确模式的比对
-
VF_VerifyMatch(&feat1, &feat2, &mr, VF_MATCHMODE_VERIFY);
-
}
-
-
// 匹配的相似度
-
//*lpScore = mr.Similarity/10;
-
*lpScore = mr.Similarity;
-
/*if (mr.MMCount < 8)
-
{
-
*lpScore = 0;
-
}
-
else
-
{
-
*lpScore = mr.Similarity;
-
}*/
-
-
return
0;
-
}
二、怎么调用该源码算法库
在此不进行过多重复叙述,请移步我的另外一篇博文:https://blog.csdn.net/yanxiaolx/article/details/78730291
三、测试该算法识别率的测试demo
测试指纹算法的效果好坏,有3个指标:拒真率,认假率和识别率
测试的指纹库github已经上传:点击这里
正样本:所有指纹全部来自同一手指
负样本:所有指纹均来自不同手指
拒真率:正样本测试不通过的比率
认假率:负样本测试通过的比率
识别率:1 -(拒真率 + 认假率) / 2
第一个函数,对两个指纹图片的识别进行测试:
-
void test3()
-
{
-
char ImagePathName1[
100] =
"D:\\c++code\\test\\1 (1).BMP";
-
char ImagePathName2[
100] =
"D:\\c++code\\test\\1 (1).BMP";
-
-
BYTE lpFeature1[
500] = {
0 };
-
BYTE lpFeature2[
500] = {
0 };
-
-
int lpSize1 =
0, lpSize2 =
0, score =
0;
-
int iReturn =
0;
-
-
sprintf(ImagePathName1,
"D:\\c++code\\test\\1 (13).BMP");
-
sprintf(ImagePathName2,
"D:\\c++code\\test\\1 (14).BMP");
-
iReturn = AnalyzeFromFile(ImagePathName1, lpFeature1, &lpSize1);
-
if (iReturn !=
0)
-
{
-
printf(
"从BMP文件中读取图像1失败\n");
-
}
-
-
iReturn = AnalyzeFromFile(ImagePathName2, lpFeature2, &lpSize2);
-
if (iReturn !=
0)
-
{
-
printf(
"从BMP文件中读取图像2失败\n");
-
}
-
-
PatternMatch(lpFeature1, lpFeature2, &score);
//对指纹进行比对
-
-
if (score >
35)
//原来是60
-
{
-
printf(
"Same Fingerprint! \n");
-
}
-
else
-
{
-
printf(
"Different Fingerprint! \n");
-
}
-
-
return;
-
-
}
测试认假率:
-
int count1 =
0, Arr_score1[
11476] = {
0 };
-
-
void test1(double *Arr1)//测试认假率
-
{
-
char ImagePathName1[
100] =
"E:\\c++code\\指纹测试资料\\SyntFingerDLL\\测试分类指纹库图片\\0.正常\\1 (1).BMP";
-
char ImagePathName2[
100] =
"E:\\c++code\\指纹测试资料\\SyntFingerDLL\\测试分类指纹库图片\\0.正常\\1 (1).BMP";
-
-
BYTE lpFeature1[
500] = {
0 };
-
BYTE lpFeature2[
500] = {
0 };
-
-
int lpSize1=
0, lpSize2=
0, score=
0;
-
int iReturn =
0;
-
-
//DWORD start_time = GetTickCount();
-
for (
int i =
1; i <
152; i++)
//注意修改循环后面的值
-
{
-
sprintf(ImagePathName1,
"E:\\c++code\\指纹测试资料\\SyntFingerDLL\\测试分类指纹库图片\\0.正常\\1 (%d).BMP", i);
-
for (
int j = i+
1; j <=
152; j++)
//尽量保证假样本多,(n-1)*n/2
-
{
-
sprintf(ImagePathName2,
"E:\\c++code\\指纹测试资料\\SyntFingerDLL\\测试分类指纹库图片\\0.正常\\1 (%d).BMP", j);
-
iReturn = AnalyzeFromFile(ImagePathName1, lpFeature1, &lpSize1);
-
if (iReturn !=
0)
-
{
-
printf(
"从BMP文件中读取图像%d失败\n", i);
-
break;
-
}
-
-
iReturn = AnalyzeFromFile(ImagePathName2, lpFeature2, &lpSize2);
-
if (iReturn !=
0)
-
{
-
printf(
"从BMP文件中读取图像%d失败\n", j);
-
continue;
-
}
-
-
PatternMatch(lpFeature1, lpFeature2, &score);
//对指纹进行比对
-
-
Arr_score1[count1] = score;
-
count1++;
-
cout << count1 <<
",i=" << i <<
",j=" << j <<
endl;
-
}
-
-
}
-
//DWORD end_time = GetTickCount();
-
-
//cout << "The run time is:" << (end_time - start_time)/23436 << "ms!" << endl;
-
-
FILE *f;
-
f = fopen(
"D:\\c++code\\指纹测试资料\\认假test1\\score.txt",
"w");
-
if (f ==
NULL)
-
{
-
printf(
"ERROR!");
-
return;
-
}
-
-
for (
int i =
1; i <=
1000; i++)
-
{
-
int Y_count =
0, N_count =
0;
-
-
for (
int j =
0; j < count1; j++)
-
{
-
if (Arr_score1[j]>=i
-1)
-
{
-
Y_count++;
-
}
-
else
-
{
-
N_count++;
-
}
-
}
-
-
fprintf(f,
"序号=%d,Y_count=%d,N_count=%d,sum=%d,认假率=%lf\n", i, Y_count, N_count, Y_count + N_count, Y_count*
1.0 / (Y_count + N_count));
-
Arr1[i -
1] = Y_count*
1.0 / (Y_count + N_count);
-
}
-
-
for (
int j =
0; j < count1; j++)
-
{
-
fprintf(f,
"序号=%d,score=%d\n", j +
1, Arr_score1[j]);
-
}
-
-
fclose(f);
-
-
return ;
-
}
测试拒真率:
-
int count2 =
0;
-
int Arr_score2[
12000] = {
0 };
-
void test2(double *Arr2)//测试拒真率
-
{
-
char ImagePathName1[
100] =
"D:\\c++code\\指纹测试资料\\指纹采集2014.7.3-bmp\\1 (1)\\1 (1).BMP";
-
char ImagePathName2[
100] =
"D:\\c++code\\指纹测试资料\\指纹采集2014.7.3-bmp\\1 (1)\\1 (1).BMP";
-
-
BYTE lpFeature1[
500] = {
0 };
-
BYTE lpFeature2[
500] = {
0 };
-
-
int lpSize1 =
0, lpSize2 =
0, score =
0;
-
int iReturn =
0;
-
int N=
10;
//修改文件夹方便
-
-
//DWORD start_time = GetTickCount();
-
for (
int k =
1; k <=
232; k++)
-
{
-
for (
int i =
1; i <= N; i++)
//注意修改循环后面的值
-
{
-
sprintf(ImagePathName1,
"D:\\c++code\\指纹测试资料\\指纹采集2014.7.3-bmp\\1 (%d)\\1 (%d).BMP", k, i);
-
for (
int j = i; j <= N; j++)
//不考虑比对过的重复,尽量保证真样本多,n*(n+1)/2
-
{
-
//count++;
-
sprintf(ImagePathName2,
"D:\\c++code\\指纹测试资料\\指纹采集2014.7.3-bmp\\1 (%d)\\1 (%d).BMP", k, j);
-
iReturn = AnalyzeFromFile(ImagePathName1, lpFeature1, &lpSize1);
-
if (iReturn !=
0)
-
{
-
printf(
"从BMP文件中读取图像%d失败\n", i);
-
break;
-
}
-
-
iReturn = AnalyzeFromFile(ImagePathName2, lpFeature2, &lpSize2);
-
if (iReturn !=
0)
-
{
-
printf(
"从BMP文件中读取图像%d失败\n", j);
-
continue;
-
}
-
-
PatternMatch(lpFeature1, lpFeature2, &score);
//对指纹进行比对
-
-
Arr_score2[count2] = score;
-
count2++;
-
cout << count2 <<
",k=" << k <<
",i="<<i<<
",j=" << j <<
endl;
-
}
-
}
-
}
-
-
//DWORD end_time = GetTickCount();
-
-
FILE *f;
-
f = fopen(
"D:\\c++code\\指纹测试资料\\拒真test2\\score.txt",
"w");
-
-
if (f ==
NULL)
-
{
-
printf(
"ERROR!");
-
return ;
-
}
-
-
for (
int i =
1; i <=
1000; i++)
-
{
-
int Y_count =
0, N_count =
0;
-
-
for (
int j =
0; j < count2; j++)
-
{
-
if (Arr_score2[j]>=i
-1)
-
{
-
Y_count++;
-
}
-
else
-
{
-
N_count++;
-
}
-
}
-
fprintf(f,
"score=%d,Y_count=%d,N_count=%d,sum=%d,拒真率=%lf\n", i, Y_count, N_count, Y_count + N_count, N_count*
1.0 / (Y_count + N_count));
-
Arr2[i -
1] = N_count*
1.0 / (Y_count + N_count);
-
}
-
-
for (
int j =
0; j < count2; j++)
-
{
-
fprintf(f,
"序号=%d,score=%d\n", j +
1, Arr_score2[j]);
-
}
-
-
fclose(f);
-
return ;
-
}
-
最后输出各种识别率,存在记事本中:
-
int main()
-
{
-
double Arr1[
1000] = {
0 }, Arr2[
1000] = {
0 }, Arr3[
1000] = {
0 };
-
test2(Arr2);
//测试拒真率
-
test1(Arr1);
//测试认假率
-
-
for (
int i =
0; i <
1000; i++)
-
{
-
Arr3[i] =
1 - (Arr1[i] + Arr2[i]) /
2;
-
}
-
-
FILE *f;
-
f = fopen(
"D:\\c++code\\指纹测试资料\\识别率4.txt",
"w");
-
if (f ==
NULL)
-
{
-
printf(
"ERROR!");
-
return
0;
-
}
-
-
for (
int i =
0; i <
1000; i++)
-
{
-
fprintf(f,
"score=%d,认假率=%lf,拒真率=%lf,识别率=%lf\n", i , Arr1[i],Arr2[i],Arr3[i]);
-
printf(
"score=%d,认假率=%lf,拒真率=%lf,识别率=%lf\n", i , Arr1[i], Arr2[i], Arr3[i]);
-
}
-
fclose(f);
-
-
//test3();
-
system(
"pause");
-
return
0;
-
}
本人一共测试了正副样本大概各10万对左右,在不同的阈值下,指纹的识别率分布大概呈现正态分布,其中score表示阈值,如下图数据记录:
由上图可以看出,当score=19时,识别率=0.965707达到最优峰值。
该项目是传统指纹识别算法,当然识别率不是最优的,至于更优的指纹识别算法版本出于商业机密,暂时不能开源,哈哈,好气是不是,不要打我。
未完待续,空了再继续完善博文
原文地址https://blog.csdn.net/yanxiaolx/article/details/82192343