当前位置:   article > 正文

指纹模式识别算法源码及其测试和应用方法_指纹比对算法

指纹比对算法

指纹算法需求

指纹特征值生成、比对API库需求:

  1. 可输出指纹图像。图像格式为bmp,小于等于500DPI,不大于50K。
  2. 可输出指纹模板。生成模板需要至少采集几次指纹需说明,建议不超过三次。模板大小不超过1K。模板生成时间不大于1秒。
  3. 可输出指纹特征值(可以是非字符串格式)。特征值大小不超过512B。
  4. 可输出指纹特征值字符串。字符串为可见字符,长度不超1024。
  5. 指纹比对时,支持输入指纹特征值字符串比对。
  6. 指纹比对时,支持输入指纹图像进行比对。
  7. 指纹比对API支持多线程模式,支持大并发调用。
  8. 指纹比对支持1:1,即指纹验证。
  9. 指纹比对支持1:N,即指纹辨识。
  10. 指纹比对时每枚比对速度要求小于0.1秒。
  11. 认假率小于0.0001% 。
  12. 拒真率小于0.75% 。
  13. 库要求32位,但支持在64位操作系统运行。
  14. 可提供dll、jar两种形式API的库。
  • 环境要求

  • 编译环境:VS2013

废话不多说,直接上干货,先附上一张指纹算法项目的思路流程图:

点击这里:指纹项目的算法及其测试完整Github链接

一、先讲解一下指纹算法源码的思路

从指纹图像中提取指纹特征:

  1. int __stdcall Analyze(BYTE *lpImage, int Width, int Height, BYTE *lpFeature, int *lpSize)
  2. {
  3. ///
  4. // Width: [in] 指纹图像宽度
  5. // Height: [in] 指纹图像高度
  6. // lpImage: [in] 指纹图像数据指针
  7. // Resolution: [in] 指纹图像分辨率,默认500
  8. // lpFeature: [out] 提取的指纹特征数据指针
  9. // lpSize: [out] 指纹特征数据大小
  10. // TODO: Add your implementation code here
  11. VF_RETURN re;
  12. // 导入指纹图像数据
  13. VF_ImportFinger(lpImage, Width, Height);
  14. // 处理指纹图像,提取指纹特征
  15. re = VF_Process();
  16. if (re != VF_OK)
  17. return re;
  18. // 对指纹特征进行编码
  19. re = VF_FeatureEncode(&g_Feature, lpFeature, lpSize);
  20. if (re != VF_OK)
  21. return re;
  22. return 0;
  23. }


对两个指纹进行特征比对:

  1. int __stdcall PatternMatch(BYTE *lpFeature1, BYTE *lpFeature2, int *lpScore)
  2. {
  3. // lpFeature1: [in] 第一个指纹特征
  4. // lpFeature2: [in] 第二个指纹特征
  5. // lpScore: [out] 比对的相似度
  6. // FastMode: [in] 是否进行快速模式比对
  7. VF_RETURN re1,re2;
  8. MATCHRESULT mr;
  9. FEATURE feat1, feat2;
  10. // 第一个指纹特征的解码
  11. re1 = VF_FeatureDecode(lpFeature1, &feat1);
  12. if (re1 != VF_OK)
  13. {
  14. printf("图像1解码失败\n");
  15. return 0;
  16. //return re1;
  17. }
  18. // 第二个指纹特征的解码
  19. re2 = VF_FeatureDecode(lpFeature2, &feat2);
  20. if (re2 != VF_OK)
  21. {
  22. printf("图像2解码失败\n");
  23. return 0;
  24. //return re2;
  25. }
  26. *lpScore = 0;
  27. bool FastMode = true;
  28. if (FastMode)
  29. {
  30. // 快速模式的比对
  31. VF_VerifyMatch(&feat1, &feat2, &mr, VF_MATCHMODE_IDENTIFY);
  32. }
  33. else
  34. {
  35. // 精确模式的比对
  36. VF_VerifyMatch(&feat1, &feat2, &mr, VF_MATCHMODE_VERIFY);
  37. }
  38. // 匹配的相似度
  39. //*lpScore = mr.Similarity/10;
  40. *lpScore = mr.Similarity;
  41. /*if (mr.MMCount < 8)
  42. {
  43. *lpScore = 0;
  44. }
  45. else
  46. {
  47. *lpScore = mr.Similarity;
  48. }*/
  49. return 0;
  50. }

二、怎么调用该源码算法库

在此不进行过多重复叙述,

使用VS2015 创建C++动态链接库并调用,原文链接:http://blog.csdn.net/dearkundy/article/details/73331514

使用VS2013 创建C++动态链接库并调用,原文链接:http://blog.csdn.net/zhunianguo/article/details/52294339

三、测试该算法识别率的测试demo

测试指纹算法的效果好坏,有3个指标:拒真率,认假率和识别率

测试的指纹库github已经上传:点击这里

正样本:所有指纹全部来自同一手指

负样本:所有指纹均来自不同手指

拒真率:正样本测试不通过的比率

认假率:负样本测试通过的比率

识别率:1 -(拒真率 + 认假率) / 2

第一个函数,对两个指纹图片的识别进行测试:

  1. void test3()
  2. {
  3.     char ImagePathName1[100] = "D:\\c++code\\test\\1 (1).BMP";
  4.     char ImagePathName2[100] = "D:\\c++code\\test\\1 (1).BMP";
  5.  
  6.     BYTE lpFeature1[500] = { 0 };
  7.     BYTE lpFeature2[500] = { 0 };
  8.  
  9.     int lpSize1 = 0, lpSize2 = 0, score = 0;
  10.     int iReturn = 0;
  11.     
  12.     sprintf(ImagePathName1, "D:\\c++code\\test\\1 (13).BMP");
  13.     sprintf(ImagePathName2, "D:\\c++code\\test\\1 (14).BMP");
  14.             iReturn = AnalyzeFromFile(ImagePathName1, lpFeature1, &lpSize1);
  15.             if (iReturn != 0)
  16.             {
  17.                 printf("从BMP文件中读取图像1失败\n");
  18.             }
  19.  
  20.             iReturn = AnalyzeFromFile(ImagePathName2, lpFeature2, &lpSize2);
  21.             if (iReturn != 0)
  22.             {
  23.                 printf("从BMP文件中读取图像2失败\n");
  24.             }
  25.  
  26.             PatternMatch(lpFeature1, lpFeature2, &score);//对指纹进行比对
  27.  
  28.             if (score >35)//原来是60
  29.             {
  30.                 printf("Same Fingerprint!   \n");
  31.             }
  32.             else
  33.             {
  34.                 printf("Different Fingerprint!  \n");
  35.             }
  36.     
  37.     return;
  38.  
  39. }


测试认假率:

  1. int count1 = 0, Arr_score1[11476] = { 0 };
  2.  
  3. void test1(double *Arr1)//测试认假率
  4. {
  5.     char ImagePathName1[100] = "E:\\c++code\\指纹测试资料\\SyntFingerDLL\\测试分类指纹库图片\\0.正常\\1 (1).BMP";
  6.     char ImagePathName2[100] = "E:\\c++code\\指纹测试资料\\SyntFingerDLL\\测试分类指纹库图片\\0.正常\\1 (1).BMP";
  7.  
  8.     BYTE lpFeature1[500] = { 0 };
  9.     BYTE lpFeature2[500] = { 0 };
  10.  
  11.     int lpSize1=0, lpSize2=0, score=0;
  12.     int iReturn = 0;
  13.  
  14.     //DWORD start_time = GetTickCount();
  15.     for (int i = 1; i <152; i++)//注意修改循环后面的值
  16.     {
  17.         sprintf(ImagePathName1, "E:\\c++code\\指纹测试资料\\SyntFingerDLL\\测试分类指纹库图片\\0.正常\\1 (%d).BMP", i);
  18.         for (int j = i+1; j <=152; j++)//尽量保证假样本多,(n-1)*n/2
  19.         {
  20.             sprintf(ImagePathName2, "E:\\c++code\\指纹测试资料\\SyntFingerDLL\\测试分类指纹库图片\\0.正常\\1 (%d).BMP", j);
  21.             iReturn = AnalyzeFromFile(ImagePathName1, lpFeature1, &lpSize1);
  22.             if (iReturn != 0)
  23.             {
  24.                 printf("从BMP文件中读取图像%d失败\n", i);
  25.                 break;
  26.             }
  27.  
  28.             iReturn = AnalyzeFromFile(ImagePathName2, lpFeature2, &lpSize2);
  29.             if (iReturn != 0)
  30.             {
  31.                 printf("从BMP文件中读取图像%d失败\n", j);
  32.                 continue;
  33.             }
  34.  
  35.             PatternMatch(lpFeature1, lpFeature2, &score);//对指纹进行比对
  36.  
  37.                 Arr_score1[count1] = score;
  38.                 count1++;    
  39.                 cout << count1 <<",i=" << i << ",j=" << j << endl;
  40.         }
  41.         
  42.     }
  43.     //DWORD end_time = GetTickCount();
  44.     
  45.     //cout << "The run time is:" << (end_time - start_time)/23436 << "ms!" << endl;
  46.  
  47.         FILE *f; 
  48.         f = fopen("D:\\c++code\\指纹测试资料\\认假test1\\score.txt", "w"); 
  49.         if (f == NULL)
  50.         {
  51.             printf("ERROR!");
  52.             return;
  53.         }
  54.         
  55.         for (int i = 1; i <= 1000; i++)
  56.         {
  57.             int Y_count = 0, N_count = 0;
  58.  
  59.             for (int j = 0; j < count1; j++)
  60.             {
  61.                 if (Arr_score1[j]>=i-1)
  62.                 {
  63.                     Y_count++;
  64.                 }
  65.                 else
  66.                 {
  67.                     N_count++;
  68.                 }
  69.             }
  70.  
  71.             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));
  72.             Arr1[i - 1] = Y_count*1.0 / (Y_count + N_count);
  73.         }
  74.  
  75.         for (int j = 0; j < count1; j++)
  76.         {
  77.             fprintf(f, "序号=%d,score=%d\n", j + 1, Arr_score1[j]);
  78.         }
  79.  
  80.         fclose(f);
  81.  
  82.         return ;
  83. }


测试拒真率:

  1. int count2 = 0;
  2. int Arr_score2[12000] = { 0 };
  3. void test2(double *Arr2)//测试拒真率
  4. {
  5.     char ImagePathName1[100] = "D:\\c++code\\指纹测试资料\\指纹采集2014.7.3-bmp\\1 (1)\\1 (1).BMP";
  6.     char ImagePathName2[100] = "D:\\c++code\\指纹测试资料\\指纹采集2014.7.3-bmp\\1 (1)\\1 (1).BMP";
  7.  
  8.     BYTE lpFeature1[500] = { 0 };
  9.     BYTE lpFeature2[500] = { 0 };
  10.  
  11.     int lpSize1 = 0, lpSize2 = 0, score = 0;
  12.     int iReturn = 0;
  13.     int N=10;//修改文件夹方便
  14.     
  15.     //DWORD start_time = GetTickCount();
  16.     for (int k =1; k <= 232; k++)
  17.     {
  18.         for (int i = 1; i <= N; i++)//注意修改循环后面的值
  19.         {
  20.             sprintf(ImagePathName1, "D:\\c++code\\指纹测试资料\\指纹采集2014.7.3-bmp\\1 (%d)\\1 (%d).BMP", k, i);
  21.             for (int j = i; j <= N; j++)//不考虑比对过的重复,尽量保证真样本多,n*(n+1)/2
  22.             {
  23.                 //count++;
  24.                 sprintf(ImagePathName2, "D:\\c++code\\指纹测试资料\\指纹采集2014.7.3-bmp\\1 (%d)\\1 (%d).BMP", k, j);
  25.                 iReturn = AnalyzeFromFile(ImagePathName1, lpFeature1, &lpSize1);
  26.                 if (iReturn != 0)
  27.                 {
  28.                     printf("从BMP文件中读取图像%d失败\n", i);
  29.                     break;
  30.                 }
  31.  
  32.                 iReturn = AnalyzeFromFile(ImagePathName2, lpFeature2, &lpSize2);
  33.                 if (iReturn != 0)
  34.                 {
  35.                     printf("从BMP文件中读取图像%d失败\n", j);
  36.                     continue;
  37.                 }
  38.  
  39.                 PatternMatch(lpFeature1, lpFeature2, &score);//对指纹进行比对
  40.  
  41.                 Arr_score2[count2] = score;
  42.                 count2++;
  43.                 cout << count2 << ",k=" << k << ",i="<<i<<",j=" << j << endl;
  44.             }
  45.         }
  46.     }
  47.  
  48.     //DWORD end_time = GetTickCount();
  49.  
  50.     FILE *f; 
  51.     f = fopen("D:\\c++code\\指纹测试资料\\拒真test2\\score.txt", "w"); 
  52.  
  53.     if (f == NULL
  54.     { 
  55.         printf("ERROR!"); 
  56.         return
  57.     } 
  58.     
  59.     for (int i = 1; i <= 1000; i++)
  60.     {
  61.         int Y_count = 0, N_count = 0;
  62.  
  63.         for (int j = 0; j < count2; j++)
  64.         {
  65.             if (Arr_score2[j]>=i-1)
  66.             {
  67.                 Y_count++;
  68.             }
  69.             else
  70.             {
  71.                 N_count++;
  72.             }
  73.         }
  74.         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));
  75.         Arr2[i - 1] = N_count*1.0 / (Y_count + N_count);
  76.     }
  77.  
  78.     for (int j = 0; j < count2; j++)
  79.     {
  80.         fprintf(f, "序号=%d,score=%d\n", j + 1, Arr_score2[j]);
  81.     }
  82.  
  83.     fclose(f);
  84.     return ;
  85. }

最后输出各种识别率,存在记事本中:

  1. int main()
  2. {
  3.     double Arr1[1000] = { 0 }, Arr2[1000] = { 0 }, Arr3[1000] = { 0 };
  4.     test2(Arr2);//测试拒真率
  5.     test1(Arr1);//测试认假率
  6.  
  7.     for (int i = 0; i < 1000; i++)
  8.     {
  9.         Arr3[i] = 1 - (Arr1[i] + Arr2[i]) / 2;
  10.     }
  11.  
  12.     FILE *f;
  13.     f = fopen("D:\\c++code\\指纹测试资料\\识别率4.txt", "w");
  14.     if (f == NULL)
  15.     {
  16.         printf("ERROR!");
  17.         return 0;
  18.     }
  19.  
  20.     for (int i = 0; i <1000; i++)
  21.     {
  22.         fprintf(f, "score=%d,认假率=%lf,拒真率=%lf,识别率=%lf\n", i , Arr1[i],Arr2[i],Arr3[i]);
  23.         printf("score=%d,认假率=%lf,拒真率=%lf,识别率=%lf\n", i , Arr1[i], Arr2[i], Arr3[i]);
  24.     }
  25.     fclose(f);
  26.  
  27.     //test3();
  28.     system("pause");
  29.     return 0;
  30. }


本人一共测试了正副样本大概各10万对左右,在不同的阈值下,指纹的识别率分布大概呈现正态分布,其中score表示阈值,如下图数据记录:

由上图可以看出,当score=19时,识别率=0.965707达到最优峰值。

下面举例聊聊指纹算法在银行的业务应用流程:

1、指纹采集

(1)柜员到支行以上的部门进行指纹集中采集;

(2)采集时需要同时运行并打开平台、客户端、设备,同时完成联接;

(3)采集时至少采集柜员的三枚手指,优先采集左手手指,同时优先采集食指、中指、大拇指;

(4)采集指纹功能由客户端、设备完成。指纹在设备上获取后,由客户端完成模板的处理,再由客户端上传平台;

(5)平台将客户端上传的柜员号、指纹图像、指纹特征值模板、指头标记进行处理,完成平台用户、柜员、指纹的绑定。

2、指纹比对

(一)柜员签到流程

(1)柜员签到过程中的指纹验证是在系统平台上完成;

(2)首先从终端柜面输入柜员号,然后柜员将注册过的手指在设备上按压来实时采集指纹;

(3)设备对实时采集的指纹图像进行处理并生成指纹特征值,同时上传到平台;

(4)平台将指纹特征值与已采集的指纹模板进行比对,判断合法性;

(5)比对不成功,则返回错误值。比对成功,则平台将柜员关联的用户密码返回给终端;终端柜面根据此密码登录前端系统。

(二)业务授权流程

(1)柜员授权过程中的指纹验证是在系统平台上完成;

(2)在等待输入授权柜员号时,具有授权权限的柜员将注册过的手指按压到设备进行采集指纹;

(3)设备对实时采集的指纹图像进行处理并生成指纹特征值,同时上传到平台;

(4)平台将指纹特征值与已采集的指纹模板进行比对,判断合法性;

(5)比对不成功,则返回错误值。比对成功,则平台将柜员关联的用户密码返回给终端,终端柜面根据此密码完成授权过程。

该项目是传统指纹识别算法,当然识别率不是最优的,至于更优的指纹识别算法版本出于商业机密,暂时不能开源,
 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/765009
推荐阅读
相关标签
  

闽ICP备14008679号