Posted on Di 27 Juli 2010

Biometric identification through door movement analysis

With my friend Julian we thought it may be possible to identify a person entering into a building from the way it opens the building's door, analyzing the angular values over time.

It's because of the differences between human beings (physical and psychological) that anyone of us interact with our surroundings in a very unique way. The key thing here is to be able to recognize patterns for each individual, and then use them as identification method.

samples

Input

The first step is to collect some samples, so we can have a nice test set to develop/train the recognition system.

To feed the system, we wanted to sample the angular position of a door at a fixed rate for a fixed amount of time. This sample will then be used as the 'fingerprint' of the person to be identified.

The experiment is going to take place with a garage door, where only a reduced amount of people has access.

For the sensor we use a potentiometer with its body fixed to the wall, and the moving shaft attached to the door.

potentionmeter

The potentiometer should be aligned with the door axis, allowing the moving shaft to follow the angular movements of the door.

potentionmeter

Nice, we're all set. Now whenever someone opens the door, the potentiometer will track the movement all the time.

To process the signal we use an Arduino, and because we are students with no money it's my self made Severino version.

The signals of the potentiometer are directly connected to the Arduino, where it's digitalized/cuantified and then sent to a PC where it's going to be stored in a database for future processing.

arduino

We defined our data sample as the serie of measurements while the door is open. When the door is closed we don't care.

As the Arduino is very scarse on memory we have can't store the whole data sample on it, and then send it to the PC. We have to send every measurement away to keep the memory footprint low, and assemple the data sample on the PC which has more resources. The arduino runs a sketch wich performs the following:

  • It calibrates the value of the door closed
  • Detects when the door starts to open
  • When its opened
    • Measure the potentiometer signal
    • Send this signal to the computer immediately (there is no enough memory on the arduino to store large samples)
    • Wait a fixed amount of time before the next reading
  • When the door closes send a special character to signalize the pc that the sampling finished (and it can be saved on the DB)

The code of the sketch looks like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
       Neuror - Door Interface Sketch 
*/

/// Parametros de funcionamiento ///
#define Tolerancia 7
#define PinAnalogico 0
#define PinLedIndicador 13
#define TiempoEntreMuestras 20 // Valor en ms. + lo q toma enviar 
                               // los 2/3/4/5 bytes por serial.

int i = 0;
int valorAD;
int valorMinimo = 1023; // Para forzar una recalibracion

void setup() {
    Serial.begin(9600); 
    pinMode(PinLedIndicador, OUTPUT);

    // Serial.println("READY!");
    // Mostar q ya empieza el programa
    digitalWrite(PinLedIndicador, HIGH);   
    delay(1000);                  
    digitalWrite(PinLedIndicador, LOW);

    /// RUTINA RECALIBRACION ///
    valorAD = analogRead(PinAnalogico);
    if ((valorAD-valorMinimo) <= -(Tolerancia/2)) { 
        // Hay q recalibrar el minimo.  Si el minimo esta demasiado cerca
        // del limite superior del CAD no hay q establecerlo tan cerca.
        if ((1023-valorAD) > Tolerancia) {          
          valorMinimo = valorAD;
        }
        else {
          valorMinimo =1023 - Tolerancia -1;
        }

        // Prendemos el led para mostar q se recalibro (sucking copypaste) 
        digitalWrite(PinLedIndicador, HIGH);   
        delay(500);                  
        digitalWrite(PinLedIndicador, LOW);
        delay(500);   
        digitalWrite(PinLedIndicador, HIGH);   
        delay(500);                  
        digitalWrite(PinLedIndicador, LOW);
    }
    /// RUTINA RECALIBRACION ///
}

void loop() {
    valorAD = analogRead(PinAnalogico);

    if ((valorAD-valorMinimo) >= Tolerancia) {
        digitalWrite(PinLedIndicador, LOW);

        while((valorAD-valorMinimo) >= Tolerancia){ 
          Serial.print(valorAD);
          Serial.println();
          delay(TiempoEntreMuestras);
          valorAD = analogRead(PinAnalogico);
        }

        Serial.print("x");  // Esto indica el fin del sample
        Serial.println();   // Esto indica el fin de la transmision
        digitalWrite(PinLedIndicador, HIGH);  
    }
    delay(10);  // Evita falsos samples cuando la puerta 'rebota' 
}

To recieve the data we reconditioned some old hardware, and we plug the Arduino Severino to the serial port (I like old fashion). If you're interested you can read about how to invert your monitor coils.

pc

The data is now received on the PC through the serial port. To keep it simple we run a SQLite database and a python script which constantly waiting for data. The script recieves all the measurements in secuence, and when the newline caracter arrives it will recognice it as the end of the sample and store it in the database.

So a little more of detail:

  • Connect to the database and get a cursor
  • Open the serial port
  • Go in a loop where:
    • It receives each reading until a newline character signalizes the end of the sampling
    • Store the sample on the database

NOTE: The readline() function of the Serial library blocks until the newline character appears on the line.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import datetime
import serial
import sqlite3
import time

connection = sqlite3.connect('puerta-datos.db', 
                             detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
cursor = connection.cursor()

## To create the database the first time uncomment this
#print "Creando base de datos..."
#cursor.execute('DROP TABLE datos')
#cursor.execute('CREATE TABLE datos (id INTEGER PRIMARY KEY, 
#                                    fecha TIMESTAMP, 
#                                    datos VARCHAR(320))')  #320 ==> "9999-"x64
#connection.commit()

## To print all the data use this
#print "Visualizando datos:"
#cursor.execute('SELECT * FROM datos')
#for row in cursor:
#    print row

s = serial.Serial('/dev/ttyS0', 9600)
print "Port in use:", s.portstr

while True:
    cursor.execute('INSERT INTO datos(fecha, datos) values (?, ?)',
                    (datetime.datetime.now(),
                     s.readline())
                  )
    connection.commit()

#cursor.close()
#connection.close()
#s.close()

Samples

The samples obtained were very nice. You can tell just by looking at them, the different patters that appear.

See the picture at the beginning of the article. I used matplotlib to plot some of them.

samples samples

Analysis

Julian started to train some neuronal networks to be able to recognize and group the patterns. He worked with Kohonnen maps.

Sadly we had to quit the project because we got another priorities and we end up abandon the project.

UPDATE (Oct 2014): I put all the samples and code on GitHub in case you're interested.

Author: Maximiliano Padulo

Category: hacks

© Maximiliano Padulo. Site built with Pelican. Theme forked from perec. Member of the Internet Defense League.