Lector Dactilar desde Java (Parte I)

Entrada no corta …

Como siempre, en el trabajo me pidieron hacer algo que no tenía ni idea de cómo hacer lo que tenía que hacer.😯

En resumen, vamos a leer huellas dactilares (en el tuto usando el u.are.u 4000B de digitalPersona) desde Java. El modelo del lector, pues, porque ese me pasaron aquí …

Entonces, empezamos por instalar el SDK. Asumo que, si tienen un lector, tienen el SDK. Si no tienen un lector, pues, lean a modo de conocimiento general …

TODO el post se basa en lo leído en la gran serie de Jair Rios en su blog. De modo que, si algo no lo entienden y yo no puedo contestarlo, diríjanse a él🙂

Nos vamos con una app de escritorio. Si quisiéramos hacerlo web, necesitaríamos un applet (que básicamente es lo mismo😯 ).

Personalmente, utilizo IntelliJ como IDE, y le agregué el plugin de jFormBuilder para la interfaz gráfica. En su caso, pueden hacerlo como quieran/puedan.

La ventana es algo así Dibujo

Ok. Tenemos lo siguiente Dibujo

Importamos los .jar del SDK Dibujo

Y los imports

import com.digitalpersona.onetouch.*;
import com.digitalpersona.onetouch.capture.DPFPCapture;
import com.digitalpersona.onetouch.capture.event.*;
import com.digitalpersona.onetouch.processing.DPFPEnrollment;
import com.digitalpersona.onetouch.processing.DPFPFeatureExtraction;
import com.digitalpersona.onetouch.processing.DPFPImageQualityException;
import com.digitalpersona.onetouch.verification.DPFPVerification;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.GroupLayout;
import javax.swing.border.*;

Ahora si. Primero vamos a las variables globales (estamos en una clase que herede de un jPanel o jFrame).

//Nos sirve para identificar al dispositivo
private DPFPCapture Lector = DPFPGlobal.getCaptureFactory().createCapture();
//Nos sirve para leer a modo de enrrolar, y crear una plantilla nueva, a base de 4 huellas.
private DPFPEnrollment Reclutador = DPFPGlobal.getEnrollmentFactory().createEnrollment();
//Nos sirve para leer a modo de verificar o comparar, a base de una plantilla creada anteriormente
private DPFPVerification Verificador = DPFPGlobal.getVerificationFactory().createVerification();
//La plantilla, nueva o rescatada
private DPFPTemplate template;
//A modo de CONSTANTE para crear plantillas
public String TEMPLATE_PROPERTY = "template";
//Para leer la huella, y definirla como un enrrolamiento
public DPFPFeatureSet featureSetInscripcion;
//Para leer la huella, y definirla como una verificación
public DPFPFeatureSet featureSetVerificacion;

Siguiente, el constructor

<br />public Enrrolar() {
  try{
    for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
      if ("Nimbus".equals(info.getName())) {
        UIManager.setLookAndFeel(info.getClassName());
        break;
      }
    }
  }catch(Exception e){
    JOptionPane.showMessageDialog(null,
      "No es posible cambiar tema visual",
      "LookAndFeel inválido",
      JOptionPane.ERROR_MESSAGE);
  }
  initComponents();
  Iniciar();
  start();
  EstadoHuellas();
  btnGuardar.setEnabled(false);
  btnIdentificar.setEnabled(false);
  btnVerificar.setEnabled(false);
  btnSalir.grabFocus();
  txtMensaje.setEditable(false);
}
  1. Cambiar el estilo (es opcional, pero hace que sea vea cool 8) )
  2. Carga de los elementos. Esta función la genera el IDE.
  3. Iniciamos todos sus parámetros y eventos del lector.
  4. Iniciamos el lector.
  5. Abajo.
  6. Ordenamos que todos los botones, salvo el de salida, queden desactivados.

Entonces, ahora vamos con Iniciar. El lector tiene sus propios eventos, los cuales linkeamos desde esta función. Nosotros vamos a usar 4:

  • dataAcquired, desde Lector.addDataListener
  • readerConnected, desde Lector.addReaderStatusListener
  • readerDisconnected, desde Lector.addReaderStatusListener también
  • errorReader, desde Lector.addErrorListener

Dice:

protected void Iniciar(){
  Lector.addDataListener(new DPFPDataAdapter(){
    @Override public void dataAcquired(final DPFPDataEvent e){
      SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          EnviarTexto("La huella ha sido capturada");
          ProcesarCaptura(e.getSample());}
        });
      }
    });
  Lector.addReaderStatusListener(new DPFPReaderStatusAdapter(){
    @Override public void readerConnected(final DPFPReaderStatusEvent e){
      SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          EnviarTexto("El sensor de huella dactilar se encuentra Activado");
        }
      });
    }
    @Override public void readerDisconnected(final DPFPReaderStatusEvent e){
      SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          EnviarTexto("El sensor de huella dactilar se encuentra Desactivado");
        }
      });
    }
  });
  Lector.addErrorListener(new DPFPErrorAdapter(){
    public void errorReader(final DPFPErrorEvent e){
      SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          EnviarTexto("Error: " + e.getError());
        }
      });
    }
  });
}

En todos ocupamos EnviarTexto, pero en el primero al leer la huella, llamamos a otra función.
Vamos a comenzar con EnviarTexto. Únicamente tiene

public void EnviarTexto(String mensaje){
  txtMensaje.append(mensaje + "\n");
}

Y txtMensaje es el JTextArea en la parte inferior de la ventana.

Ahora vamos con start (y de paso stop), después EstadoHuellas y luego saltamos a ProcesarCaptura.

public void start(){
  Lector.startCapture();
  EnviarTexto("Utilizando lector de huella dactilar");
}
public void stop(){
  Lector.stopCapture();
  EnviarTexto("Lector detenido");
}

Iniciamos y terminamos la captura del lector y, además, mostramos un mensaje por cada evento.

Seguimos con EstadoHuellas

public void EstadoHuellas(){
  EnviarTexto("Muestra de huellas necesarias para guardar plantilla: " + Reclutador.getFeaturesNeeded());
}

Únicamente muestra un mensaje con la cantidad de huellas que faltan para completar la plantilla, que por defecto son 4.

Vamos con ProcesarCaptura.

public void ProcesarCaptura(DPFPSample muestra){
  featureSetInscripcion = extraerCaracteristicas(muestra, DPFPDataPurpose.DATA_PURPOSE_ENROLLMENT);
  featureSetVerificacion = extraerCaracteristicas(muestra, DPFPDataPurpose.DATA_PURPOSE_VERIFICATION);
  if(featureSetInscripcion != null){
    try {
      System.out.println("Las características de la huella han sido creadas");
      Reclutador.addFeatures(featureSetInscripcion);
      DibujarHuella(CrearImagenHuella(muestra));
      btnVerificar.setEnabled(true);
      btnIdentificar.setEnabled(true);
    } catch (DPFPImageQualityException e) {
      System.err.println("Error: "+e.getMessage());
    }finally {
    EstadoHuellas();
      switch (Reclutador.getTemplateStatus()){
        case TEMPLATE_STATUS_READY:
          stop();
          setTemplate(Reclutador.getTemplate());
          EnviarTexto("La plantilla de huella ha sido creada. Puede Verificar o Identificarla");
          btnIdentificar.setEnabled(false);
          btnVerificar.setEnabled(false);
          btnGuardar.setEnabled(true);
          btnGuardar.grabFocus();
          break;
        case TEMPLATE_STATUS_FAILED:
          Reclutador.clear();
          stop();
          EstadoHuellas();
          setTemplate(null);
          JOptionPane.showMessageDialog(Enrrolar.this,
            "La plantilla de la huella no pudo ser creada. Repita el proceso",
            "Inscripción de Huellas Dactilares",
            JOptionPane.ERROR_MESSAGE);
          start();
          break;
      }
    }
  }
}

Las 2 primeras líneas son para guardar las plantillas que, acabamos de leer o rescatar. Cada una donde corresponde. Las identificamos con el enum DATA_PURPOSE_ENROLLMENT o DATA_PURPOSE_VERIFICATION.

Las 2 las obtenemos llamando a la función extraerCaracteristicas, que tiene lo siguiente:

public DPFPFeatureSet extraerCaracteristicas(DPFPSample muestra, DPFPDataPurpose motivo){
  DPFPFeatureExtraction extractor = DPFPGlobal.getFeatureExtractionFactory().createFeatureExtraction();
  try{
    return extractor.createFeatureSet(muestra, motivo);
  } catch (DPFPImageQualityException e) {
    System.out.println(e.getMessage());
    return null;
  }
}

Recibimos el la plantilla con las 4 huellas y si es para guardar o leer. Nada más que eso.

Siguiendo con ProcesarCaptura, en el if, se puede dar el caso que la huella no quede bien leída u ocupemos otro dedo. En esos caso, no cae en la condición porque sería un null.

Al contrario, si todo sale ok, agregamos la huella a la plantilla, y además mostramos la huella en el jLabel que creamos. En realidad, le agregamos un ícono. Dicho paso lo creamos con estas 2 funciones:

public Image CrearImagenHuella(DPFPSample muestra){
  return DPFPGlobal.getSampleConversionFactory().createImage(muestra);
}
public void DibujarHuella(Image image){
  lblHuella.setIcon(
    new ImageIcon(
      image.getScaledInstance(
        lblHuella.getWidth(),
        lblHuella.getHeight(),
        Image.SCALE_DEFAULT
      )
    )
  );
}

Simplemente tomamos la huella, la “transformamos” en imagen y la agregamos en el label. Debo decir que hacer esto es muuuucho más simple en Java que en C# (primero aprendí a trabajar con huellas en C#)

Luego habilitamos los botones.

Si pos A, B, o C motivo algo pasa, entramos al catch y simplemente levantamos el error.

Siguiendo con la lógica del sistema, Imprimimos el estado (cuantos nos faltan de los 4). Y luego entramos a un switch y vemos si completamos las 4 lecturas o si algo malo ocurrió.

De estar terminado el proceso (4 lecturas), detenemos el lector y actualizamos la plantilla con las nuevas huellas leídas.

public void setTemplate(DPFPTemplate template) {
  DPFPTemplate antigua = this.template;
  this.template = template;
  firePropertyChange(TEMPLATE_PROPERTY, antigua, template);
}

Luego habilitamos los botones.

En caso de error, detenemos el lector, limpiamos las huellas que teníamos, vaciamos la plantilla, informamos del error, y luego reiniciamos la lectura.

En el caso de que aún falten huellas, no se hace nada y simplemente seguimos marcando con el dedo.

Y eso es todo😀

Una vez que aprenda a guardar la info en una BD, agrego el post correspondiente.

Acerca de MaritoCares

Ingeniero Informático. Con tendencias a la programación en [C#, VB].NET, Java(Web principalmente...), PHP, JavaScript, algo mínimo de [ruby, python], y el clásico C.
Esta entrada fue publicada en Java, Tutoriales. Guarda el enlace permanente.

31 respuestas a Lector Dactilar desde Java (Parte I)

  1. Ibrahim dijo:

    Oye amigo, ¿Podrias pasarme el link de donde descargaste el One Touch SDK? O mandarme el archivo de la libreria, en verdad te lo agradeceria mucho.

  2. Jon dijo:

    Pasame tu proyecto en mi correo….

    me urge

  3. Anónimo dijo:

    Hola buenas tardes, tengo una duda se necesita licencia para el SDK o es libre

  4. anielreyes dijo:

    Hola Y la segunda parte donde la encuentro???

  5. Anónimo dijo:

    este tutorial es inutil ya que net beans no deja editar tan facilmente los JPanels, es mejor dejar el proyecto, que andar adivinando que y como va acomodado

  6. Anónimo dijo:

    Hola, sabes como cambiar el parámetro para cambiar el numero de muestras necesarias para crear la plantilla, que son 4 por defecto?

  7. Anónimo dijo:

    Hola, sabes como hacer para que solo te pida una muestra de la huella en ves de 4??

  8. Guille dijo:

    cuando realizas el Clear and build y ejecutas el Jar genera exception, has logrado solucionarlos?, no logro pillar el problema con DPFPImageQualityException del sdk

    Exception in thread “main”

    java.lang.NoClassDefFoundError:

    com/digitalpersona/onetouch/processing/DPFPImageQualityException

    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
    at java.lang.Class.getMethod0(Unknown Source)
    at java.lang.Class.getMethod(Unknown Source)
    at sun.launcher.LauncherHelper.getMainMethod(Unknown Source)
    at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)

    Caused by:

    java.lang.ClassNotFoundException:

    com.digitalpersona.onetouch.processing.DPFPImageQualityException

    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)

  9. Julio dijo:

    Hola que variantes habría que hacer en este código para guardar el tempalte en formato ANSI378?
    Saludos

  10. Anónimo dijo:

    Hola, me puedes ayudar a comparar dos Template, quiero ver cuantas huellas tengo repetidas. Muchas gracias.

  11. MaritoCares dijo:

    Suponiendo que las tienes guardadas como tipo blob, es cosa de recorrer y comparar con un equals… No deberia ser tanto drama

  12. David dijo:

    Hola, oye… quiero verificar la huella que tengo en la plantilla con la que voy a capturar desde el lector, es decir… lo que haria el boton Verificar

  13. Worman Andrade dijo:

    Hola, buen día… Tengo un problema… me sale TEMPLATE_STATUS_INSUFFICIENT y no me permite guardar la huella en mi sqlServer. Me podrías ayudar con esto?

  14. kunkun901226 dijo:

    Cuando utilizo el lector dactilar todo funciona mientras la aplicación Java está corriendo en primer plano, pero en cuanto pierde el foco se dejan de escuchar los eventos.

  15. Max dijo:

    serias tan amable de colgar las librerias =)

  16. Saludos, aquí con un par de dudas, estuve investigando y el lector de huella digital Persona al parecer no es compatible con Windows 10 y 8, me podrías decir si ¿¿¿hay manera de adaptarlo a estos sistemas operativos???, y ¿¿los archivos Jar que utilizas pueden ser compatibles con otros lectores ???.. de antemano muchas gracias ….

    • MaritoCares dijo:

      Hola!
      Hace poco trabajé con un lector (mucho más nuevo del que usé cuando escribí ésta entrada) y no tuve ningún problema bajo W10… tal vez el lector/driver que ocupaste era antiguo.

      Con respecto a los archivos Jar, va a depender de la versión de driver que traiga dicho Jar… si el driver que entrega Digital Persona es “universal” no deberías tener problemas. Yo solamente tenía un modelo, por lo que no puedo confirmarlo.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s