Parmak İzi Sensörü ve kullanımı.

Yayınlandı: 05 Ağustos 2018 / İncelemeler
Etiketler:, , , , ,

Parmak izi sisteminin bulunuşu çok eski tarihlere dayanır, fakat bu izden istifade etmek oldukça yenidir. Eski literatürde parmak izi konusunda bazı kayıtlar varsa da bu kayıtlarda parmak izinin kullanılması hususunda herhangi bir bilgiye rastlanmamaktadır. İlk önce, Nehemiah Grew (1684), Marcello Malpighi (1686) ve J. E. Purkinje (1823) gibi anatomistler insanların parmaklarındaki kıvrımların bazı özellikleri bulunduğuna dikkat çekmekle beraber, bu izlerden faydalanma metotlarını belirtmemişlerdir.

Modern manada parmak izi tespiti ve faydalanma konusunda ilk adım 1880’de atılmıştır. Bu tarihte İngiliz bilgini olan Henry Faulds ve Wiliam James Herschel adlı iki İngiliz, Nature adlı bir ilmi mecmuada parmak izi hakkında makale yazmışlardır. Bu bilginler önceleri pişmiş çömleklerdeki parmak izleriyle ve matbaa mürekkebiyle parmak izi alma metoduyla uğraştılar. Bu gün kullanılan parmak izi metodu da aynı esasa dayanır.

Parmak izi konusunda daha sonra çalışan Galton da, kalıtım yolu ile geçen parmak izi olmadığını açıkladı. Her insanın parmak izinin birbirinden farklı olduğunu kaydetti.

Parmak izi, bugün suçlunun tespitinde oldukça önem kazanmıştır. Kesin delil teşkil etmektedir. Bilhassa silah, tabanca vs. kullanılarak işlenen suçlarda parmak izi çok önem kazanmıştır.

Genetik parmak izi deliliyle ilk mahkumiyet kararı, 1987 Ekiminde Bristol (İngiltere) Mahkemesi’nde alınmıştır.

İlmi araştırmalar parmak izinin kimlik tespitinde kesin delil olduğunu göstermiştir. İnsanların parmak izleri birbirlerinin kesinlikle aynısı olmadığından, parmak izi suçlunun tespitinde çok önemli bir delil olmaktadır. Kişinin parmak kıvrımları yaşlanması ile değişmez ve kaybolmaz. Kolay ve ucuz bir metod olduğu için parmak izi bugün hüviyet tespitinde oldukça sık kullanılmaktadır.

Parmak izinin özelliklerinden dolayı son dönemlerde sıklıkla günlük hayatta  kimlik tespitinde kullanılmaya başlanmıştır. Cep telefonlarının ekran kilidini açmaktan tutun, artık apartman kapılarında bile anahtarsız giriş amacıyla kullanılmaktadır.

Ben de bedavadan parmağımda taşıdığım parmak izi bir işe yarasın diye öteden beri  kullanmak istediğim çin malı bir parmak izi sensörü olan FPM10A’yı satın alıp kurcaladım.

Büyük görmek için tıklayın…

Parmak izi sensörleri günümüzde 3 farklı yöntemle çalışmaktadırlar:   1- Optik, 2- Ultrasonik, 3- Kapasitif.

FPM10A en eski yöntem olan optik yöntemle ölçüm yapmaktadır. Bu sistemin çalışması kabaca bir ışık kaynağından gelen  ışık bir prizmadan geçirilerek  kırılır ve parmak yüzeyine yansıtılır. Parmaktan yansıyan ışık bir mercek vasıtasıyla optik sensör üzerine düşürülerek bir fotoğraf elde edilir. Buradaki optik sensörün kalitesi sensörün güvenilirliğindeki temel faktörlerden birisidir. Elde edilen fotoğraf, piksellerine ayrılarak her pikseldeki değer ayrı ayrı kaydedilir ve her parmak okumasında bu değerler karşılaştırılarak eşleşme olup olmadığı sınanır. Eşleşme belli bir oranın üzerindeyse okunan parmak izinin daha önce kaydedilen aynı parmağa ait olduğu kabul edilir.

Optik parmak izi tarayıcılar çok güvenli değillerdir. Çünkü protez bir parmak iziyle veya bir fotoğrafla kandırılabilirler. Sonuçta 2D bir görüntü üzerinden karşılaştırma yapılmaktadır.

Parmak izi sensörlerinde genel olarak iki ayrı işlem yapılmaktadır. Bunlar enrollment (kayıt) ve verification (doğrulama) olarak adlandırılırlar. İlk olarak sensör kayıt moduna alınarak kullanıcıların parmak izleri kayıt altına alınır. Daha sonra sensör doğrulama moduna geçirilerek kullanıcıların parmak izlerinin eşleşip eşleşmediği kontrol edilir ve bir bilgisayar veya mikrodenetleyici yardımıyla geçiş-kontrol işlemleri yaptırılabilir.

FPM10-A parmak izi sensörünün  özellikleri aşağıdaki gibidir.

  • Besleme Gerilimi: 3.6 – 6.0VDC
  • Çalışma Akımı: 120mA Azami
  • Anlık Azami Akım: 150mA
  • Parmak İzi Görüntüleme Hızı: <1.0 saniye
  • Sensör Alanı: 14mm x 18mm
  • İmza Dosyası: 256 bayt
  • Şablon Dosyası: 512 bayt
  • Depolama Kapasitesi: 162 şablon
  • Güvenlik Dereceleri: 1-5 arasında güvenlik seviyesi
  • Yanlış Kabul Oranı: <% 0,001 (Güvenlik seviyesi 3)
  • Yanlış Reddetme Oranı: <% 1.0
  • Baud Hızı: 9600, 19200, 28800, 38400, 57600 (varsayılan 57600)
  • Çalışma Sıcaklığı Aralığı: -20C ila + 50C
  • Nemli Çalışma:% 40 -% 85 RH
  • Tam Ebat: 56 x 20 x 21.5 mm
  • Ağırlık: 20 gram

Sensör dahili olarak parmak izlerini karşılaştırma ve buna göre çıkış verme özelliğine sahiptir. Özelliklerden görüldüğü gibi maksimum 162 parmak izi kaydetme kapasitesine sahiptir. Bu da bazı durumlarda yetersiz kalabilir.  Fakat sensörün ayrıca okuduğu parmak izi verilerini dışarıya aktarma özelliği de bulunmaktadır. Bu sayede sınırsız sayıda parmak izi verisini harici bir donanım üzerinde depolamamıza olanak sağlamaktadır. Geliştireceğimiz algoritmalar sayesinde okunan parmak izi verisi, harici hafızaya depoladığımız verilerle karşılaştırılarak geçiş-kontrol işlemleri yaptırabiliriz.

Gelelim sensörün dış dünya ile nasıl haberleştiğine. Sensör default olarak 57600 bps haberleşme hızında uart haberleşme protokolüyle haberleşmektedir. Aynı zamanda üzerinde usb bağlantısı kurabilmek için pinler de mevcuttur. Fakat ben henüz usb özelliğini denemedim. Sensörün haberleşme komutları sayesinde gerekli komutlar sensöre gönderilebilmekte ve istenilen veriler çıkıştan alınabilmektedir. Sensörün ram hafızasında 3 adet buffer bulunmaktadır. Bunlar Image Buffer, Char Buffer 1 ve Char Buffer 2 olarak isimlendirilmişlerdir. Sensörle işlem yapılırken çekilen parmak izi fotoğrafları ilk önce image buffer’a aktarılır. Buradaki resim dosyası  char buffer 1 veya char buffer 2 ‘ye aktarılarak,  kalıcı flash hafızaya kaydetme veya  karşılaştırma işlemleri yapılır.  Sensöre ayrıca 4 byte uzunluğunda bir şifre konularak farklı kişiler tarafından erişilmesinin önüne geçilebilinir. Sensörde ayrıca 32-bit değerinde bir random number generator (rastgele sayı üretici) bulunmaktadır. Bunlara ek olarak 512 byte uzunluğunda , kullanıcı için ayrılmış not defteri de bulunmaktadır.

Sensör ile iletişim kurmak için gerekli mesajların bir kısmı aşağıdakilerdir. Bu mesajları ben kurcalama esnasında not aldığım için hepsi burada bulunmamaktadır. Sensörün kullanım klavuzuna buradan ulaşarak daha detaylı inceleyebilirsiniz.

0xEF 0x01 0xFF 0xFF 0xFF 0xFF 0x01 0x00 0x04 0x17 0x00 0x00 0x1c //handshake
0xEF 0x01 0xFF 0xFF 0xFF 0xFF 0x01 0x00 0x03 0x01 0x00 0x05 // GenIMG
0xEF 0x01 0xFF 0xFF 0xFF 0xFF 0x01 0x00 0x03 0x1d 0x00 0x21 //Read valid template number:TempleteNum
0xEF 0x01 0xFF 0xFF 0xFF 0xFF 0x01 0x00 0x03 0x0f 0x00 0x13// Read system Parameter
0xEF 0x01 0xFF 0xFF 0xFF 0xFF 0x01 0x00 0x03 0x0a 0x00 0x0e // Upload image UpImage
0xEF 0x01 0xFF 0xFF 0xFF 0xFF 0x01 0x00 0x04 0x02 0x01 0x00 0x08 //To generate character file from image:Img2Tz CharBuffer1
0xEF 0x01 0xFF 0xFF 0xFF 0xFF 0x01 0x00 0x04 0x02 0x02 0x00 0x09 //CharBuffer2
0xEF 0x01 0xFF 0xFF 0xFF 0xFF 0x01 0x00 0x03 0x03 0x00 0x07 // To carry out precise matching of two finger templates:Match
0xEF 0x01 0xFF 0xFF 0xFF 0xFF 0x01 0x00 0x08 0x04 0x01 0x00 0x00 0x00 0xff 0x01 0x0d // Search: To search finger library (Page ID parmak ID si, Page Number : Parmak izi sayısı. Bizim modül 150 adet kabul ediyor)
0xEF 0x01 0xFF 0xFF 0xFF 0xFF 0x01 0x00 0x03 0x05 0x00 0x09 //To generate template: RegModel
0xEF 0x01 0xFF 0xFF 0xFF 0xFF 0x01 0x00 0x06 0x06 0x01 0x00 0xID 0x00 0xsum // To store template: Store Char Buffer 1
0xEF 0x01 0xFF 0xFF 0xFF 0xFF 0x01 0x00 0x06 0x02 0x00 0xID 0x00 0xsum //Store Char Buffer 2 ,// Checksum= 8+ID , 9+ID
0xEF 0x01 0xFF 0xFF 0xFF 0xFF 0x01 0x00 0x06 0x07 0x01 0x00 0xID 0x00 0xsum // LoadChar

Yukarıdaki komutlar sensöre gönderildiğinde sensör cevap olarak benzer mesajlar göndermektedir.  Bu mseajların bazı byte ları değerlendirilerek işlemler kontrol edilmektedir. Bu mesajların bazılarında checksum hesaplanmalıdır. Checksum mesajın doğruluğunu test edebilmek için kullanılan ve cümlenin son iki byte değerini kapsayan bir toplama işlemi sonucudur. cümlenin 7. byte’ından itibaren  gelen bütün bytelar toplama işlemine tabi tutulur ve elde edilen değer cümlenin son iki byte’ını oluşturur. Böylelikle cümlede bir hata olup olmadığı kontrol edilir.

Sensörün temel olarak iki fonksiyonu vardır; kayıt ve karşılaştırma. Aşağıda bu işlemleri yaparkan uyulması gereken sıralama gösterilmiştir;

Kayıt:
——
1- handshake
2- parmak okuyana kadar, Gen IMG
3- IMG2Tz Char buffer1
4- parmak okuyana kadar, Gen IMG
5- IMG2Tz Char buffer2
6- RegModel
7- Store Char Buffer 1 veya Store Char Buffer 2

Karşılaştırma:
—————–
1- handshake
2- parmak okuyana kadar, Gen IMG
3- IMG2Tz Char buffer1
4- search finger library

 

Burada da Nodemcu kullanarak yapmış olduğum kayıt ve karşılaştırma işlemlerinin kodları bulunmaktadır;

Kayıt:


#include <SoftwareSerial.h>
SoftwareSerial myserial(D7, D6); // RX, TX

byte handshake[13]={0xEF,0x01 ,0xFF ,0xFF ,0xFF ,0xFF ,0x01 ,0x00 ,0x04 ,0x17 ,0x00 ,0x00 ,0x1c};
byte getimg[12]={0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x03, 0x01, 0x00, 0x05};
byte img2tz1[13]={0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x04, 0x02, 0x01, 0x00, 0x08};
byte img2tz2[13]={0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x04, 0x02, 0x02, 0x00, 0x09};
byte regmodel[12]={0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x03, 0x05, 0x00, 0x09};
byte store[15]={0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x06, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00};
byte search[17]={0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x08, 0x04, 0x01, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0d};
byte load[15]={0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x06, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00};
int KAYIT_ID=7;

int tampon[25];

//////////////////////////////////////////////////////////
void tamponusifirla()
{
for(int i=0; i<25;i++)tampon[i]=0xff;
//for(int i=0;i<10;i++)myserial.read();
}
//////////////////////////////////////////////////////////
int fp_basla()
{
int i=0;
for(i=0; i<13; i++)
{
myserial.write(handshake[i]);
}

while(!myserial.available());
i=0;
while(i<12)
{
if(myserial.available())
{
tampon[i]=myserial.read();
i++;
}
}

if(tampon[9]==0)
{
tamponusifirla();
return 1;
}
else
{
tamponusifirla();
return 0;
}
}
//////////////////////////////////////////////////////////
int parmak_oku()
{
int i=0;
for(i=0; i<12; i++)
{
myserial.write(getimg[i]);
}

while(!myserial.available());
i=0;
while(i<12)
{
if(myserial.available())
{
tampon[i]=myserial.read();
i++;
}
}

if(tampon[9]==0)
{
tamponusifirla();
return 1;
}
else if(tampon[9]==1 || tampon[9]==3)
{
tamponusifirla();
return 2;
}
else
{
tamponusifirla();
return 0;
}
}
//////////////////////////////////////////////////////////
int chardizisinecevir()
{
int i=0;
for(i=0; i<13; i++)
{
myserial.write(img2tz1[i]);
}

while(!myserial.available());
i=0;
while(i<12)
{
if(myserial.available())
{
tampon[i]=myserial.read();
i++;
}
}

if(tampon[9]==0)
{
tamponusifirla();
return 1;
}
else
{
tamponusifirla();
return 0;
}
}
//////////////////////////////////////////////////////////
int chardizisinecevir2()
{
int i=0;
for(i=0; i<13; i++)
{
myserial.write(img2tz2[i]);
}

while(!myserial.available());
i=0;
while(i<12)
{
if(myserial.available())
{
tampon[i]=myserial.read();
i++;
}
}

if(tampon[9]==0)
{
tamponusifirla();
return 1;
}
else
{
tamponusifirla();
return 0;
}
}
//////////////////////////////////////////////////////////
int datayi_goruntule(int pageid)
{
int i=0;
int sum=0;
byte pageid1,pageid2;
byte sum1,sum2;

pageid1=(pageid>>8)&0x00ff;
pageid2=(pageid&0x00ff);
load[11]=pageid1;
load[12]=pageid2;
for(i=6; i<13; i++)
{
sum+=load[i];
}
sum1=(sum>>8)&0x00ff;
sum2=(sum&0x00ff);
load[13]=sum1;
load[14]=sum2;

for(i=0; i<15; i++)
{
myserial.write(load[i]);
}

while(!myserial.available());
i=0;
while(i<12)
{
if(myserial.available())
{
tampon[i]=myserial.read();
i++;
}
}

if(tampon[9]==0)
{
tamponusifirla();
return 1;
}
else
{
tamponusifirla();
return 0;
}
}
//////////////////////////////////////////////////////////
int templateolustur()
{
int i=0;
for(i=0; i<12; i++)
{
myserial.write(regmodel[i]);
}

while(!myserial.available());
i=0;
while(i<12)
{
if(myserial.available())
{
tampon[i]=myserial.read();
i++;
}
}

if(tampon[9]==0)
{
tamponusifirla();
return 1;
}
else
{
tamponusifirla();
return 0;
}
}

//////////////////////////////////////////////////////////
int kayit_yap(int pageid)
{
int i=0;
int sum=0;
byte pageid1,pageid2;
byte sum1,sum2;

pageid1=(pageid>>8)&0x00ff;
pageid2=(pageid&0x00ff);
store[11]=pageid1;
store[12]=pageid2;
for(i=6; i<13; i++)
{
sum+=store[i];
}
sum1=(sum>>8)&0x00ff;
sum2=(sum&0x00ff);
store[13]=sum1;
store[14]=sum2;

for(i=0; i<15; i++)
{
myserial.write(store[i]);
}

while(!myserial.available());
i=0;
while(i<12)
{
if(myserial.available())
{
tampon[i]=myserial.read();
i++;
}
}
if(tampon[9]==0)
{
tamponusifirla();
return 1;
}
else
{
tamponusifirla();
return 0;
}
}

////////////////////////////////************************************///////////////////////////
void setup() {
Serial.begin(9600);
myserial.begin(57600);
delay(1000);

if(fp_basla()) Serial.println("El sıkışma tamam");
else Serial.println("El sıkışılamadı");

Serial.println("Kayıtlı ID numaraları:");
for(int j=0;j<150;j++)
{
if(datayi_goruntule(j))
Serial.println(j);
}
}

void loop()
{
int p=0;
Serial.println("Kaydedilecek Parmağınızı okutun...");
while(p==0)
{
p=parmak_oku();
}
if(p==1) Serial.println("Parmak okundu");
else if(p==2)Serial.println("Lütfen tekrar deneyin");

p=chardizisinecevir();
if(p==1) Serial.println("Karakter dizisine çevrildi..");
else if(p==0)Serial.println("Karakter dizisine çevrilemedi..");

p=0;
Serial.println("Kaydedilecek Parmağınızı tekrar okutun...");
while(p==0)
{
p=parmak_oku();
}
if(p==1) Serial.println("Parmak okundu");
else if(p==2)Serial.println("Lütfen tekrar deneyin");

p=chardizisinecevir2();
if(p==1) Serial.println("Karakter dizisine çevrildi..");
else if(p==0)Serial.println("Karakter dizisine çevrilemedi..");

p=templateolustur();
if(p==1) Serial.println("Template oluşturuldu, Kayıt numarasını giriniz (0-150)");
else if(p==0)Serial.println("Template oluşturulamadı..");

while(!Serial.available());
if(Serial.available()) KAYIT_ID=Serial.parseInt();
while(Serial.available())Serial.read();
p=kayit_yap(KAYIT_ID);
if(p==1){Serial.print(KAYIT_ID);Serial.println(" Numaralı ID ile kayıt oluşturuldu."); }
else if(p==0)Serial.println("Kayıt oluşturulamadı..");
delay(3000);

}

 

Karşılaştırma:


#include <SoftwareSerial.h>
SoftwareSerial myserial(D7, D6); // RX, TX

byte handshake[13]={0xEF,0x01 ,0xFF ,0xFF ,0xFF ,0xFF ,0x01 ,0x00 ,0x04 ,0x17 ,0x00 ,0x00 ,0x1c};
byte getimg[12]={0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x03, 0x01, 0x00, 0x05};
byte img2tz1[13]={0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x04, 0x02, 0x01, 0x00, 0x08};
byte img2tz2[13]={0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x04, 0x02, 0x01, 0x00, 0x08};
byte regmodel[12]={0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x03, 0x05, 0x00, 0x09};
byte store[14]={0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00};
byte search[17]={0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x08, 0x04, 0x01, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0d};
int PARMAK_ID,SKOR;

int tampon[25];

//////////////////////////////////////////////////////////
void tamponusifirla()
{
for(int i=0; i<25;i++)tampon[i]=0xff;
//for(int i=0;i<10;i++)myserial.read();
}
//////////////////////////////////////////////////////////
int fp_basla()
{
int i=0;
for(i=0; i<13; i++)
{
myserial.write(handshake[i]);
}

while(!myserial.available());
i=0;
while(i<12)
{
if(myserial.available())
{
tampon[i]=myserial.read();
i++;
}
}

if(tampon[9]==0)
{
tamponusifirla();
return 1;
}
else
{
tamponusifirla();
return 0;
}
}
//////////////////////////////////////////////////////////
int parmak_oku()
{
int i=0;
for(i=0; i<12; i++)
{
myserial.write(getimg[i]);
}

while(!myserial.available());
i=0;
while(i<12)
{
if(myserial.available())
{
tampon[i]=myserial.read();
i++;
}
}

if(tampon[9]==0)
{
tamponusifirla();
return 1;
}
else if(tampon[9]==1 || tampon[9]==3)
{
tamponusifirla();
return 2;
}
else
{
tamponusifirla();
return 0;
}
}
//////////////////////////////////////////////////////////
int chardizisinecevir()
{
int i=0;
for(i=0; i<13; i++)
{
myserial.write(img2tz1[i]);
}

while(!myserial.available());
i=0;
while(i<12)
{
if(myserial.available())
{
tampon[i]=myserial.read();
i++;
}
}

if(tampon[9]==0)
{
tamponusifirla();
return 1;
}
else
{
tamponusifirla();
return 0;
}
}
//////////////////////////////////////////////////////////
int arabul()
{
int i=0;
for(i=0; i<17; i++)
{
myserial.write(search[i]);
}

while(!myserial.available());
i=0;
while(i<16)
{
if(myserial.available())
{
tampon[i]=myserial.read();
i++;
}
}

if(tampon[9]==0)
{
PARMAK_ID=(tampon[10]<<8)+(tampon[11]&0x00ff);
SKOR=(tampon[12]<<8)+(tampon[13]&0x00ff);
tamponusifirla();
return 1;
}
else
{
tamponusifirla();
return 0;
}
}

void setup() {
Serial.begin(9600);
myserial.begin(57600);
delay(1000);
if(fp_basla()) Serial.println("El sıkışma tamam");
else Serial.println("El sıkışılamadı");
}

void loop()
{
int p=0;
Serial.println("Parmağınızı okutun...");
while(p==0)
{
p=parmak_oku();
}
if(p==1) Serial.println("Parmak okundu");
else if(p==2)Serial.println("Lütfen tekrar deneyin");

p=chardizisinecevir();
if(p==1) Serial.println("Karakter dizisine çevrildi..");
else if(p==2)Serial.println("Karakter dizisine çevrilemedi..");

p=arabul();
if(p==1){ Serial.print("Parmak izi bulundu, Kayıt no:");Serial.println(PARMAK_ID);Serial.print("Eşleşme skoru:");Serial.println(SKOR);}
else if(p==0){Serial.println("Parmak izi bulunamadı"); Serial.println("************************");}

delay(3000);

}

 

Buradan Sensörün çalışmasına ait videoyu izleyebilirsiniz;

İyi çalışmalar,  bir sonraki yazıda görüşmek üzere.

Yorum bırakın