Professional Documents
Culture Documents
SZTUCZNA INTELIGENCJA - Brzegowy Dutka
SZTUCZNA INTELIGENCJA - Brzegowy Dutka
Krzysztof Brzegowy
Jarosław Dutka
1 Wstęp.............................................................................................................................................4
2 Systemy oparte o geometrię dłoni.................................................................................................6
3 Proces rozpoznawania....................................................................................................................7
3.1 Sposób pozyskiwania danych.................................................................................................7
3.2 Segmentacja...........................................................................................................................9
3.3 Obróbka zdjęć.......................................................................................................................10
4 Cechy geometrii dłoni...................................................................................................................13
5 Sposób porównywania cech.........................................................................................................14
5.1 Normalizacja.........................................................................................................................14
5.2 Metoda najbliższego sąsiada................................................................................................14
5.3 Metryka................................................................................................................................15
5.4 Wagi......................................................................................................................................15
6 Przeprowadzone badania.............................................................................................................16
6.1 Metoda przeprowadzenia badań..........................................................................................16
6.2 Wyniki testów.......................................................................................................................16
6.2.1 Test 1............................................................................................................................16
6.2.2 Test 2............................................................................................................................16
6.2.3 Test 3............................................................................................................................16
6.3 Interpretacja wyników..........................................................................................................17
6.4 Wnioski.................................................................................................................................17
7 Wstęp do OpenCv + opis wykorzystywanych struktur oraz funkcji..............................................18
7.1 Pliki nagłówkowe..................................................................................................................18
7.2 IplImage – struktura danych obrazowych.............................................................................18
7.2.1 Alokacja obrazu:...........................................................................................................18
7.2.2 Zwalnianie obrazu:........................................................................................................19
7.2.3 Powielanie obrazu:.......................................................................................................19
7.2.4 Odczytywanie obrazu z pliku........................................................................................19
7.2.5 Zapis obrazu do pliku:...................................................................................................19
7.3 CvScalar – struktura przechowująca skalary.........................................................................19
7.4 CvPoint - struktura przechowująca współrzędne punktów..................................................20
7.5 Funkcje rysowania................................................................................................................20
7.5.1 Okrąg............................................................................................................................20
7.5.2 Odcinek.........................................................................................................................20
8 Integracja OpenCV 1.0 ze środowiskiem Visual Studio 2008........................................................21
9 Struktury i funkcje........................................................................................................................23
9.1 Struktury...............................................................................................................................23
9.1.1 Circle.............................................................................................................................23
9.1.2 Finger............................................................................................................................23
9.1.3 Hand.............................................................................................................................24
9.2 Funkcje pomocnicze.............................................................................................................26
9.2.1 get_pixel(IplImage* image, CvPoint p).........................................................................26
9.2.2 set_pixel(IplImage* image, CvPoint p, unsigned char c)...............................................26
9.2.3 calc_distance(CvPoint p1, CvPoint p2)..........................................................................27
10 Proces przetwarzania próbki oraz wyszukiwania cech.............................................................28
10.1 Przygotowanie wektora punktów konturu...........................................................................28
10.2 Znajdowanie końcówek palców oraz zagłębień miedzy palcami..........................................30
10.3 Znajdowanie cech placów.....................................................................................................32
10.4 Znajdowanie punktów podstawy dłoni (lewy oraz prawy dolny punkt dłoni).......................33
10.5 Obliczenie cech dłoni............................................................................................................33
10.6 Obliczanie pole powierzchni palców.....................................................................................35
10.7 Znajdowanie okręgów wpisanych w palce............................................................................38
11 Instrukcja obsługi......................................................................................................................43
12 Literatura..................................................................................................................................46
1 Wstęp
Najistotniejsze jest to, że obecnie stosowane metody identyfikują numer, kartę czy hasło, a nie
osobę. Uwierzytelnianie w takim przypadku nie jest w żaden sposób związana z osobą - jest związana
wyłącznie z urządzeniem. Prawdziwa, biometryczna identyfikacja zastępuje potrzebę pamiętania
hasła całkowicie. Biometryczne metody identyfikacji mogą być stosowane zarówno oddzielnie jak i
łącznie z dotychczas stosowanymi rozwiązaniami. Zabezpieczeń dla systemów informatycznych i
pomieszczeń wykorzystujących techniki biometryczne umożliwiają całkowitą ochronę przed
dostępem i ingerencją osób niepowołanych.
Informacja przetwarzana i przesyłana w tych systemach jest całkowicie niedostępna dla osób
postronnych. Dzięki zachowywaniu w repozytorium jedynie matematycznego zapisu cech
charakterystycznych, jak również dzięki szyfrowaniu transmisji, dane chronione są zarówno przed
przypadkowym jak i celowym działaniem intruzów. Systemy biometryczne zapewniają wysoki poziom
bezpieczeństwa oraz wygody. Użytkownicy systemu nie muszą nosić ze sobą żadnych specjalnych
kart, pamiętać skomplikowanych haseł itd. Z drugiej strony techniki te nadają się do zabezpieczania
zarówno pilnie strzeżonych zasobów jak i pojedynczych komputerów PC.
Problemy te nie występują w przypadku kontroli biometrycznej. Jest ona bowiem oparta o
specyficzne cechy organizmu (lub jego zachowania), indywidualnych dla każdego człowieka. Warto
podkreślić, że również z punktu widzenia kosztów systemy oparte o karty nie są najbardziej
korzystne: wszak oprócz czytnika trzeba jeszcze zakupić, często niebagatelną, ilość kart. Ponadto, w
przypadku kart magnetycznych konieczna jest ich okresowa wymiana! Dzięki powstaniu rozwiązań w
których weryfikacja jest przeprowadzona przez komputer, czytnik nie musi już być tak wyładowany
elektroniką.
Warto zauważyć, że mimo iż niemal cała pracująca populacja ma dłonie to system może również
zostać zaadaptowany do obsługi osób niepełnosprawnych (oczywiście tylko z pewnymi typami
niepełnosprawności). W razie konieczności istnieje możliwość integracji z innymi technikami
biometrycznymi, a w szczególności z pomiarami odcisków palców i/lub układu linii papilarnych na
wewnętrznej stronie dłoni (ang. palmprints).
Główną wadą biometrii geometrii dłoni jest fakt, że jakość działania systemu może zostać
poważnie zmniejszona w przypadku poważnych zranień dłoni (opuchnięcia, złamania). Tymczasem
uszkodzenia kończyn górnych są jednymi z najczęściej występujących skutków wypadków przy pracy.
Częściowym rozwiązaniem tego typu problemów może być wprowadzanie do pamięci systemu obu
dłoni każdego użytkownika.
Dane dotyczące kształtu dłoni są obliczane na podstawie zdjęcia dłoni. Po wykonania zdjęcia
dłoni stosuje się specjalne techniki przetwarzania obrazu i wyznacza geometryczne cech dłoni. W celu
porównania dłoni z zapisanym w pamięci systemu wzorcem stosowane są różne techniki klasyfikacji.
Sam proces porównania można rozumieć jako wyznaczanie odległości między wzorcem a aktualnie
weryfikowaną dłonią. Jeśli dłoń należy do tego samego użytkownika, do którego należy wzorzec, to
wyznaczona odległość jest mała (tzn. występuje duże podobieństwo między wzorcem a bieżącym
obrazem dłoni). W przeciwnym wypadku odległość jest duża.
3 Proces rozpoznawania
3.1 Sposób pozyskiwania danych
Pierwszym krokiem w systemie identyfikacji jest pobranie danych cech od użytkownika poprzez
wykonanie zdjęcia dłoni. Zdjęcia można wykonać na kilka różnych sposobów.
Zwykły aparat fotograficzny umieszczamy w stałej odległości od maty na której kładziemy dłoń.
W metodzie tej możliwe są różne kąty pomiędzy palcami (brak kołeczków) co wymaga dodatkowego
modułu dokonującego korekty rozstawień palców, gdyż metoda rozpoznawania dłoni po geometrii
wymaga aby kąty między palcami były odpowiednich stałych wielkości.
Innym sposobem realizacji tego problemu jest budowa urządzenia które składa się z szyby za
którą znajduje się aparat fotograficzny. Do szyby przykładamy dłoń. Dłoń za każdym razem jest w
jednakowej odległości od obiektywu. W takim rozwiązaniu napotykamy problem rozstawu palców
oraz detekcji dłoni od tła, gdyż dłoń może za każdym razem znajdować się na innym tle. Oba
problemy można rozwiązać.
Najbardziej przyjazną metodą, a zarazem najbardziej estetyczną jest kamera przed którą
obracamy ręką. System wybiera z serii zdjęć zdjęcie najbardziej prostopadłe do obiektywu i
przekazuje do dalszej obróbki. Jednakże w metodzie tej pojawia się poważny problem związany z
odległością ręki od obiektywu. Z lekcji fizyki wiemy, że rzeczy bliższe wydają się większe, a rzeczy
bardziej oddalone mniejsze. Z racji tego, że w naszym systemie do rozpoznawania używamy wiele
cech związanych z szukaniem odległości (palców, długości dłoni, obwodów, itd.) sytuacja taka nie
może mieć miejsca. Potrzebny jest moduł to skalowania obrazów zdjęć.
3.2 Segmentacja
W metodach których dopuszczamy różne rozstawy między palcami – nie używamy kołeczków
między które wstawiamy dłoń musimy dodać moduł dokonujący segmentacji dłoni. Dla każdej dłoni
wymagamy aby linie między wierzchołkami palców a punktami między nimi nie stykały się
wzajemnie. Dłonie mające podobne wady jak na rysunku poniżej należy odrzucić:
3.3 Obróbka zdjęć
odcięcie nadgarstka
Na powyższych ilustracjach pokazaliśmy jakie kroki wykonać, aby otrzymać obrazki mogące służyć
jako próbki w naszym programie. Nie jest to jednak zakres naszego projektu. Dokładny opis jak
wykonać powyższe kroki opisują: Ender Konukoğlu, Erdem Yörük, Jerôme Darbon, Bülent Sankur w
pracy pt: “Shape-Based Hand Recognition”
5x długość palca
5x pole podstawy palca
4x największy okrąg wpisany w górnej połowie palców (baz kciuka)
4x największy okrąg wpisany w dolnej połowie palców (bez kciuka)
1x największy okrąg wpisany w kciuka
5x pole powierzchni palców
5x obwód palców
4x odległości między początkiem kciuka a środkami podstaw poszczególnych palców (bez
kciuka)
4x poszczególne boki czworokąta wokół środka dłoni (czerwone linie na rysunku).
5 Sposób porównywania cech
Jako dane wyjściowe programu wyznaczającego cechy dostajemy wektor 39 liczb. Są to wartości
nie znormalizowane i ich zakres zależy od charakteru cechy. W takiej postaci cechy nie nadają się do
porównania gdyż zakres wartości każdej z cech jest różny. Aby temu zaradzić należy poddać wektor
cech normalizacji.
5.1 Normalizacja
Proces normalizacji przeprowadzany jest dla każdej cechy osobno. Pierwszym krokiem jest
znalezienie wartości maksymalnej i minimalnej cech. Następnie wartość każdej cechy jest
przenoszona w zakres 0,0 - 1,0. Przykładowo wartość pewniej cechy w jakiejś próbce wynosi 15.
Wartość minimalna równa się 10 a maksymalna 20. W tym przypadku nowa wartość tej cechy
wyniesie 0,5.
Po procesie normalizacji każda cecha znajduje się w zakresie 0,0 - 1,0 dzięki czemu waga każdej
cechy jest taka sama.
Jako metodę porównywania próbek wybraliśmy metodę najbliższego sąsiada. Polega ona na
mierzeniu odległości pomiędzy punktami które są reprezentowane poprzez wektor cech w
przestrzeniu n-wymiarowej oraz wybieraniu tych znajdujących sie najbliżej. W naszym przypadku
przestrzeń ta ma 39 wymiarów.
Każdy osobnik wprowadzany do systemu posiada pewną liczbę próbek jego dłoni. Taki zestaw
próbek tworzy tak zwaną klasę. Uwzględniając fakt, że punkty w takiej grupie leżą bardzo blisko
siebie możemy z dużym prawdopodobieństwem wnioskować, że najbliższy punkt aktualnie
badanemu należy do tej samej klasy.
Prosty przykład pokazujący ideę szukania najbliższego sąsiada. W tym przypadku są dwie klasy
punktów 'A' oraz 'B'. Oraz przestrzeń jest dwu-wymiarowa.
5.3 Metryka
Ważnym aspektem jest również sposób mierzenia odległości. Można tu skorzystać z różnych
metryk. My zdecydowaliśmy się na metrykę Euklidesową. Jest ona bardzo popularna i łatwa do
wyobrażenia sobie oraz zapewnie dobrą skuteczność.
√
N
d 2 ( x , y )= ∑ ¿¿¿
i=1
5.4 Wagi
Aby poprawić skuteczność metody zostały wprowadzone wagi dla każdej z cech. Wybór
odpowiedniego zestawu wag jest bardzo trudny i musi zostać wykonany automatycznie.
Głównym czynnikiem przyjętym przez nas podczas doboru wag był rozrzut wartości danej
cechy. Im Wartości były bardziej zróżnicowane tym waga była większa. Dobrym wskaźnikiem rozrzutu
jest odchylenie standardowe i właśnie je przyjęliśmy za wagi.
√
n
1
s= ∑ ¿¿¿
n−1 i=1
6 Przeprowadzone badania
6.1 Metoda przeprowadzenia badań
Pierwsza liczba określa numer aktualnie badanej klasy. Kolejne liczby to klasy najbliższych
sąsiadów. Jak widać w drugiej linijce najbliższy sąsiad dla tej próbki miał klasę numer 22 a poprawna
klasa znalazła się dopiero na czwartej pozycji.
Przeprowadziliśmy testy dla trzech zestawów próbek. Próbki te zostały wybrane przypadkowo.
Na każdego osobnika przypadają po 3 próbki dłoni. Daje to nam rozmiar klasy równy 3. Jest to
wartość bardzo mała. Zwiększenie jest do 5 lub 10 na pewno znacznie poprawiło by wyniki.
6.2.1 Test 1
Liczba próbek: 289
Dopasowanie: 1 - 90,31%, 2 - 93,43%, 3 - 94,46%, 4 - 96,19%, 5 - 96,89%, 6 - 97,23%, 7 - 97,92%, 8 - 98,27%, 9 -
98,62%, 10 - 98,62%,
6.2.2 Test 2
Liczba próbek: 199
Dopasowanie: 1 - 86,93%, 2 - 90,95%, 3 - 92,96%, 4 - 92,96%, 5 - 94,47%, 6 - 94,97%, 7 - 96,48%, 8 - 96,98%, 9 -
96,98%, 10 - 96,98%,
6.2.3 Test 3
Liczba próbek: 2225
Dopasowanie: 1 - 65,66%, 2 - 72,58%, 3 - 77,08%, 4 - 79,60%, 5 - 81,84%, 6 - 83,42%, 7 - 84,54%, 8 - 85,35%, 9 -
86,25%, 10 - 86,97%,
6.3 Interpretacja wyników
Pewne wątpliwości może budzić forma wyników. Otóż zapis 3 - 77,08% oznacza, że z
prawdopodobieństwem równym 77% wśród trzech najbliższych sąsiadów znajdzie się próbka tej
samej klasy co badana. W przypadku systemów wspomagających wybór decyzji w przypadku dostępu
warunkowego ta informacja jest dość istotna.
6.4 Wnioski
W teście numer 3 wyniki nie są zbyt dobre. Spowodowane to jest bardzo małą liczbą próbek
dłoni przypadającą na jedną osobę. W przypadku zwiększenia tej liczby wyniki powinny ulec znacznej
poprawie. W teście 1 gdzie sumaryczna liczba próbek była o rząd mniejsza wyniki prezentują się
znacznie lepiej.
7 Wstęp do OpenCv + opis wykorzystywanych struktur oraz funkcji
OpenCV jest biblioteką funkcji wykorzystywanych podczas obróbki obrazu, opartą o otwarty kod i
zapoczątkowaną przez Intela. Biblioteka ta jest wieloplatformowa, można z niej korzystać w Mac OS
X, Windows jak i Linux. Autorzy jej skupiają się na przetwarzaniu obrazu w czasie rzeczywistym.
Podstawowe struktury:
#include <cv.h>
#include <cvaux.h>
#include <highgui.h>
#include <cxcore.h> // niekoniecznie - zawarty w cv.h
IplImage
|-- int nChannels; // Number of color channels (1,2,3,4)
|-- int depth; // Pixel depth in bits:
| // IPL_DEPTH_8U, IPL_DEPTH_8S,
| // IPL_DEPTH_16U,IPL_DEPTH_16S,
| // IPL_DEPTH_32S,IPL_DEPTH_32F,
| // IPL_DEPTH_64F
|-- int width; // image width in pixels
|-- int height; // image height in pixels
|-- char* imageData; // pointer to aligned image data
| // Note that color images are stored in BGR order
|-- int dataOrder; // 0 - interleaved color channels,
| // 1 - separate color channels
| // cvCreateImage can only create interleaved
// images
|-- int origin; // 0 - top-left origin,
| // 1 - bottom-left origin (Windows bitmaps style)
|-- int widthStep; // size of aligned image row in bytes
|-- int imageSize; // image data size in bytes = height*widthStep
|-- struct _IplROI *roi;// image ROI. when not NULL specifies image
| // region to be processed.
|-- char *imageDataOrigin; // pointer to the unaligned origin of image
// data
| // (needed for correct image deallocation)
|
|-- int align; // Alignment of image rows: 4 or 8 byte alignment
| // OpenCV ignores this and uses widthStep instead
|-- char colorModel[4]; // Color model - ignored by OpenCV
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
cvReleaseImage(&img);
IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
IplImage* img2;
img2=cvCloneImage(img1);
Obsługiwane formaty: BMP, DIB, JPEG, JPG, JPE, PNG, PBM, PGM, PPM, SR, RAS, TIFF, TIF ):
IplImage* img=0;
img=cvLoadImage(fileName);
if(!img) printf("Nie można załadować pliku: %s\n",fileName);
Ładowany obraz domyślnie jest traktowany jako 3-kanałowy obraz kolorowy. Może to być
zmienione przez zastosowanie:
img=cvLoadImage(fileName,flag);
flag:
>0 the loaded image is forced to be a 3-channel color image
=0 the loaded image is forced to be a 1 channel grayscale image
<0 the loaded image is loaded as is (with number of channels in the file).
p.x=5.0;
p.y=5.0;
7.5.2 Odcinek
W projekcie została użyta biblioteka OpenCV 1.0. Po zainstalowaniu jej na PC, przed kompilacją
programu należy skonfigurować środowisko Visual Studio według następujących zasad:
"C:\Program Files\OpenCV\cv\include"
"C:\Program Files\OpenCV\cxcore\include"
"C:\Program Files\OpenCV\otherlibs\highgui"
"C:\Program Files\OpenCV\cvaux\include"
"C:\Program Files\OpenCV\otherlibs\_graphics\include"
Wybieramy z listy Sources files i dodajemy następujące katalogi:
"C:\Program Files\OpenCV\cv\src"
"C:\Program Files\OpenCV\cxcore\src"
"C:\Program Files\OpenCV\cvaux\src"
"C:\Program Files\OpenCV\otherlibs\highgui"
"C:\Program Files\OpenCV\otherlibs\_graphics\src"
Klikamy OK.
9 Struktury i funkcje
9.1 Struktury
9.1.1 Circle
Struktura definiująca okrąg jako środek , oraz promień. Trzymamy w niej okręgi wpisanych w palce.
struct circle
{
CvPoint p;
int r;
};
9.1.2 Finger
struct finger
{
int first;
int last;
int area;
int length;
int base_length;
int circuit;
circle circles[2];
CvPoint first_point;
CvPoint last_point;
CvPoint finger_end_point;
CvPoint base_center_point;
};
finger fingers[5];
9.1.3 Hand
struct hand
{
int total_area;
int length;
int base_center_point_to_thumb_length[4];
int index_first_point_to_pinkle_last_point_length;
int hand_right_end_point_to_left_end_point_length;
int hand_left_end_point_to_index_first_point_length;
int pinkle_last_point_to_hand_right_end_point_length;
CvPoint left_end_point;
CvPoint right_end_point;
};
hand hand_features;
9.2 Funkcje pomocnicze
9.2.1 get_pixel(IplImage* image, CvPoint p)
Dane wyjściowe - wektor w którym znajdują się punkty definiujące kontur dłoni, począwszy od
piksela leżącego o jedną pozycję piksela wyżej niż lewy dolny róg dłoni, zgodnie z ruchem wskazówek
zegara. Ostatni punkt w wektorze to lewy dolny róg dłoni.
std::vector<CvPoint> contour_points;
Tworzenie konturu dłoni podzielone jest na 2 etapy. Pierwszy to usunięcie z wnętrza dłoni
wszystkich białych pikseli tak by na obrazku został tylko kontur o grubości jednego piksela co jest
równoznaczne z tym, że każdy piksel ma tylko dwóch sąsiadów. Pierwszy etap realizuje następująca
funkcja:
if((!b1 && b2 && !b3 && b4)||(!b1 && b2 && b3 && !b4)||
(b1 && !b2 && !b3 && b4)||(b1 && !b2 && b3 && !b4))
out_data[i*image1->widthStep+j] = 0;
else
out_data[i*image1->widthStep+j] = 255;
}
else
out_data[i*image1->widthStep+j] = 0;
}
}
contour_points.push_back(current_point);
radial_distance_values.push_back(distance);
Jak widać na wykresie maksima oraz minima mogą być są płaskie. Każde ekstremum
traktowane jest jako pewien przedział gdyż nie można jednoznacznie powiedzieć który piksel jest
wartością maksymalną. Znajdowaniem tych przedziałów zajmuje sie funkcja find_extremums.
void find_extremums()
{
group min_group;
min_group.first = 0;
min_group.last = 0;
group max_group;
max_group.first = 0;
max_group.last = 0;
min_group.first = 0;
min_group.last = 1;
min_points_groups.insert(min_points_groups.begin(), min_group);
}
Po znalezieniu kluczowych punktów dłonie policzenie większości cech jest stosunkowo proste.
Sprowadza się to do paru prostych operacji matematycznych jak liczenie odległości między punktami.
Funkcja licząca cechy palców nazywa się calc_fingers_feature i wygląda następująco.
void calc_fingers_feature()
{
for(int i=0; i<1; i++)
{
CvPoint p1 = contour_points[min_points_groups[i].last];
CvPoint p2 = contour_points[min_points_groups[i+1].first];
CvPoint p3 = cvPoint(
(p2.x - p1.x)/2 + p1.x,
(p2.y - p1.y)/2 + p1.y);
CvPoint p4 = find_farrest_point(max_points_groups[i], p3);
fingers[i].first = min_points_groups[i].last;
fingers[i].last = min_points_groups[i+1].first;
fingers[i].first_point = p1;
fingers[i].last_point = p2;
fingers[i].base_center_point = p3;
fingers[i].finger_end_point = p4;
}
fingers[i-1].first_point = p1;
fingers[i-1].last_point = p2;
fingers[i-1].base_center_point = p3;
fingers[i-1].finger_end_point = p4;
}
}
10.4 Znajdowanie punktów podstawy dłoni (lewy oraz prawy dolny punkt
dłoni).
std::vector<CvPoint> contour_points;
Cel: uzupełnienie pól prawego oraz lewego dolnego punktu w strukturze hand.
Lewy dolny punkt dłoni to ostatni punkt w konturze. Prawy dolny punkt obliczamy korzystając z
wiadomości, że jest to punkt o takiej samej współrzędnej OY jak lewy, natomiast współrzędna OX jest
największa z możliwych.
hand_features.right_end_point = hand_features.left_end_point =
contour_points[contour_points.size()-1];
Całkowite pole powierzchni dłoni obliczamy jako liczba białych pikseli na znormalizowanym obrazku:
Całkowitą długość dłoni obliczamy jako odległość między współrzędną OY lewego dolnego
punktu dłoni, a najmniejszą współrzędną OY z pośród środków paznokci palców.
Pozostałe cechy dłoni (struktura hand) wyliczamy wykorzystując wcześniej omówioną funkcję
calc_distance.
void find_hand_features()
{
int i,j;
for(i=0;i<image_orginal->height;i++)
for(j=0;j<image_orginal->width;j++)
{
if ( get_pixel(image_orginal, cvPoint(i, j)) == 255 )
hand_features.total_area++;
}
//hand_right_end_point_to_left_end_point_length
hand_features.hand_right_end_point_to_left_end_point_length =
calc_distance(hand_features.right_end_point,hand_features.left_end_point);
//hand_left_end_point_to_index_first_point_length;
hand_features.hand_left_end_point_to_index_first_point_length =
calc_distance(hand_features.left_end_point,fingers[1].first_point);
//pinkle_last_point_to_hand_right_end_point_length;
hand_features.pinkle_last_point_to_hand_right_end_point_length =
calc_distance(fingers[4].last_point,hand_features.right_end_point);
Pierwszym krokiem jest odseparowanie palców od całej dłoni, poprzez narysowanie linii
łączących punkty między palcami. Po realizacji tego kroku otrzymujemy:
Następnie dla każdego palca z osobna zapuszczanym algorytm wypełnianie konturowe (ang
boundary-fill) - wszystkie piksele zawarte wewnątrz konturu (zamkniętej linii zbudowanej z pikseli o
tym samym kolorze – linie obwodów palców ) zostają pokolorowane na ten sam kolor wypełnienia.
Pozostałe piksele znajdujemy wykorzystując fakt, że: do każdego piksela w obszarze można
dotrzeć poruszając się po pikselach tego obszaru tylko w 4 kierunkach - góra, dół, prawo, lewo
Omawiany algorytmy należy do grupy algorytmów wypełniania przez sianie (ang. seed fill
algorithm) . Wewnątrz wypełnianego obszaru umieszczamy ziarno wypełnienia, a następnie
próbujemy je propagować (siać) w czterech kierunkach. Jeśli ziarno trafi na podatny grunt, to
wypełnia go kolorem i próbuje dalej się propagować w czterech kierunkach. W ten sposób cały
obszar zostanie zamalowany określonym kolorem. Ziarno sieje się tylko na pikselu o kolorze różnym
od koloru konturu.
Podczas siania liczymy sumę zasianych ziaren dla poszczególnych pól (palców). Wielkość ta to
pole powierzchni poszczególnych palców.
void clac_fingers_area()
{
IplImage *img; // obraz z konturem dłoni
img = cvCloneImage(image1);
// góra
p.x = top.x + 1;
p.y = top.y;
color = get_pixel(img,p);
if ( color != 255 && color != 155 ) stack.push(p);
// dół
p.x = top.x - 1;
p.y = top.y;
color = get_pixel(img,p);
if ( color != 255 && color != 155 ) stack.push(p);
// prawo
p.x = top.x ;
p.y = top.y + 1;
color = get_pixel(img,p);
if ( color != 255 && color != 155 ) stack.push(p);
// lewo
p.x = top.x;
p.y = top.y - 1;
color = get_pixel(img,p);
if ( color != 255 && color != 155 ) stack.push(p);
}
// pole powierzchni palca = liczba zasianych ziaren w danym
// obsarze – liczba pokolorowanych pikseli
fingers[i].area = count;
Problem znajdowania okręgów wpisanych w palce, można uogólnić jako problem wpisania okręgu w
dowolny obszar zamknięty, jak np.; kwadrat, trapez, pięciokąt lub inny obszar ograniczony.
Jako dane wyjściowe otrzymujemy tablice której wartości gdzie występowało zero zostały zastąpione
wartościami kwadratu największej odległości promienia okręgu o środku w danym punkcie
wpisanego w obszar ograniczony.
Wejście: 1 1 1 1 1 1 1 1 1
1 1 1 0 0 0 1 1 1
1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1
1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1
1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1
1 1 1 0 0 0 1 1 1 1 1 1 2 4 2 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 4 9 4 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 2 4 2 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
Wyjście: 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
Algorytm realizujący powyższe zadanie (dokładne opis zasady działania znajduje się w pracy Pedro F.
Felzenszwalb oraz Daniel P. Huttenlocher dołączonej jako załącznik do projektu):
dd = new unsigned[_h*_w];
n=_h>_w?_h:_w;
v = new int[n];
z = new int[n+1];
f = new unsigned[_h];
for(i=0;i<_h;i++)
{
k=-1;
for(j=0;j<_w;j++)if(_bimg[i*_w+j])
{
int s;
s=k<0?0:(v[k]+j>>1)+1;
v[++k]=j;
z[k]=s;
}
if(k<0)
for(j=0;j<_w;j++)dd[j*_h+i]=UINT_MAX;
else
{
int zk;
z[k+1]=_w;
j=k=0;
do
{
int d1;
int d2;
d1=j-v[k];
d2=d1*d1;
d1=d1<<1|1;
zk=z[++k];
for(;;)
{
dd[j*_h+i]=(unsigned)d2;
if(++j>=zk)break;
d2+=d1;
d1+=2;
}
}
while(zk<_w);
}
}
for(j=0;j<_w;j++)
{
int v2;
int q2;
k=-1;
for(i=q2=0;i<_h;i++)
{
unsigned d;
d=dd[j*_h+i];
if(d<UINT_MAX)
{
int s;
if(k<0)s=0;
else for(;;)
{
s=q2-v2+d-f[k];
if(s>0)
{
s=s/(i-v[k]<<1)+1;
if(s>z[k])break;
}
else s=0;
if(--k<0)break;
v2=v[k]*v[k];
}
if(s<_h){
v[++k]=i;
f[k]=d;
z[k]=s;
v2=q2;
}
}
q2+=i<<1|1;
}
if(k<0)
{
memcpy(_d,dd,_w*_h*sizeof(*_d));
break;
}
else
{
int zk;
z[k+1]=_h;
i=k=0;
do
{
int d2;
int d1;
d1=i-v[k];
d2=d1*d1+f[k];
d1=d1<<1|1;
zk=z[++k];
for(;;)
{
_d[i*_w+j]=(unsigned)d2;
if(++i>=zk)break;
d2+=d1;
d1+=2;
}
}
while(zk<_h);
}
}
delete f;
delete z;
delete v;
delete dd;
}
Wykorzystując powyższy algorytm napiszemy funkcję przyjmująca jako dane wejściowe obrazek
binarny typu:
0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 0 0 0
0 0 1 0 0 0 1 0 0
0 1 0 0 0 0 0 1 0
0 1 0 0 0 0 0 1 0
0 1 0 0 0 0 0 1 0
0 0 1 0 0 0 1 0 0
0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0
for(m=0;m<h;m++)
for(n=w-1;n>0;n--)
{
if (b[m*w+n] == 1 ) break;
b[m*w+n] = 1;
}
for(m=0;m<h;m++)
for(n=0;n<w;n++)
{
if (max < d[m*w+n])
{
max = d[m*w+n];
pMax = cvPoint(n,m);
}
}
circle abc;
abc.p = pMax;
abc.r = (int)sqrt((float)max);
delete b;
delete d;
return abc;
}
11 Instrukcja obsługi
W folderze zawierającym program aby wszystko działało jak należy powinny znajdować się
następujące pliki:
cv100.dll,
cxcore100.dll,
highgui100.dll,
libguide40.dll,
handrec.exe,
run.bat,
save_to_file.bat,
HandRecManager.exe,
ZedGraph.dll
Program Handrec.exe był tematem naszego projektu. Nie jest bezpośrednio używany lecz korzysta z
niego HandRecManager.exe oraz skrypt save_to_file.bat. Przyjmuje on jako parametr wejściowy
nazwę bitmapy z dłonią, zwraca wektor cech danej dłoni. Program ten został napisany w C++ i
szczegółowo jest omówiony we wcześniejszej części dokumentacji. Korzysta on z OpenCv 1.0 dlatego
w danym folderze muszą się znajdować pliki: cv100.dll, cxcore100.dll, highgui100.dll, libguide40.dll.
Do tworzenia bazy danych z wartościami cech dłoni służy skrypt save_to_file.bat. Stworzona baza
cech dłoni jest używana przez HandRecManager.exe. Program pobiera bitmapy z folderu images_in,
wylicza cechy dłoni korzystając z programu handrec.exe, oraz tworzy i umieszcza je w pliku out.txt.
Stworzenie bazy cech dłoni polega więc na skopiowaniu danych bitmapek z dłońmi do katalogu
images_in oraz uruchomieniu skryptu save_to_file.bat.
Po kliknięciu przycisku Test przeprowadzane są testy skuteczności rozpoznawania dłoni przez nas
system. Dokładny opis interpretacji wyników znajduje się w rozdziale 6.1 Metoda przeprowadzenia
badań.
Po kliknięciu przycisku Wagi wyliczane są wagi dla każdej cechy dłoni według zasady opisanej w
paragrafie 5.4 Wagi.
Program posiada możliwość narysowania ilości wystąpień danej wartości pojedynczej cechy –
rozrzut wartości danej cechy. Na podstawie narysowanego histogramu liczone jest odchylenie
standardowe danej cechy oraz ustalana waga. Wartości cechy są znormalizowane do przedziału od 0
do 100. Aby narysować histogram danej cechy wybieramy numer cechy, a następnie klikamy w
przycisk Histogram.
Program pozwala na narysowanie odległości danej próbki podanej w ścieżce według zasady opisanej
w paragrafie 5.2 Metoda najbliższego sąsiada oraz 5.3 Metryka do wszystkich innych znajdujących się
w bazie.
Dla przykładu wybieramy próbkę Hand_2_2.bmp. Odległość danej próbki do samej siebie wynosi zero
– co przedstawia brak słupka na wykresie. Im bardziej podobna próbka, tym wysokość słupka jest
mniejsza. Wynika z tego że najbardziej podobną próbką jest Hand_1_2.bmp, co jest zgodne z
rzeczywistością. Zauważamy także że próbki tego samego osobnika mają podobne wysokości słupków
na wykresie. Oznacza to że dłonie są podobne.
Aby sprawdzić powyżej opisane zależności klikamy w przycisk Check sample, a następnie podajemy
ścieżkę do sprawdzanej próbki dłoni.
12 Literatura
1. Erdem Yoruk , Helin Dutagaci, Bulent Sankur, „Hand biometrics”
2. Erdem Yoruk , Helin Dutagaci, Bulent Sankur, „Comparative analysis of global hand
apperance-based person recognition”
3. Próbki:
http://www.busim.ee.boun.edu.tr/%7Esankur/SankurFolder/normalized_binary_han
ds.zip
4. Yaroslav Bulatov, Sachin Jambawalikar, Piyush Kumar, Saurabh Sethia, „Hand
recognition Rusing geometric classifiers”
5. Xiaoqian Jiang, Wanhog Xu, „Contactless hand recognition”
6. Xiaoqian Jiang, Wanhong Xu, Latanya Sweeney, Yiheng Li, Ralph Gross, Daniel Yurovsky „New
directions In contact free hand recognition”
7. Pedro F. Felzenszwalb, Daniel P. Huttenlocher „Distance Transforms of Sampled Functions”