一款开源的指纹识别SDK
来源:互联网 发布:淘宝 无人机 编辑:程序博客网 时间:2024/04/25 01:52
Biometric SDK 是一个开源的指纹识别开发包,可匹配和标识人们的指纹。计算指纹相似度
关键代码:
/* Biometric SDK Version 1.3 This file contains functions that manipulate , extract features and match fingerprint images. Copyright (C) 2005 Scott Johnston Email : moleisking@googlemail.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */using System;using System.Drawing;using System.Drawing.Drawing2D;namespace BiometricsSDK.FingerPrint{/// <summary>/// Summary description for CFinger./// </summary>public class CFingerPrint {//used for image//for digital persona with kit//public int FP_IMAGE_WIDTH = 500;//public int FP_IMAGE_HEIGHT = 500;//for verifinger with kit public int FP_IMAGE_WIDTH = 323;public int FP_IMAGE_HEIGHT = 352;//Used by template//be carefull the size of the array must always be 1 larger than a number divisable by 4public int FP_TEMPLATE_MAX_SIZE = 601; //used for matching//the max distance between to points when comparing two points to count as a matchpublic int FP_MATCH_POINT_DISTANCE_MOVEMENT = 10;//the max rotation to use when comparint two points to count as a matchpublic int FP_MATCH_POINT_ROTATION_MOVEMENT = 10;//10;//a percentagepublic int FP_MATCH_THRESHOLD = 55;//finger print classifications//Wirbel classpublic const int FP_CLASS_WHORL = 1 ;//lasso classpublic const int FP_CLASS_LEFT_LOOP = 2;public const int FP_CLASS_RIGHT_LOOP = 3;public const int FP_CLASS_ARCH = 4;public const int FP_CLASS_ARCH_TENTED = 5;//fingerprint template valuesprivate const int FP_TEMPLATE_SIZE = 0;private const int FP_TEMPLATE_ORIGIN_X = 1;private const int FP_TEMPLATE_ORIGIN_Y = 2;private const int FP_TEMPLATE_FEATURE_SIZE = 6;private const int FP_TEMPLATE_SEARCH_RADIUS = 1; //fingerprint origin values //private int FP_ORIGIN_SEARCH_RADIUS = 5;//holds skeletinized imagepublic byte [,] P = new byte[500,500];public CFingerPrint(){}public CFingerPrint(int width , int height ){FP_IMAGE_WIDTH = width;FP_IMAGE_HEIGHT = height;P = new byte[width,height];}public CFingerPrint(int width , int height ,int MatchPointDistanceMovement , int MatchPointRotationMovment , int MatchThreshold ){FP_IMAGE_WIDTH = width;FP_IMAGE_HEIGHT = height;FP_MATCH_POINT_DISTANCE_MOVEMENT = MatchPointDistanceMovement;FP_MATCH_POINT_ROTATION_MOVEMENT = MatchPointRotationMovment;FP_MATCH_THRESHOLD = MatchThreshold;} /// <summary> /// /// </summary> /// <param name="m_image"></param>public void setFingerPrintImage(Bitmap m_image){ try { int h = m_image.Height;//原代码为:FP_IMAGE_HEIGHT,现替换为:h int w = m_image.Width;//原代码为:FP_IMAGE_WIDTH,现替换为:w for (int i = 0; i <= w - 1; i++) { for (int j = 0; j <= h - 1; j++) { if ((m_image.GetPixel(i, j).B <= 127) && (m_image.GetPixel(i, j).R <= 127) && (m_image.GetPixel(i, j).G <= 127)) { P[i, j] = 1; } else { P[i, j] = 0; } } } //set edges to 0 for (int i = 0; i <= w - 1; i++) { P[i, 0] = 0; P[i, h - 1] = 0; } for (int j = 0; j <= h - 1; j++) { P[0, j] = 0; P[w - 1, j] = 0; } } catch (Exception ex) { throw ex; }}public Bitmap getFingerPrintImage(){ Bitmap imageBuffer = new Bitmap(FP_IMAGE_WIDTH, FP_IMAGE_HEIGHT);for (int i = 0; i<= FP_IMAGE_WIDTH - 1;i++){for (int j = 0;j<= FP_IMAGE_HEIGHT - 1;j++){ if (P[i, j] == 1) { imageBuffer.SetPixel(i, j, Color.Blue); } else { imageBuffer.SetPixel(i, j, Color.White); }}}return imageBuffer;}public Bitmap getFingerPrintImageDetail(){//set finger print imageBitmap imageBuffer = new Bitmap(FP_IMAGE_WIDTH,FP_IMAGE_HEIGHT );for (int i = 0; i<= FP_IMAGE_WIDTH - 1;i++){for (int j = 0;j<= FP_IMAGE_HEIGHT - 1;j++){if (P[i,j] == 1)imageBuffer.SetPixel(i,j,Color.Blue);elseimageBuffer.SetPixel(i,j,Color.White );}}//get featuresdouble[] m_arr = this.getFingerPrintTemplate();//int linelength = 5;//draw pointsPen penBlue = new Pen(Color.Blue, 1); Pen penRed = new Pen(Color.Red, 1);Pen penGreen = new Pen(Color.Green, 1);Pen penGray = new Pen(Color.Gray, 1);//Graphics gf = Graphics.FromImage(Image.FromHbitmap(m_ImageBuffer.GetHbitmap() ));Graphics gf = Graphics.FromImage(imageBuffer);gf.CompositingMode = CompositingMode.SourceOver;for(int i=7 ; i<=m_arr[0]-1;i=i+6){if(m_arr[i+4]>1){gf.DrawRectangle(penRed,(int)m_arr[i]+(int)m_arr[1]-3,(int)m_arr[i+1]+(int)m_arr[2]-2,5,5);}else if(m_arr[i+4]==1){gf.DrawEllipse(penGreen,(int)m_arr[i]+(int)m_arr[1]-3,(int)m_arr[i+1]+(int)m_arr[2]-2,5,5);} }//end for//draws the origingf.DrawLine(penGray,(int)m_arr[1]-5,(int)m_arr[2],(int)m_arr[1]+5,(int)m_arr[2]);gf.DrawLine(penGray,(int)m_arr[1],(int)m_arr[2]-5,(int)m_arr[1],(int)m_arr[2]+5);return imageBuffer;}//end getFingerPrintImageDetail()public void ThinningHilditch(){int change = 1;bool mbool = true;while (change != 0){change = 0;for(int i = 2; i <= FP_IMAGE_WIDTH - 2;i++){for(int j = 2; j <= FP_IMAGE_HEIGHT - 2;j++){if (P[i,j] == 1){short c = 0;//count surrounding 1//a) Make sure pixel 1, has 2 to 6 (inclusive) neighborsif (P[i,j+1] == 1) { c++;}if (P[i+1,j+1] == 1) { c++;}if (P[i+1,j] == 1) { c++;}if (P[i+1,j-1] == 1) { c++;}if (P[i,j-1] == 1) { c++;}if (P[i-1,j-1] == 1) { c++;}if (P[i-1,j] == 1) { c++;}if (P[i-1,j+1] == 1) { c++;}if ((c >= 2) && (c <= 6 )){c = 0;//b) starting from 2, go clockwise until 9, and count the//' number of 0 to 1 transitions. This should be equal to 1.if ((P[i-1,j+1] == 0) && (P[i,j+1] == 1)) { c++;}if ((P[i,j+1] == 0) && (P[i+1,j+1] == 1)) { c++;}if ((P[i+1,j+1] == 0) && (P[i+1,j] == 1)) { c++;}if ((P[i+1,j] == 0) && (P[i+1,j-1] == 1)) { c++;}if ((P[i + 1,j-1] == 0) && (P[i,j-1] == 1)) { c++;}if ((P[i,j-1] == 0) && (P[i-1,j-1] == 1)) { c++;}if ((P[i-1,j-1] == 0) && (P[i-1,j] == 1)) { c++;}if ((P[i - 1,j] == 0) && (P[i-1,j+1] == 1)) { c++;}if (c == 1 ){c = 0;if (mbool == true){//c) 2*4*6=0 (ie either 2,4 ,or 6 is off)if ((P[i,j+1] * P[i+1,j] * P[i+1,j-1]) == 0 ){//d) 4*6*8=0if ((P[i+1,j] * P[i+1,j-1] * P[i-1,j]) == 0 ){P[i,j] = 0;change++;}}mbool = false;}else{//c) 2*6*8=0if ((P[i,j+1] * P[i+1,j-1] * P[i-1,j]) == 0){//d) 2*4*8=0if ((P[i,j+1] * P[i+1,j] * P[i-1,j]) == 0){P[i,j] = 0;change++;}}mbool = true;}}}}}}}//End While}//end ThinningHilditchAlgorithimpublic void ThinningHitAndMiss(){/** basicly you take all patterns* 111 X1X* X1X or x11 so on* 000 xxX* if these conditions are true then set the middle 1 to 0*/int c = 1;while (c != 0){c = 0;for(int i = 1;i<=FP_IMAGE_WIDTH - 1;i++){for(int j = 1;j<=FP_IMAGE_HEIGHT - 1;j++){if ((P[i,j] == 1) && (i != 0) && (j != FP_IMAGE_HEIGHT - 1) && (j != 0) && (i != FP_IMAGE_WIDTH - 1)){if ((P[i-1,j-1] == 1) &&( P[i,j-1] == 1) && (P[i+1,j-1] == 1) && (P[i-1,j+1] == 0) && (P[i,j+1] == 0) && (P[i+1,j+1] == 0)){P[i,j] = 0; //'1 on bottomc++;}else if ((P[i-1,j+1] == 1) && (P[i,j+1] == 1) && (P[i+1,j+1] == 1) && (P[i-1,j-1] == 0) && (P[i,j-1] == 0) && (P[i+1,j-1] == 0)){P[i,j] = 0; //'1 on topc++;}else if ((P[i-1,j] == 1) && (P[i-1,j - 1] == 1) && (P[i-1,j+1] == 1) && (P[i+1,j] == 0) && (P[i+1,j+1] == 0) && (P[i+1,j-1] == 0)){P[i,j] = 0; //'1 on leftc++;}else if ((P[i+1,j] == 1) && (P[i+1,j-1] == 1) && (P[i+1,j+1] == 1) && (P[i-1,j] == 0) && (P[i-1,j+1] == 0) && (P[i-1,j-1] == 0) ){P[i,j] = 0; //'1 on rightc++;}else if ((P[i-1,j] == 1) && (P[i,j-1] == 1) && (P[i,j+1] == 0) && (P[i+1,j+1] == 0) && (P[i + 1,j] == 0)){//x00//110//x1xP[i,j] = 0; //'1 on Bottem Leftc++;}else if ((P[i-1,j] == 1) && (P[i,j+1] == 1) && (P[i,j-1] == 0) && (P[i+1,j-1] == 0) && (P[i+1,j] == 0)){//x1x//110//x00P[i,j] = 0; //'1 on Top Leftc++;}else if ((P[i,j+1]== 1) && (P[i+1,j] == 1) && (P[i-1,j] == 0) && (P[i-1,j-1] == 0) && (P[i,j-1] == 0)){//x1x//011//00xP[i,j] = 0; //'1 on Top Rightc++;}else if ((P[i,j-1] == 1) && (P[i+1,j] == 1) && (P[i-1,j] == 0) && (P[i-1,j+1] == 0) && (P[i,j+1] == 0) ){//00x//011//x1xP[i,j] = 0; //'1 on Bottom Rightc++;}}}//Next}//Next}//End While}//end ThinningHitAndMisspublic void ChaneLinkAlgorithm(int ChainLinkDistance){//short count1;for(int i = 1;i<= FP_IMAGE_WIDTH - 1;i++){for (int j = 1 ; j <= FP_IMAGE_HEIGHT - 1;j++){//change second condition when changeing direction//Horizontalif ((P[i,j] == 1) && (i != FP_IMAGE_WIDTH - 1) && (i != 0) && (j != FP_IMAGE_HEIGHT - 1) && (j != 0)){if (P[i + 1,j] == 0){short countX = 0;//count Horizontal Holewhile (((i + countX) <= FP_IMAGE_WIDTH - 1) && (countX <= ChainLinkDistance)){if (((i + countX + 1) <= FP_IMAGE_WIDTH - 1) && ((countX + 1) <= ChainLinkDistance)){if (P[i + countX + 1,j] == 0){countX++;}else{break;}}else{break;}}//Fill hole if it is wide enoughif ((countX != 0) && ((countX + 1) <= ChainLinkDistance)){for (int temp = 0; temp<= countX;temp++){P[i+temp,j] = 1;}}}}//change second condition when changeing direction//Verticalif ((P[i,j] == 1) && (i != FP_IMAGE_WIDTH - 1) && (i != 0) && (j != FP_IMAGE_HEIGHT - 1) && (j != 0)){if (P[i,j+1] == 0 ){short countY = 0;//count Horizontal Holewhile (((j + countY) <= FP_IMAGE_HEIGHT-1) && (countY <= ChainLinkDistance)){if (((j + countY + 1) <= FP_IMAGE_HEIGHT-1) && ((countY + 1) <= ChainLinkDistance) ){//i pu this here bacause it kept on crashingif (P[i,j + countY + 1] == 0){countY++;}else{break;}}else{break;}}//Fill hole if it is wide enoughif ((countY != 0) && (countY + 1 <= ChainLinkDistance)){for(int temp = 0;temp<= countY;temp++){P[i,j + temp] = 1;}}}}//change second condition when changeing direction//Vertical Horizontalif ((P[i,j] == 1) && (i != FP_IMAGE_WIDTH - 1) && (i != 0) && (j != FP_IMAGE_HEIGHT - 1) && (j != 0)){if (P[i + 1,j + 1] == 0){short countYX = 0; //1//count Horizontal Holewhile ((j + countYX <= FP_IMAGE_HEIGHT-1) && (i + countYX <= FP_IMAGE_WIDTH-1) && (countYX <= ChainLinkDistance)){if (((j + countYX + 1) <= FP_IMAGE_HEIGHT-1) && ((i + countYX + 1) <= FP_IMAGE_WIDTH-1) && ((countYX + 1) <= ChainLinkDistance))if (P[i+countYX+1,j + countYX + 1] == 0){countYX++;}else{break;}else{break;}}//Fill hole if it is wide enoughif ((countYX != 0) && (countYX + 1 <= ChainLinkDistance)){for(int temp = 0 ; temp <= countYX ; temp++){P[i+temp,j+temp] = 1;}}}}}}} /// <summery>/// /// ################################/// # Extract Origin #/// ################################/// /// In future i want to use the gradients to classifie the finger print into the 5 different /// catagories which are marked in the FP_CLASS./// /// This function still needs to improved and somtimes dosen't find the center of the finger print./// /// The principle in finding the centre is simple , just find the greatest change in the gradient/// bettween two lines and you have your centre./// /// To find the classification you have to find the average changes in gradients in the different /// sectors (if you divided your picture in 4 using the fingerprint centre as the centre).You should /// then classifie the fingerprint according to this./// /// <summery>private Point getFingerPrintOrigin(){Point m_Point = new Point();double gradcur=0;double gradprev=0;double gradchangebig=0;double gradchange=0; double graddistancebig=0;double graddistance=0; double prevx=0;double prevy=0; for(int j =50;j<=FP_IMAGE_HEIGHT-50;j++){ for(int i =50;i<=FP_IMAGE_WIDTH-50;i++){if(P[i,j]==1){//count surrounding pixelsint tc=0;int x1=0;int y1=0;int x2=0;int y2=0;//find surrounding 1sfor (int m = -1*FP_TEMPLATE_SEARCH_RADIUS;m<=FP_TEMPLATE_SEARCH_RADIUS;m++){for (int n = -1*FP_TEMPLATE_SEARCH_RADIUS;n<=FP_TEMPLATE_SEARCH_RADIUS;n++){if ((m==FP_TEMPLATE_SEARCH_RADIUS)||(m==(-1)*FP_TEMPLATE_SEARCH_RADIUS)||(n==FP_TEMPLATE_SEARCH_RADIUS)||(n==(-1)*FP_TEMPLATE_SEARCH_RADIUS)){if(P[i+m,j+n] == 1 ){tc++;if (tc==1){x1=i+m;y1=j+n;}if (tc==2){x2=i+m;y2=j+n;}}//end if}//end if}//end for n} //end for m //does all the hard work of finding the greatest change in gradientif(tc==2){if ((x2-x1)>0){ gradcur = (y2-y1)/(x2-x1);//check to see gradient change by at least 270 degreesif((gradcur>0)&&(gradprev<0)){gradchange = Math.Abs(gradcur) + Math.Abs(gradprev) ; graddistance = Math.Abs(i) - Math.Abs(prevx); if(gradchangebig<gradchange){if (graddistancebig<graddistance){gradchangebig=gradchange;graddistancebig=graddistance;m_Point.X=i;//FP_ORIGIN_X =i;m_Point.Y=j;//FP_ORIGIN_Y =j;}}break;}//reset varibles for new checksgradprev=gradcur;gradcur=0;prevx=i;prevy=j;}//(x2-x1)>0}//end if tc==2}//end if P[x,y]==1}//end for i}//end for j// JOptionPane.showMessageDialog (null,Integer.toString(FP_ORIGIN_X)+";"+Integer.toString(FP_ORIGIN_Y),"getFingerPrintOrigin",JOptionPane.PLAIN_MESSAGE);return m_Point;}private int getFingerPrintClassification(){Point m_Point = this.getFingerPrintOrigin();double gradcur=0; //stores total gradient of cornersdouble gradlt=0;double gradrt=0;double gradlb=0;double gradrb=0; //counts total of each corner gradientdouble cgradlt=0;double cgradrt=0;double cgradlb=0;double cgradrb=0; for(int j =50;j<=FP_IMAGE_HEIGHT-50;j++){ for(int i =50;i<=FP_IMAGE_WIDTH-50;i++){if(P[i,j]==1){//count surrounding pixelsint tc=0;int x1=0;int y1=0;int x2=0;int y2=0;//find surrounding 1sfor (int m = -1*FP_TEMPLATE_SEARCH_RADIUS;m<=FP_TEMPLATE_SEARCH_RADIUS;m++){for (int n = -1*FP_TEMPLATE_SEARCH_RADIUS;n<=FP_TEMPLATE_SEARCH_RADIUS;n++){if ((m==FP_TEMPLATE_SEARCH_RADIUS)||(m==(-1)*FP_TEMPLATE_SEARCH_RADIUS)||(n==FP_TEMPLATE_SEARCH_RADIUS)||(n==(-1)*FP_TEMPLATE_SEARCH_RADIUS)){if(P[i+m,j+n] == 1 ){tc++;if (tc==1){x1=i+m;y1=j+n;}if (tc==2){x2=i+m;y2=j+n;}}//end if}//end if}//end for n} //end for m //does all the hard work of finding the greatest change in gradientif(tc==2){if ((x2-x1)>0){ gradcur = (y2-y1)/(x2-x1);//check to see gradient change by at least 270 degreesif ((x2<m_Point.X)&&(y2>m_Point.Y)){ gradlt=gradlt+gradcur;gradlt++;} else if ((x2>m_Point.X)&&(y2>m_Point.Y)){ gradrt=gradrt+gradcur;gradrt++;} else if ((x2<m_Point.X)&&(y2<m_Point.Y)){ gradlb=gradlb+gradcur;gradlb++;} else if ((x2>m_Point.X)&&(y2<m_Point.Y)){ gradrb=gradrb+gradcur;gradrb++;} }//(x2-x1)>0}//end if tc==2}//end if P[x,y]==1}//end for i}//end for j//get average gradient for 4 cornersgradlb=gradlb/cgradlb;gradrb=gradrb/cgradrb;gradlt=gradlt/cgradlt;gradrt=gradrt/cgradrt;//determin classification according to gradient//needs workif ((gradlt>0)&&(gradrt>0)&&(gradlb>0)&&(gradrb>0)){return FP_CLASS_WHORL;}else if ((gradlt>0)&&(gradrt>0)&&(gradlb>0)&&(gradrb>0)){return FP_CLASS_LEFT_LOOP;}else if ((gradlt>0)&&(gradrt>0)&&(gradlb>0)&&(gradrb>0)){return FP_CLASS_RIGHT_LOOP;}else if ((gradlt>0)&&(gradrt>0)&&(gradlb>0)&&(gradrb>0)){return FP_CLASS_ARCH;}else if ((gradlt>0)&&(gradrt>0)&&(gradlb>0)&&(gradrb>0)){return FP_CLASS_ARCH_TENTED;}else{return 1;} // JOptionPane.showMessageDialog (null,Integer.toString(FP_ORIGIN_X)+";"+Integer.toString(FP_ORIGIN_Y),"getFingerPrintOrigin",JOptionPane.PLAIN_MESSAGE);} /*<summery> ################################ # Extract Template # ################################ The template will have to be formated according to the ISO standards as set out buy NIST , NIST also has a set of binary pictures to use for examples. This database is used for determaning the FAR(False Acceptance Rate) and FRR (False Rejection Rate) First 7 are (elements in array , originx , originy , null , null , null ,null) after that the format is (x,y,r,degree ,number of ends,resultant degree).The size of the array is always pre set. There is also future work that needs to be done on genralization , basicly what this means is that you take 3 finger templates , then take the features that are common to all three templeate and you will then come out with a generalized template.This will improve quality of the template. </summery>*/public double[] getFingerPrintTemplate(){// final int SEARCH_RADIUS = 1; double x=0;double y=0;double r=0;double d=0;double[] m_arr = new double[FP_TEMPLATE_MAX_SIZE]; this.ThinningHilditch();this.ThinningHitAndMiss();this.ThinningHilditch();this.ThinningHitAndMiss(); Point origin = this.getFingerPrintOrigin(); m_arr[1]=origin.X;m_arr[2]=origin.Y; int c = 7 ;int previ=0;int prevj=0; bool first = true; //start from 5 units in to avoid detection of edges of finger print and out of bound exceptionsfor(int j = 5 ;j<= FP_IMAGE_HEIGHT - 6;j++){first = true; for( int i =5 ;i<= FP_IMAGE_WIDTH - 6;i++){if ((c<FP_TEMPLATE_MAX_SIZE)&&(P[i,j] == 1) && (i != FP_IMAGE_WIDTH - 1) && (i != 0) && (j != FP_IMAGE_HEIGHT - 1) && (j != 0) ){/* * Must not capture first and last feature because those are the edges of the finger print* and will provide no value to the template.*/ if(first == true){first = false;//cheak to see if previos item in array was aslo endif( (c>7)&&((m_arr[c-6]+origin.X)==previ)&&((m_arr[c-5]+origin.Y)==prevj) ){//delete previos featuem_arr[c--]=0;m_arr[c--]=0;m_arr[c--]=0;m_arr[c--]=0;m_arr[c--]=0;m_arr[c--]=0; }}else{int tc = 0;for (int m = -1*FP_TEMPLATE_SEARCH_RADIUS;m<=FP_TEMPLATE_SEARCH_RADIUS;m++){for (int n = -1*FP_TEMPLATE_SEARCH_RADIUS;n<=FP_TEMPLATE_SEARCH_RADIUS;n++){if ((m==FP_TEMPLATE_SEARCH_RADIUS)||(m==(-1)*FP_TEMPLATE_SEARCH_RADIUS)||(n==FP_TEMPLATE_SEARCH_RADIUS)||(n==(-1)*FP_TEMPLATE_SEARCH_RADIUS)){if(P[i+m,j+n] == 1 ){tc++;}//end if}//end if}//end for n} //end for m //calculate parameters necesary for templateif ((tc==1)||(tc==3)){x = i- origin.X;y = j- origin.Y;r = Math.Sqrt(x*x + y*y);if ((x>0)&&(y>0)){d =Math.Atan(y/x);}else if ((x<0)&&(y>0)){d =Math.Atan(y/x) - Math.PI ;}else if ((x<0)&&(y<0)){d =Math.PI + Math.Atan(y/x);}else if ((x>0)&&(y<0)){d =2*Math.PI + Math.Atan(y/x);}} //check to see if point already been capturedbool foundx = false; bool foundy = false; for (int m=7;m<=c;m=m+6){if(m_arr[m+4]==3){if(Math.Abs(Math.Abs((int)m_arr[m])-Math.Abs(x))<4){foundx=true;}if(Math.Abs(Math.Abs((int)m_arr[m+1])-Math.Abs(y))<4){foundy=true;}}//end if}//end for m //1 surrounding 1sif ((tc==1) && (c <= FP_TEMPLATE_MAX_SIZE-6) && (x!=0) && (y!=0) && ((foundx==false)||(foundy==false)) ){ if (P[i-1,j+1] == 1) {m_arr[c++] = x;m_arr[c++] = y;m_arr[c++] = r;m_arr[c++] = d;m_arr[c++] = 1 ;m_arr[c++] = 135 ;}else if (P[i,j+1] == 1){m_arr[c++] = x;m_arr[c++] = y;m_arr[c++] = r;m_arr[c++] = d;m_arr[c++] = 1 ;m_arr[c++] =90 ;}else if (P[i+1,j+1] == 1){m_arr[c++] = x;m_arr[c++] = y;m_arr[c++] = r;m_arr[c++] = d;m_arr[c++] = 1 ;m_arr[c++] =45 ;}else if (P[i+1,j] == 1) {m_arr[c++] = x;m_arr[c++] = y;m_arr[c++] = r;m_arr[c++] = d;m_arr[c++] = 1 ;m_arr[c++] = 0 ;}else if (P[i+1,j-1] == 1){m_arr[c++] = x;m_arr[c++] = y;m_arr[c++] = r;m_arr[c++] = d;m_arr[c++] = 1 ;m_arr[c++] =315 ;}else if (P[i,j-1] == 1){m_arr[c++] = x;m_arr[c++] = y;m_arr[c++] = r;m_arr[c++] = d;m_arr[c++] = 1 ;m_arr[c++] = 270 ;}else if (P[i-1,j-1] == 1){m_arr[c++] = x;m_arr[c++] = y;m_arr[c++] = r;m_arr[c++] = d;m_arr[c++] = 1 ;m_arr[c++] = 225 ;}else if (P[i-1, j] == 1 ) {m_arr[c++] = x;m_arr[c++] = y;m_arr[c++] = r;m_arr[c++] = d;m_arr[c++] = 1 ;m_arr[c++] = 180 ;}}else if ((tc>=3)&&(c <= FP_TEMPLATE_MAX_SIZE - 6)&&(x!=0)&&(y!=0)&&((foundx==false)||(foundy==false)) ){ //3 surrounding 1sm_arr[c++] = x;m_arr[c++] = y;m_arr[c++] = r;m_arr[c++] = d;m_arr[c++] = 3;m_arr[c++] = 0;}//if tc>=3 }//end if firstprevi=i;prevj=j; //306;269if (((i- origin.X)>=(306 - 4))&&((i- origin.Y)>=(269-4))){if (((i- origin.X)<=(306+4))&&((i- origin.Y)<=(269+4))){//JOptionPane.showMessageDialog (null,Double.toString(c)+";"+Integer.toString(i)+";"+Integer.toString(j),"My Point",JOptionPane.PLAIN_MESSAGE);}} }//end if that checks for p[x,y]=1}//end for}//end for//put total size of points collected at 0 in arraym_arr[0]=c;return m_arr;}//end getFingerPrintTemplate()public String ConvertFingerPrintTemplateDoubleToString(double[] finger){String temp="";for (int i=0;i<=finger.Length-1 ; i++){temp = temp + finger[i].ToString() +";";}return temp;} public double [] ConvertFingerPrintTemplateStringToDouble(String finger){double[] m_finger = new double[FP_TEMPLATE_MAX_SIZE]; int c=-1;String m_double = "";String temp ="";for (int i=0;i<=finger.Length-1 ; i++){char[] tempch = finger.ToCharArray();temp = temp[i].ToString();if (temp==";"){m_finger[c++] =Double.Parse(m_double);}else{m_double = m_double + temp; }}return m_finger;} /// <summery>/// ################################/// # Matching #/// ################################/// /// Something to possably look at are/// /// Distance = (X1 -X2)^2 + (Y1 - Y2)^2. The Error_Rating , if a image is is to the left or/// right or even at a angle the distance betwwen matched points will always be the same./// /// The matching dose account for rotation , thats what the cos and sin are for. /// /// In matching you will never get a 100% match uunless they are exactly the same /// image. 60% is quite good in general ,anything above 55% is considered a match , even /// in other commercial versions. Remember you comparing twod DIFFERENT images then drawing a conclusion of a match./// /// </summery> //cross-corelation algorithmpublic int Match(double[] finger1,double[] finger2 , int threshold , bool fastmatch){//compare matrix with all shifted matrixes//must do later. must get the size of the array// JOptionPane.showMessageDialog (null,Double.toString(finger1[0])+";"+Double.toString(finger1[1])+";"+Double.toString(finger2[3]),"Match",JOptionPane.PLAIN_MESSAGE);double matchcount = 0;double matchcounttotal = (finger1[0]-6)/6;double bestmatch =0;double radian = Math.PI/180;bool foundpoint; for (int k = -1*FP_MATCH_POINT_ROTATION_MOVEMENT; k <= FP_MATCH_POINT_ROTATION_MOVEMENT; k++){for (int i =7; i <= finger1[0]-5; i=i+6){foundpoint = false; for (int j =7; j <= finger2[0]-5; j=j+6){if(foundpoint==false){//compare two points account for rotational , verticle and horizontal shiftint resx=0;int resy=0;double x1=0 ;double y1=0;double x2=0;double y2=0;double r=0;double d=0;//find nessasary parameters r =finger2[j+2];d = finger2[j+3];x2=finger1[i];y2=finger1[i+1];//do angle shift for xx1 = r*Math.Cos(d+(k*radian));resx = Math.Abs((int)x2 + (int)(-1*x1));//do angle shift for y y1 = r*Math.Sin(d+(k*radian));resy = Math.Abs((int)y2 + (int)(-1*y1)); //cheak shift matchs count as matchif((FP_MATCH_POINT_DISTANCE_MOVEMENT > resx) && (FP_MATCH_POINT_DISTANCE_MOVEMENT > resy)){ //cheak if same kind of featureif(finger1[i+4] == finger2[j+4]){//cheak if feature in same direction// if(((finger1[i+5]-finger2[j+5])<=46)||((finger1[i+5]==0)&&(finger2[j+5]==315))||((finger1[i+5]==0)&&(finger2[j+5]==45)))// {matchcount++;foundpoint = true;//break;// }//cheak if feature in same direction} //cheak if same kind of feature }//end if}//if found}//end for j}//end for i//see if we have a match if ((((matchcount/matchcounttotal)*100)>=threshold)&& (fastmatch == true)){//found matchreturn (int)((matchcount/matchcounttotal)*100);}else{//not found match if(matchcount>bestmatch){bestmatch = matchcount;}//reset match counter to 0matchcount=0; } //end if }//end for kreturn (int)((bestmatch/matchcounttotal)*100);}//end Match }//end class}//end namespace
源代码下载地址1:http://download.csdn.net/detail/lovegonghui/8996059
源代码下载地址2:http://down.51cto.com/data/2081611
1 0
- 一款开源的指纹识别SDK
- 三星GALAXY指纹识别Pass SDK(一)
- iOS 8 SDK Touch ID指纹识别功能
- 一款开源的配置管理软件
- 一款开源的项目变更管理软件
- 一款功能强大的开源视频转换器
- 分享一款好的开源CMS
- 分享一款开源的http工具
- atom,一款开源的代码编辑器
- 一款开源的密码管理器
- 一款开源的中国象棋人工智能程序
- 【下载】推荐一款免费的人脸识别SDK
- 指纹识别的基本原理
- 指纹识别的欺骗方法
- 指纹识别技术设计的注意事项
- 指纹识别的基本原理
- iOS 简单的指纹识别
- 指纹识别
- 【leetcode】Valid Anagram 【java】
- Eclipse导入外部项目问题总结
- 多校第七场 1010 hdu 5378 Leader in Tree Land(概率dp)
- UITableView
- Android View事件分发和处理
- 一款开源的指纹识别SDK
- Web.Config和Sql Server2005连接字符串总结
- JAVA查询Oracle数据库导出成txt文本
- ubuntu11.04 编译ffmpeg2.7 并生成 ffplay进行流媒体测试
- ABBYY FineReader 12中条码检测不到怎么办
- 如何查看mysql运行、访问记录等日志
- SpingMVC中的三种HandlerMapping(映射器)
- html之 《meta》设置缓存
- sybase 优化总结