赞
踩
指纹特征值生成、比对API库需求:
废话不多说,直接上干货,先附上一张指纹算法项目的思路流程图:
- 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;
- }
在此不进行过多重复叙述,
使用VS2015 创建C++动态链接库并调用,原文链接:http://blog.csdn.net/dearkundy/article/details/73331514
使用VS2013 创建C++动态链接库并调用,原文链接:http://blog.csdn.net/zhunianguo/article/details/52294339
测试指纹算法的效果好坏,有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达到最优峰值。
1、指纹采集
(1)柜员到支行以上的部门进行指纹集中采集;
(2)采集时需要同时运行并打开平台、客户端、设备,同时完成联接;
(3)采集时至少采集柜员的三枚手指,优先采集左手手指,同时优先采集食指、中指、大拇指;
(4)采集指纹功能由客户端、设备完成。指纹在设备上获取后,由客户端完成模板的处理,再由客户端上传平台;
(5)平台将客户端上传的柜员号、指纹图像、指纹特征值模板、指头标记进行处理,完成平台用户、柜员、指纹的绑定。
2、指纹比对
(一)柜员签到流程
(1)柜员签到过程中的指纹验证是在系统平台上完成;
(2)首先从终端柜面输入柜员号,然后柜员将注册过的手指在设备上按压来实时采集指纹;
(3)设备对实时采集的指纹图像进行处理并生成指纹特征值,同时上传到平台;
(4)平台将指纹特征值与已采集的指纹模板进行比对,判断合法性;
(5)比对不成功,则返回错误值。比对成功,则平台将柜员关联的用户密码返回给终端;终端柜面根据此密码登录前端系统。
(二)业务授权流程
(1)柜员授权过程中的指纹验证是在系统平台上完成;
(2)在等待输入授权柜员号时,具有授权权限的柜员将注册过的手指按压到设备进行采集指纹;
(3)设备对实时采集的指纹图像进行处理并生成指纹特征值,同时上传到平台;
(4)平台将指纹特征值与已采集的指纹模板进行比对,判断合法性;
(5)比对不成功,则返回错误值。比对成功,则平台将柜员关联的用户密码返回给终端,终端柜面根据此密码完成授权过程。
该项目是传统指纹识别算法,当然识别率不是最优的,至于更优的指纹识别算法版本出于商业机密,暂时不能开源,
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。