How to code
The application has two important forms, FormAuth and FormUserMgt. We will see separately how they work and how they interact with it other. Then we will take a more detailed look at the biometric parts.
FormAuth
Note that this forum will hold griaule's component. However we use 2 forms, only one component is necessary to handle the fingerprints, we just have to do some tricks on the code to allow that. Also, note that there is a dataset, a tableAdapter and a tableAdapterManager in the form. Those components are related to the dataset created on the previous section and can be find at the toolbox. They will be responsible for "talking" with the database.
Once the form is loaded, we instantiate FingerprintOPFormAuth, which is the "util" class for this form and then we call its function that will be responsible for starting griaule's component. Also, we fill our dataset and we fill the combo box with the user's names stored in the database.
Private Sub FormAuth_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
fingerprintOP = New FingerprintOPFormAuth()
fingerprintOP.InitializeGrFinger(GrFingerXCtrl)
tabelaTableAdapter.Fill(ds.tabela)
'fill our dataset
loadComboNames()
End Sub
Private Sub loadComboNames()
'loop the database to bring all the user's name
For Each row As DBGriauleDataSet.tabelaRow In ds.tabela.Rows
comboNames.Items.Add(row.Name)
Next
End Sub
When the onSensorPlug event happpens, we tell the application to start the capture.
Private Sub grFingerXCtrlAuth_SensorPlug(ByVal sender As Object, ByVal e As AxGrFingerXLib._IGrFingerXCtrlEvents_SensorPlugEvent) Handles GrFingerXCtrl.SensorPlug
GrFingerXCtrl.CapStartCapture(e.idSensor)
'start the capture on this sensor
End Sub
When the user puts the finger on the reader the onImageAcquired event is fired. When it happens, we want to get the image, put it on our picture box, extract the template and check if it matches the fingerprint of the user whose name is equal to the name selected on the combo box.
Another important thing in this match, is the "trick" that is made to use one component for two forms. Here we play with the flag "whichForm" , we check whether the received imaged belong to FormAuth or to FormUserMgt.
Private Sub grFingerXCtrlAuth_ImageAcquired(ByVal sender As Object, ByVal e As AxGrFingerXLib._IGrFingerXCtrlEvents_ImageAcquiredEvent) Handles GrFingerXCtrl.ImageAcquired
Dim handle As System.Drawing.Image = Nothing
Dim hdc As IntPtr = GetDC(System.IntPtr.Zero)
GrFingerXCtrl.CapRawImageToHandle(e.rawImage, e.width, e.height, hdc.ToInt32(), handle)
If whichForm.Equals("FormAuth") Then
'do the action related to the FormAuth
pbFingerprint.Image = handle
'put the just added image in our picture box
pbFingerprint.Update()
'set the parameters in the FingerprintOPFormUSerMgt class
fingerprintOP.rawImage.img = e.rawImage
fingerprintOP.rawImage.height = CInt(e.height)
fingerprintOP.rawImage.width = CInt(e.width)
fingerprintOP.rawImage.Res = e.res
'finally , we extract the template and try to validate de user
fingerprintOP.extractTemplate()
Dim matched As Boolean = fingerprintOP.authenticate(comboNames.SelectedItem.ToString(), ds)
'if the user is validated , a new form containing some details about this user is opened
If matched Then
Dim frm As New FormUser()
frm.Show()
End If
Else
FormUserMgt.onImageAcquired(handle, e.rawImage, CInt(e.height), CInt(e.width), e.res)
End If
'do the action related to the FormUserMgt
End Sub
The flag whichForm starts with the value "FormAuth. There are two other moments when its value is modified.
One is when the FormUserMgt is opened, when obviously the flag assumes the value "FormUserMgt"
Private Sub btnUserMgt_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnUserMgt.Click
whichForm = "FormUserMgt"
FormUserMgt = New FormUserMgt(GrFingerXCtrl, ds)
AddHandler FormUserMgt.FormClosed, AddressOf formUserMgt_FormClosed
FormUserMgt.Show()
End Sub
The other moment is when the FormUserMgt is closed, when obviously the flag assumes the value "FormAuth"
One is when the FormUserMgt is opened, where obviously the flag assumes the value FormUserMgt
Private Sub formUserMgt_FormClosed(ByVal sender As Object, ByVal e As FormClosedEventArgs)
whichForm = "FormAuth"
comboNames.Items.Clear()
loadComboNames()
End Sub
FormUserMgt
This form is responsible for inserting/searching/removing users.
Its constructor receives the griaule's component , and FormAuth's dataset. By that, it is able to perform fingerprint and database operations
Public Sub New(ByVal grfingerxFormAuth As AxGrFingerXLib.AxGrFingerXCtrl, ByVal dataSet As DBGriauleDataSet)
InitializeComponent()
fingerprintOP = New FingerprintOPFormUserMgt(grfingerxFormAuth, dataSet, Me)
End Sub
It has a function called onImageAcquired, note that this is not the griaule's component function, it is just an imitation that is called from the true function in the FormAuth. This form has an util class as well, it is called FingerprintOPFormUserMgt. When the fake onImageAcquired is fired , this util class parameters are set and the image is handled.
Understand the biometric codes
This application introduces us to some important biometric engineering concepts. One of them is storing 3 or more templates of the same finger. It strongly helps in reducing false rejections due to bad quality reading. The other is the idea of bringing the templates to the memory instead of directly managing the database. In the java tutorials we had to make a class for this specif purpose, but fortunately, visual studio components do that to us automatically.
The Extraction
For comparison, we can't use an image object. It's necessary to extract a representation of this image, it is called template. Griaule's component offers the method extract for that, see how the function extractTemplate,defined in our application uses the method extract from grfinger. It passes the parameters as reference, receiving the template in the variable template.tpt.
Public Sub extractTemplate()
template.size = CInt(GRConstants.GR_MAX_SIZE_TEMPLATE)
grfingerx.Extract(rawImage.img, rawImage.width, rawImage.height, rawImage.Res, template.tpt, template.size, _
CInt(GRConstants.GR_DEFAULT_CONTEXT))
End Sub
The verification
In fingerprint recognition, we call verification when an specif fingerprint in a database is matched against a read fingerprint. That's what happens when the user puts its finger on the reader in the FormAuth. The application tries to match this user, with the user selected in the combo box. See the code comments for details.
Public Function authenticate(ByVal name As String, ByVal ds As DBGriauleDataSet) As Boolean
'instantiating the new templates
Dim t1 As New TTemplate()
Dim t2 As New TTemplate()
Dim t3 As New TTemplate()
Dim score As Integer = 0
Dim result As Integer
'we loop the database to find the name we want
For Each row As DBGriauleDataSet.tabelaRow In ds.tabela.Rows
If row.Name.Equals(name) Then
'when the name is found, we retrieve the template
Dim temp As Byte() = row.Template1
System.Array.Copy(temp, 0, t1.tpt, 0, temp.Length)
t1.size = temp.Length
temp = row.Template2
System.Array.Copy(temp, 0, t2.tpt, 0, temp.Length)
t2.size = temp.Length
temp = row.Template3
System.Array.Copy(temp, 0, t3.tpt, 0, temp.Length)
t3.size = temp.Length
Exit For
End If
Next
'now we try to match with at least one of the user's fingerprint
result = CInt(grfingerx.Verify(t1.tpt, template.tpt, score, CInt(GRConstants.GR_DEFAULT_CONTEXT)))
If DirectCast(result, GRConstants) = GRConstants.GR_MATCH Then
Return True
End If
result = CInt(grfingerx.Verify(t2.tpt, template.tpt, score, CInt(GRConstants.GR_DEFAULT_CONTEXT)))
If DirectCast(result, GRConstants) = GRConstants.GR_MATCH Then
Return True
End If
result = CInt(grfingerx.Verify(t3.tpt, template.tpt, score, CInt(GRConstants.GR_DEFAULT_CONTEXT)))
If DirectCast(result, GRConstants) = GRConstants.GR_MATCH Then
Return True
End If
Return False
End Function
The Identification
In fingerprint recognition, we call identification when an specif fingerprint is, in the worst of cases, searched in a whole database. That's what happens when the user puts its finger on the reader in the FormUserMgt after clicking search. The application tries to match this user with some user registered in the database. See the code comments for details.
Private Sub search()
[function] = -1
Dim temp As Byte()
Dim score As Integer = 0
templateSearch = extractTemplate(templateSearch)
'the variable templateSearch receives the image
Dim result As GRConstants = DirectCast(grfingerx.IdentifyPrepare(templateSearch.tpt, CInt(GRConstants.GR_DEFAULT_CONTEXT)), GRConstants)
If result < 0 Then
Return
End If
currentRow = Nothing
'linear search in the database, trying to match at least one fingerprint
For Each rowAux As DBGriauleDataSet.tabelaRow In ds.tabela.Rows
'first fingerprint test
temp = rowAux.Template1
System.Array.Copy(temp, 0, template1.tpt, 0, temp.Length)
template1.size = temp.Length
result = DirectCast(grfingerx.Identify(template1.tpt, score, CInt(GRConstants.GR_DEFAULT_CONTEXT)), GRConstants)
If result = GRConstants.GR_MATCH Then
currentRow = rowAux
Exit For
End If
'second fingerprint test
temp = rowAux.Template2
System.Array.Copy(temp, 0, template2.tpt, 0, temp.Length)
template2.size = temp.Length
result = DirectCast(grfingerx.Identify(template2.tpt, score, CInt(GRConstants.GR_DEFAULT_CONTEXT)), GRConstants)
If result = GRConstants.GR_MATCH Then
currentRow = rowAux
Exit For
End If
'third fingerprint test
temp = rowAux.Template3
System.Array.Copy(temp, 0, template3.tpt, 0, temp.Length)
template3.size = temp.Length
result = DirectCast(grfingerx.Identify(template3.tpt, score, CInt(GRConstants.GR_DEFAULT_CONTEXT)), GRConstants)
If result = GRConstants.GR_MATCH Then
currentRow = rowAux
Exit For
End If
Next
frm.handleSearch()
'the form handles the result, considering if the fingerprint was found or not
End Sub