Griaule Biometrics

Home » The code itself

Tutorial

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 void FormAuth_Load(object sender, EventArgs e)
{
  fingerprintOP = new FingerprintOPFormAuth();
  fingerprintOP.InitializeGrFinger(grFingerXCtrl);
 
  tabelaTableAdapter.Fill(ds.tabela);
  loadComboNames();
}
 
private void loadComboNames()
{
  foreach (DBGriauleDataSet.tabelaRow row in ds.tabela.Rows)
    {
      comboNames.Items.Add(row.Name);
    }
}

When the onSensorPlug event happpens, we tell the application to start the capture.

private void grFingerXCtrlAuth_SensorPlug(object sender, AxGrFingerXLib._IGrFingerXCtrlEvents_SensorPlugEvent e)
{
  grFingerXCtrl.CapStartCapture(e.idSensor);
}

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 void grFingerXCtrlAuth_ImageAcquired(object sender, AxGrFingerXLib._IGrFingerXCtrlEvents_ImageAcquiredEvent e)
{
  System.Drawing.Image handle = null;
  IntPtr hdc = GetDC(System.IntPtr.Zero);
  grFingerXCtrl.CapRawImageToHandle(ref e.rawImage, e.width, e.height,
				    hdc.ToInt32(), ref handle);
 
  if (whichForm.Equals("FormAuth")) //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 = (int)e.height;
      fingerprintOP.rawImage.width = (int)e.width;
      fingerprintOP.rawImage.Res = e.res;
 
      //finally , we extract the template and try to validate de user
      fingerprintOP.extractTemplate();
      bool matched = fingerprintOP.authenticate(comboNames.SelectedItem.ToString(), ds);
 
      //if the user is validated , a new form containing some details about this user is opened
      if (matched)
	{
	  FormUser frm = new FormUser();
	  frm.Show();
	}
    }
  else
    formUserMgt.onImageAcquired(handle, e.rawImage, (int)e.height, (int)e.width, e.res);//do the action related to the FormUserMgt
}

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 void btnUserMgt_Click(object sender, EventArgs e)
{
  whichForm = "FormUserMgt";
  formUserMgt = new FormUserMgt(grFingerXCtrl, ds);
  formUserMgt.FormClosed += new FormClosedEventHandler(formUserMgt_FormClosed);
  formUserMgt.Show();
}

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 void formUserMgt_FormClosed(object sender, FormClosedEventArgs e)
{
  whichForm = "FormAuth";
  comboNames.Items.Clear();
  loadComboNames();
}

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 FormUserMgt(AxGrFingerXLib.AxGrFingerXCtrl grfingerxFormAuth,DBGriauleDataSet dataSet)
{
  InitializeComponent();
  fingerprintOP = new FingerprintOPFormUserMgt(grfingerxFormAuth,dataSet,this);
}

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 void extractTemplate()
{
  template.size = (int)GRConstants.GR_MAX_SIZE_TEMPLATE;
  grfingerx.Extract(ref rawImage.img, rawImage.width, rawImage.height,
		    rawImage.Res,ref template.tpt, ref template.size,
		    (int)GRConstants.GR_DEFAULT_CONTEXT);
}
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 bool authenticate(string name,DBGriauleDataSet ds)
{
  //instantiating the new templates
  TTemplate t1 = new TTemplate();
  TTemplate t2 = new TTemplate();
  TTemplate t3 = new TTemplate();
 
  int score = 0;
  int result;
 
  //we loop the database to find the name we want
  foreach (DBGriauleDataSet.tabelaRow row in ds.tabela.Rows)
  {
    if (row.Name.Equals(name))
      {
	//when the name is found, we retrieve the template
	System.Byte[] temp = 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;
 
	break;
      }
  }
 
  //now we try to match with at least one of the user's fingerprint
  result = (int)grfingerx.Verify(ref t1.tpt, ref template.tpt,
				 ref score,(int)GRConstants.GR_DEFAULT_CONTEXT);
 
  if ((GRConstants)result == GRConstants.GR_MATCH)
    return true;
 
  result = (int)grfingerx.Verify(ref t2.tpt, ref template.tpt,
				 ref score, (int)GRConstants.GR_DEFAULT_CONTEXT);
 
  if ((GRConstants)result == GRConstants.GR_MATCH)
    return true;
 
  result = (int)grfingerx.Verify(ref t3.tpt, ref template.tpt,
				 ref score, (int)GRConstants.GR_DEFAULT_CONTEXT);
 
  if ((GRConstants)result == GRConstants.GR_MATCH)
    return true;
 
  return false;
}
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 void search()
{
  function = -1;
  System.Byte[] temp;
  int score = 0;
  templateSearch = extractTemplate(templateSearch); //the variable templateSearch receives the image
 
  GRConstants result = (GRConstants) grfingerx.IdentifyPrepare(ref templateSearch.tpt,
							       (int)GRConstants.GR_DEFAULT_CONTEXT);
  if (result < 0)
    return;
 
  currentRow = null;
 
  //linear search in the database, trying to match at least one fingerprint
  foreach (DBGriauleDataSet.tabelaRow rowAux 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 = (GRConstants)grfingerx.Identify(ref template1.tpt, ref score, (int)GRConstants.GR_DEFAULT_CONTEXT);
    if (result == GRConstants.GR_MATCH)
      {
	currentRow = rowAux;
	break;
      }
 
    //second fingerprint test
    temp = rowAux.Template2;
    System.Array.Copy(temp, 0, template2.tpt, 0, temp.Length);
    template2.size = temp.Length;
 
    result = (GRConstants)grfingerx.Identify(ref template2.tpt, ref score, (int)GRConstants.GR_DEFAULT_CONTEXT);
    if (result == GRConstants.GR_MATCH)
      {
	currentRow = rowAux;
	break;
      }
 
    //third fingerprint test
    temp = rowAux.Template3;
    System.Array.Copy(temp, 0, template3.tpt, 0, temp.Length);
    template3.size = temp.Length;
 
    result = (GRConstants)grfingerx.Identify(ref template3.tpt, ref score, (int)GRConstants.GR_DEFAULT_CONTEXT);
    if (result == GRConstants.GR_MATCH)
      {
	currentRow = rowAux;
	break;
      }
  }
 
  frm.handleSearch();//the form handles the result, considering if the fingerprint was found or not
}