Wednesday, March 19, 2014

Implementing fingerprint readers in .net - Part two

This post will show us the way we can implement a fingerprint reader in .net applications.


This example is a C# app and was coded in Visual Studio 2010 using a MySQL database and Griaulle fingerprint SDK 2009. You can visit http://csharp-talks.blogspot.com/2009/10/implementing-fingerprint-readers-in-net.html. Connections between C# and MySQL were done with MySQL connector/net.



After installing Griaulle Fingerprint SDK 2009 we must create our database (all fingerprint's data will be stored at our database). Our database [finger] and a table [data], this table contains 5 columns:
Id (int)
texto_asociado (text): This column will store a reference text to identify each row
template (mediumblob): This column will store all our fingerprint data from our fingerprint reader.
Imagen (mediumblob): Will not be used in this example
Calidad_template (int): This column will store a value indicating quality level for our data stored in column “template”.






Once we have created our project in VS, first step is to add a reference to Griaulle SDK. Right click over References we click over Add Reference and we select Browse and select our Griaulle SDK installation directory (C:\Program Files\Griaule\Fingerprint SDK 2009\bin\GriauleFingerprintLibrary.dll). Same steps to add connector/net (C:\Program Files\MySQL\MySQL Connector Net 6.0.4\Assemblies\MySql.Data.dll)







In this example, our form has two options:
Registrar: Inserts the fingerprint's data in database (also inserts a reference text).

Identificar: Identify our fingerprint, comparing our recently extracted fingerprint against each fingerprint stored at our database.




When using fingerprint SDK we must declare a FingerprintCore Object:
GriauleFingerprintLibrary.FingerprintCore core = New GriauleFingerprintLibrary.FingerprintCore();

Then, we declare onStatus and onImage events. onStatus is triggered each time a fingerprint reader is connected and disconnected; onImage is triggered each time a fingerprint is acquired from fingerprint reader.

core.onStatus += new GriauleFingerprintLibrary.StatusEventHandler(core_onStatus);
core.onImage += new GriauleFingerprintLibrary.ImageEventHandler(core_onImage);

We must initialize library using Initialize() and then start capturing fingerprints:

core.Initialize();
core.CaptureInitialize();

Events are declared in Form's Load event (same as initialize library and capture).

At this point, we have started capturing fingerprints with our fingerprint reader and we have defined the function that will be executed each time the reader acquires a new fingerprint (onImage event) and, also, we have defined the function that will be executed each time a reader is connected/disconnected (onStatus event).

In onStatus function we must indicate to start capturing fingerprints using connected reader:

void core_onStatus(object source, GriauleFingerprintLibrary.Events.StatusEventArgs se)
{
  if (se.StatusEventType == GriauleFingerprintLibrary.Events.StatusEventType.SENSOR_PLUG)
  {
   core.StartCapture(source);
  }

}

OnImage verifies quality of fingerprint acquired by fingerprint reader, if it has a bad quality it must to be acquired once again, if it has a medium quality then a question is asked to user, and if it has goo quality then process can continue.

        void core_onImage(object source, GriauleFingerprintLibrary.Events.ImageEventArgs ie)
        {
            buttonOK.Enabled = groupBox1.Enabled = false;
            try
            {
                imagenHuella = ie.RawImage;
                core.Extract(imagenHuella, ref templateHuella); // we extract fingerprint's information and store that information in templateHuella
               
                switch(templateHuella.Quality)
                {
                    case 0:     // in case fingerprint has a bad quality
                        labelCalidad.Text = "bad quality, try again";
                        return;
                   
                    case 1:     // in case fingerprint has a medium quality
                        labelCalidad.Text = "Medium Quality";
                        if (MessageBox.Show("Fingerprint has a medium quality, proceed anyway?", "", MessageBoxButtons.YesNo) == DialogResult.Yes)
                            break;
                        return;                    

                    case 2:     // good quality
                        labelCalidad.Text = "fingeprint has good quality";
                        break;
                }
                buttonOK.Enabled = groupBox1.Enabled = true;
            }
            catch (System.Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }

condition if() is to verify if a reader was plugged (onStatus is triggered every time a reader is plugged and unplugged).

core.StartCapture(source); starts the capture with the recently plugged reader trough object source.

At this time, if we place a fingerprint over our reader a onImage event will be triggered, if we want to handle our fingerprint we must to extract a template from our reader and store it temporally in memory to insert it in our database, those actions are done in our Extract(...) function.

GriauleFingerprintLibrary.DataTypes.FingerprintRawImage imagenHuella;
imagenHuella = ie.RawImage;
core.Extract(imagenHuella, ref templateHuella);

In Extract(...) function, imagenHuella parameter is the original fingerprint image and templateHuella is the object where  we will store the data gotten from imagenHuella.

Once we have our template we are ready to insert a new record to database; it is important to use parameters.
_________________________________________________
We can use something like this:

bd.InsertarRegistroParametrizado("INSERT INTO data (texto_asociado,template,calidad_template,imagen) VALUES('" + txtBxRegistrar.Text + "',@template," + templateHuella.Quality.ToString() + ",'')",
"@template", (object)templateHuella.Buffer);
_________________________________________________


To continue we need at least one record in database.

To start identification process we need to retrieve each record in database to compare them "one to one". We require  a temp object to store our retrieved templates from database.

string consulta;
byte[] dataTemp; //to store temporally a template
GriauleFingerprintLibrary.DataTypes.FingerprintTemplate templateTemp;
int precision,calidad;

consulta = "select texto_asociado, template, calidad_template from data where 1=1";
MySql.Data.MySqlClient.MySqlDataReader rdr = bd.EjecutarConsulta(consulta); //we must to prepare library to identify fingerprints
core.IdentifyPrepare(templateHuella);

while (rdr.Read())
{
dataTemp = (byte[])rdr["template"]; //Extract template from database
calidad = (int)rdr["calidad_template"];

/* Create a new FingerprintTemplate object and assign all template's properties recently retrieved from DB*/
templateTemp = new GriauleFingerprintLibrary.DataTypes.FingerprintTemplate();
templateTemp.Buffer = dataTemp;
templateTemp.Size = dataTemp.Length;
templateTemp.Quality = calidad;
if ((core.Identify(templateTemp, out precision))==1) //Only if template has all our precition expectations
{
MessageBox.Show(rdr["texto_asociado"].ToString());
break;
}
}

Above code, statement while(rdr.Read()){…} gets each record in DB and compares it again user's fingerprint.

Any doubt or suggestion is appreciated.

You may be interested in: How to detect faces in .net applications (spanish)