Griaule Biometrics

Home » Creating an Access Control System using VB.2008 and Fingerprint SDK - Fingerprint support

On Fingerprint SDK documentation you can find all the functions available to deal with fingerprint handling and how to use them. This tutorial is partially based on the samples that come with it, with several adjustments. To reduce your reading, this tutorial just explains these adjustments and what they do, so you must check your Fingerprint SDK documentation to understand them. This sample was designed to use GrFinger library in two forms: one to enroll fingerprints and another to access the system.

The grUtilities class

We're grouping all the functions required to handle all GrFinger methods and events into a single class, called grUtilities (note: the code was adapted from Util.vb file, part of your Fingerprint SDK sample files). For our application, the main functions are: PrintBiometricDisplay, used to display images generated by GrFinger; ExtractTemplate, used to extract the template from acquired image; Enroll, used to store fingerprint on database; and Identify, used to compare a fingerprint against database contents.

The other functions (briefly described) are used to manipulate the GrFinger methods and events accordingly. The methods are:

  • InitializeGrFinger: prepare GrFinger library to be used
  • FinalizeGrFinger: ends GrFinger library

And the event handlers are:

  • SensorPlug: triggered when a reader is plugged
  • SensorUnplug: triggered when a reader is unplugged
  • FingerDown: triggered when a finger is placed over reader
  • FingerUp: triggered when a finger is removed from reader
  • ImageAcquired: triggered when an image was acquired

We also created two events that must be handled by the form instantiating this class:

  • ImageIsAvailable: triggered when an image was captured and can be processed by the form
  • WriteLog: triggered by each message generated by class

PrintBiometricDisplay

This function receives a PictureBox by reference from the form, calls CapRawImageToHandle or BiometricDisplay depending on call request, and shows the image on referred picture box.

ExtractTemplate

This function just calls the Extract function, generating a fingerprint template that can be used for comparison.

Enroll

This function receives a reference to the Fingerprints dataset, creates a new Fingerprints row containing the image and corresponding template and adds it to dataset.

Identify

This function prepares the acquired template for comparison using IdentifyPrepare and compares it with each template available on Fingerprints dataset (passed by reference) using Identify call, returning the matching FID or GR_NO_MATCH if no fingerprint was found.

The fingerprints registration form

This form is designed to enroll the fingerprints to a user. It prompts the user name that will be enrolled to the acquired fingerprints, the finger to be enrolled and, for redundancy purposes, waits until the same finger is placed three times, registering the three fingerprints to the user.

Design

First of all, add a new form to your project:

  1. Click ProjectAdd Windows form…
  2. Rename it to formFingerprints;
  3. Create your form as follows (pick each control from toolbox - the properties will be explained later):

 

Toolbox

 

  Control name Control type Properties
(1) ds DataSet DataSetName=AccessControlDataSet
(1) bs_u BindingSource DataSource=ds
DataMember=Users
(1) ta_u UsersTableAdapter  
(1) ta_f FingerprintsTableAdapter  
(2) cmbUsers ComboBox DropDownStyle=DropDownList
DataSource=bs_u
DisplayMember=Name
ValueMember=UID
(3) cmbFingers ComboBox DropDownStyle=DropDownList
(4) picTemplate1 PictureBox  
(4) picTemplate2 PictureBox  
(4) picTemplate3 PictureBox  
(5) lstLogFingerprint ListBox  
(6) cmdRegister Button  
(6) cmdCancel Button  

 

  1. Using designer, add the finger names to your cmbFingers combo box using Items property in order (suggested names: "Baby left", "Ring left", "Middle left", "Index left", "Thumb left", "Thumb right", "Index right", "Middle right", "Ring right" and "Baby right").

Coding

Let's define the form behavior and actions:

  1. The form must read the database into our datasets;
  2. The form must clean-up the images on picture boxes;
  3. The form must initialize GrFinger;
  4. The cmbUsers must show user names;
  5. The cmbFingers must show finger names;
  6. The form must handle the WriteLog and ImageIsAvailable events from grUtilities class;
  7. When acquired, the fingerprint must be displayed in one of the picTemplate's and enrolled to the current user;
  8. When cmdRegister is clicked, the changes on Fingerprints dataset are updated and the form is closed;
  9. When cmdCancel is clicked, the changes on Fingerprints dataset are rejected and the form is closed;
  10. Before closing, the form must release the grUtilities event handlers and finalize GrFinger;
Load

When the form is loaded, we must load the database into our datasets (i). To do so, we use the Fill function on each table adapter:

ta_us.Fill(ds.UserSystem)        ‘ Populate UserSystem DataSet

ta_s.Fill(ds.Systems)            ‘ Populate Systems DataSet

ta_u.Fill(ds.Users)              ‘ Populate Users DataSet

 

We also need to clean-up the picture boxes (ii):

picTemplate1.Image = Nothing     ‘ Clear template image #01

picTemplate2.Image = Nothing     ‘ Clear template image #02

picTemplate3.Image = Nothing     ‘ Clear template image #03

 

Finally, we need to initialize GrFinger (iii):

err = gr.InitializeGrFinger()                                     ‘ Initialize GrFingerX Library

If err < 0 Then                                                   ‘ Got error? ...

    gr.WriteError(err)                                            ‘ ... print result on log...

    MsgBox(“Cannot initialize GrFinger!”, MsgBoxStyle.Critical)

    Close()                                                       ‘ ... and close form

End If

 

Additional initialization steps :

cmdRegister.Enabled = False      ‘ Disable Register Button - enabled after third fingerprint acquired

cmbUsers.Enabled = True          ‘ Enable Users ComboBox control - disabled after first fingerprint acquired

cmbFingers.Enabled = True        ‘ Enable Fingers ComboBox control - disabled after first fingerprint acquired

cmbFingers.SelectedIndex = 6     ‘ Set default index to finger #6 (Index Right)

 

Behavior

We form behavior is set on form design by setting the desired properties on each form control. We're currently binding cmbUsers to bs_u (as described on formAccess) to show user names (iv) and adding a collection of finger names to cmbFinger items property (v).

Events

There are several events that must be handled by this form. There are two event handlers that are specific to grUtilities class: WriteLog and ImageIsAvailable (vi). Notice that, for these events to be handled, they must be explicitly added to this form:

AddHandler formMain.gr.WriteLog, AddressOf WriteLog                     ' WriteLog

AddHandler formMain.gr.ImageIsAvailable, AddressOf ImageIsAvailable     ' ImageIsAvailable

 

The local subroutines to handle these events are called WriteLog and ImageIsAvailable (specified by the AddressOf call). Notice that the grUtilities class is referred as formMain.gr. This is because the grUtilities class is declared only once on formMain (described ahead) and used here.

The WriteLog event is triggered on each message from grUtilities class. This form gets these messages and displays them on lstLogFingerprints (this code was copied from original Util.vb):

    Protected Sub WriteLog(ByVal message As String)

        lstLogFingerprints.Items.Add(message)

        lstLogFingerprints.SelectedIndex = lstLogFingerprints.Items.Count - 1

        lstLogFingerprints.ClearSelected()

    End Sub

 

The ImageIsAvailable event is triggered when a fingerprint image was acquired and is available for processing. Once acquired, we must process it accordingly:

  • Display the fingerprint image (vii) on picture box
  • Extract image template
  • Enroll the template to current user (vii)
  • Show minutiae

We do that thru the following code:

    Protected Sub ImageIsAvailable()

 

        Dim r As Integer

        Dim u As AccessControlDataSet.UsersRow

 

        u = CType(bs_u.Current, DataRowView).Row    ' Current UsersRow

        With formMain.gr                            ' work with grUtilities instance (@ formMain)

            Select Case _cap                        ' show captured image on related local picture box

                Case 0 : .PrintBiometricDisplay(picTemplate1, False, GR_DEFAULT_CONTEXT)

                    cmbUsers.Enabled = False        ' first read - disable Users ComboBox control

                    cmbFingers.Enabled = False      ' first read - disable Fingers ComboBox control

                Case 1 : .PrintBiometricDisplay(picTemplate2, False, GR_DEFAULT_CONTEXT)

                Case 2 : .PrintBiometricDisplay(picTemplate3, False, GR_DEFAULT_CONTEXT)

            End Select

 

            r = .ExtractTemplate()                  ' extract template from current image

            Select Case r                           ' write quality info to log

                Case GR_BAD_QUALITY : WriteLog("Template extracted successfully. Bad quality.")

                Case GR_MEDIUM_QUALITY : WriteLog("Template extracted successfully. Medium quality.")

                Case GR_HIGH_QUALITY : WriteLog("Template extracted successfully. High quality.")

            End Select

 

            If r > 0 Then                           ' if no error occurred...

                ' ... register the acquired template on database...

                .Enroll(cmbFingers.SelectedIndex, u.UID, ds.Fingerprints)

            Else                                    ' ... otherwise...

                formMain.gr.WriteError(r)           ' ... process error...

                Exit Sub                            ' ... and exit sub

            End If

 

            Select Case _cap                        ' display matching minutiae/segments/directions

                Case 0 : .PrintBiometricDisplay(picTemplate1, True, GR_NO_CONTEXT)

                Case 1 : .PrintBiometricDisplay(picTemplate2, True, GR_NO_CONTEXT)

                Case 2 : .PrintBiometricDisplay(picTemplate3, True, GR_NO_CONTEXT)

                    cmdRegister.Enabled = True      ' third read - enable Register button

            End Select

            _cap += 1                               ' Increase captured image counter

        End With

    End Sub

 

The other events are generated by local form controls. When the cmdRegister button is clicked, the changes on dataset must be updated on database and the form must be closed (viii):

ta_f.Update(ds.Fingerprints)        ' Update Fingerprints table

Close()                             ' Close form

 

The last event occurs when cmdRegister button is clicked (ix): we reject the changes on Fingerprints dataset and close the form:

ds.Fingerprints.RejectChanges()     ' Reject changes on Fingerprints dataset

Close()                             ' Close form

 

Remember that the form must finalize GrFinger and remove grUtitilies event handlers before closing the form (x). This is handled during FormClosing event:

RemoveHandler formMain.gr.WriteLog, AddressOf WriteLog

RemoveHandler formMain.gr.ImageIsAvailable, AddressOf ImageIsAvailable

 

formMain.gr.FinalizeGrFinger()             ' finalize GrFinger

 

The login form

This form is used as initial interface to all the other ones. It must prompt the user for his fingerprint and give him access to the systems he's allowed to access, including here the other forms.

Design

First of all, add a new form to your project:

  1. Click ProjectAdd Windows form…
  2. Rename it to formMain;
  3. Create your form as follows (pick each control from toolbox - the properties will be explained later):

 

Toolbox

 

  Control name Control type Properties
(1) ds DataSet DataSetName=AccessControlDataSet
(1) ta_s SystemsTableAdapter  
(1) ta_us UserSystemTableAdapter  
(1) ta_u UsersTableAdapter  
(1) ta_f FingerprintsTableAdapter  
(2) picTemplate PictureBox  
(3) lbUserName Label  
(3) lbUserOffice Label  
(3) lbUserPosition Label  
(4) lbFingerName Label  
(4) lbFingerScore Label  
(5) lstLogIdentity ListBox  
(6) AxGrFingerXCtrl AxGrFingerXCtrl  
(7) mnIdentify MenuStrip  

 

  1. Using designer, add the following items to your File menu:
    1. Enroll
    2. Dismiss
    3. Reset form
    4. Exit

Coding

Let's define the form behavior and actions:

  1. Class grUtilities must be initialized;
  2. The form must read the database into our datasets;
  3. When FileEnroll menu is clicked, GrFinger is initialized and grUtilities event handlers are set;
  4. When FileDismiss menu is clicked, grUtilities event handlers are removed and GrFinger is finished;
  5. When FileReset form menu is clicked, the form is cleared;
  6. When FileExit menu is clicked, the application is closed;
  7. When acquired, the fingerprint is displayed in picTemplate and identified;
  8. Once identified, the user and fingerprint info must be set on form and the systems that the user is enrolled to must appear on Systems menu;
  9. When Systems<system name> menu is clicked, the corresponding system must be accessed;
  10. Each System menu item must handle the corresponding system;
Initialization

Since this form is using an external class (grUtilities), it must be initialized before everything else (i). First of all, let's declare a handling variable:

Friend WithEvents gr As grUtilities             ' GrUtilities class

It's declared as Friend to ensure that the other members of our application have access to it, and as WithEvents to allow event handling. We also need to declare a variable to maintain the finger names:

Private _fingers() As String                    ' Finger names

Notice that we didn't need this declaration on previous form, since the finger names were added thru designer into cmbFingers combo box.

Now these variables need to be initialized. This is done on New() function:

Public Sub New()

 

   InitializeComponent()                       ' This call is required by the Windows Form Designer.

 

   gr = New grUtilities(AxGrFingerXCtrl)       ' grUtilities initalization

   _fingers = New String() {"Baby left", "Ring left", "Middle left", "Index left", "Thumb left", _

                            "Thumb right", "Index right", "Middle right", "Ring right", "Baby right"}

End Sub

 

Notice that gr is initialized here and receives a reference to our GrFinger ActiveX control.

Load

When the form is loaded, we must load the database into our datasets (ii). To do so, we use the Fill function on each table adapter. But there is an aspect to be considered before continuing: what if a table is empty? We need at least one system to access, one user enrolled to a system and one fingerprint to be identified. This is a common problem when the application is used for the first time and the database is empty. Remember that we are considering that all the other forms are systems that this form must provide access to, so at least one system must be available. The usual way to solve this problem is initializing the database with default values on first access. Our design solution asks the installer for these values:

While ta_s.Fill(ds.Systems) = 0             ' Loading Systems DataSet. Is it empty?

    MsgBox("Please create an initial system, for administrative purposes.")

    formSystems.ShowDialog()                ' Open Systems form

End While                                   ' Repeat until not empty

 

While ta_u.Fill(ds.Users) = 0               ' Loading Users DataSet. Is it empty?

    MsgBox("Please create an initial user, for administrative purposes.")

    formUsers.ShowDialog()                  ' Open Users Form

End While                                   ' Repeat until not empty

 

While ta_us.Fill(ds.UserSystem) = 0         ' Loading UserSystem DataSet. Is it empty?

    MsgBox("Setting user " & Chr(34) & ds.Users.Item(0).Name & Chr(34) & _

           " as member of " & Chr(34) & ds.Systems.Item(0).System & Chr(34) & _

           " - it's now the system administrator.")

    ds.UserSystem.AddUserSystemRow(ds.Systems.Item(0), ds.Users.Item(0)) ' First User, first System

    ta_us.Update(ds.UserSystem)             ' Update UserSystem DataSet

End While                                   ' Repeat until not empty

 

While ta_f.Fill(ds.Fingerprints) = 0        ' Loading Fingerprints DataSet. Is it empty?

    MsgBox("Requesting initial fingerprint for " & _

           Chr(34) & ds.Users.Item(0).Name & Chr(34) & ".")

    formFingerprints.ShowDialog()           ' Open Fingerprints form

End While                                   ' Repeat until not empty

 

Notice that, if a dataset it empty, the related form is opened, allowing the user to create at least one entry on that. Also, we define here the figure of System Administrator. It is the user who has access to everything else (in this case all the other forms). Ahead we show how to handle this.

Menu events

Now that the form is loaded, let's deal with its events. First of all, when FileEnroll is clicked, GrFinger is initialized and grUtilities event handlers are set (iii):

Dim err As Integer

 

err = gr.InitializeGrFinger()                                   ' Initialize GrFinger

If err < 0 Then                                                 ' Got error? ...

    gr.WriteError(err)                                          ' ... log it,

Else                                                            ' ... otherwise...

    EnrollToolStripMenuItem.Enabled = False                     ' ... disable "Enroll" menu option,...

    DismissToolStripMenuItem.Enabled = True                     ' ... enable "Dismiss" menu option,...

    AddHandler gr.WriteLog, AddressOf WriteLog                  ' ... add WriteLog event handler and...

    AddHandler gr.ImageIsAvailable, AddressOf ImageIsAvailable ' ... add ImageIsAvailable event handler.

End If

 

On the other hand, FileDismiss menu is clicked, grUtilities event handlers are removed and GrFinger is finished (iv):

RemoveHandler gr.WriteLog, AddressOf WriteLog                   ' Remove WriteLog event handler

RemoveHandler gr.ImageIsAvailable, AddressOf ImageIsAvailable   ' Remove ImageIsAvailable event handler

EnrollToolStripMenuItem.Enabled = True                          ' Enable "Enroll" menu option

DismissToolStripMenuItem.Enabled = False                        ' Disable "Dismiss" menu option

gr.FinalizeGrFinger()                                           ' Finalize GrFinger

 

When FileReset form menu is clicked, the form is cleared (v):

If DismissToolStripMenuItem.Enabled Then                        ' Is "Dismiss" menu enabled?...

    DismissToolStripMenuItem.PerformClick()                     ' ... click it

End If

 

ResetFormInfo()                                                 ' Reset form info

 

Here we're "clicking" the Dismiss menu before resetting the form, to ensure that form is reset to its original values. Finally, when FileExit menu is clicked, the application is closed (vi):

If DismissToolStripMenuItem.Enabled Then                        ' Is "Dismiss" menu enabled?...

    DismissToolStripMenuItem.PerformClick()                     ' ... click it

End If                                                                   

 

Close()                                                         ' Close form

 

Regarding Systems menu, it's originally empty and must be build on-the-fly. The way it's done is described ahead.

GrFinger events

The local subroutines to handle these events are called WriteLog and ImageIsAvailable. The WriteLog event is triggered on each message from grUtilities class. This form gets these messages and displays them on lstLogIdentity:

With lstLogIdentity

    .Items.Add(message)

    .SelectedIndex = .Items.Count - 1

    .ClearSelected()

End With

 

The ImageIsAvailable event is triggered when a fingerprint image was acquired and is available for processing. Once acquired, we must process it accordingly (vii):

  • Display the fingerprint image on picture box;
  • Extract image template;
  • Identify it;
  • Show minutiae;
  • Set user and fingerprint info on form;

We do that thru the following code:

Dim id As Integer

Dim sc As Integer

 

gr.PrintBiometricDisplay(picTemplate, False, GR_DEFAULT_CONTEXT)    ' Display fingerprint

id = gr.ExtractTemplate()                   ' Extract template from current image

Select Case id                              ' Based on id, Write quality info to log

    Case GR_BAD_QUALITY : WriteLog("Template extracted successfully. Bad quality.")

    Case GR_MEDIUM_QUALITY : WriteLog("Template extracted successfully. Medium quality.")

    Case GR_HIGH_QUALITY : WriteLog("Template extracted successfully. High quality.")

End Select

 

If id > 0 Then                              ' No error on ExtractTemplate call?

    id = gr.Identify(sc, ds.Fingerprints)   ' ... identify acquired template

End If

 

Select Case id                              ' Process result

    Case Is > 0                             ' Match found!

        WriteLog("Fingerprint identified: ID = " & id & ", score = " & sc & ".")

        gr.PrintBiometricDisplay(picTemplate, True, GR_DEFAULT_CONTEXT) ' Display minutiae/segments/directions

        SetFormInfo(id, sc)                 ' Set form information

    Case GR_NOT_MATCH                       ' No match found

        MsgBox("No match found!", MsgBoxStyle.Information)

        WriteLog("Fingerprint not Found."' Log 'not found' message

    Case Else                               ' Got error

        gr.WriteError(id)                   ' Process error

End Select

 

DismissToolStripMenuItem.PerformClick()     ' Click “Dismiss”

 

Notice the call to subroutine SetFormInfo(). It's used to set the user information on form and to add the system menu items (viii):

Dim f As AccessControlDataSet.FingerprintsRow

Dim u As AccessControlDataSet.UsersRow

Dim us As AccessControlDataSet.UserSystemRow

 

f = ds.Fingerprints.Select("FID = " & fid)(0)           ' Get finger info (unique)

u = ds.Users.Select("UID = " & f.UID)(0)                ' Get user info (unique)

 

lbFingerName.Text = _fingers(f.Finger)                  ' Set Finger name on form

lbFingerScore.Text = score                              ' Set Finger score ID on form

lbUserName.Text = u.Name                                ' Set User name on form

lbUserOffice.Text = u.Office                            ' Set User office on form

lbUserPosition.Text = u.Position                        ' Set User position on form

For Each us In ds.UserSystem.Select("UID = " & f.UID)   ' Work on each UserSystem row

 

    Dim s As AccessControlDataSet.SystemsRow

 

    s = ds.Systems.Select("SID = " & us.SID)(0)         ' Get System enrollment info

 

    ' Add current system name to "Systems" menu tab with its event handler

    AddHandler SystemsToolStripMenuItem.DropDownItems.Add(s.System).Click, AddressOf OnSystemMenuItemClick

Next

 

SystemsToolStripMenuItem.Enabled = True

 

Notice line starting with AddHandler: in a single line we do two actions:

  • Add system name (s.System) as a drop-down menu option (ix);
  • Add function OnSystemMenuItemClick() as the handler of Click event (x);

Notice that, in this design, OnSystemMenuItemClick() subroutine handles all click events on Systems menu:

Private Sub OnSystemMenuItemClick(ByVal sender As System.Object, ByVal e As System.EventArgs)

 

    Dim m As ToolStripItem

 

    m = sender                                          ' Which menu was clicked

    Select Case m.Text                                  ' Work on clicked item

        Case ds.Systems.Item(0).System                  ' Case administrative system...

            formManagement.ShowDialog()                 ' ... call the administrative form

 

            ta_f.Fill(ds.Fingerprints)                  ' Reload Fingerprints DataSet

            ta_s.Fill(ds.Systems)                       ' Reload Systems DataSet

            ta_u.Fill(ds.Users)                         ' Reload Users DataSet

            ta_us.Fill(ds.UserSystem)                   ' Reload UserSystem DataSet

 

        ‘ End Case

 

                ' --------------------- '

                ' Add your handler here '

                ' as a 'Case' option.   '

                ' ----------------------'

 

        Case Else                                       ' ... otherwise...

            MsgBox("You clicked on " & m.Text & ".")    ' ... call Default handler

    End Select  

    ResetFormInfo()                                     ' Reset Form

 

End Sub

 

Here we get the name of the sender using sender value, which maintains the information of the object that generated the event (in this case the menu item clicked). The Text property maintains the name of the system and is used as the reference to the system that we want to call.

The only handler explicitly declared here is the administrative one, referred as the first system at Systems dataset (Item(0) property) that, if clicked, opens formManagement. Since the other forms potentially change the database contents, we need to reload our local datasets as formManagement finishes.

Also, we need to reset form info after the user leaves his system, allowing our access control system to enroll another user. To do so, we create a procedure called ResetFormInfo(), which does the opposite of SetFormInfo():

Dim mi As ToolStripMenuItem

 

picTemplate.Image = Nothing                                     ' Clear template image

lbUserName.Text = ""                                            ' Clear User Name info

lbUserOffice.Text = ""                                          ' Clear User Office info

lbUserPosition.Text = ""                                        ' Clear User Position info

lbFingerName.Text = ""                                          ' Clear Finger Name info

lbFingerScore.Text = ""                                         ' Clear matching score info

           

For Each mi In SystemsToolStripMenuItem.DropDownItems           ' For each option on menu "Systems"...

    RemoveHandler mi.Click, AddressOf OnSystemMenuItemClick     ' ... remove its event handler

Next

 

SystemsToolStripMenuItem.DropDownItems.Clear()                  ' Clear all options on menu "Systems"

 

EnrollToolStripMenuItem.Enabled = True                          ' Enable "Enroll" menu option

DismissToolStripMenuItem.Enabled = False                        ' Disable "Dismiss" menu option

SystemsToolStripMenuItem.Enabled = False                        ' Disable "Systems" menu

 

That's all!