├── .gitignore ├── Activity_Tracking_Web_App ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── tests.py └── views.py ├── Attendance_Logic_Module ├── clean_data.py ├── logic.py ├── result.csv ├── test1.csv ├── test2.csv ├── test3.csv └── test4.csv ├── Attendance_Tracking_System_Using_Computer_Vision ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py ├── Computer_Vision_Module ├── Adding_New_Person_And_Training.py ├── Extract_Faces.py ├── Get_Embeddings.py ├── Load_Dataset.py ├── Load_Faces.py ├── Model_Training.py ├── Multiple_Faces_Prediction.py ├── SVM_Classifier.py ├── Variables.py └── Video_Test.py ├── LICENSE ├── README.md ├── manage.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/django 3 | # Edit at https://www.gitignore.io/?templates=django 4 | ### Django ### 5 | *.log 6 | *.pot 7 | *.pyc 8 | __pycache__/ 9 | local_settings.py 10 | db.sqlite3 11 | media 12 | .vscode 13 | # If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/ 14 | # in your Git repository. Update and uncomment the following line accordingly. 15 | # /staticfiles/ 16 | ### Django.Python Stack ### 17 | # Byte-compiled / optimized / DLL files 18 | *.py[cod] 19 | *$py.class 20 | # C extensions 21 | *.so 22 | # Distribution / packaging 23 | .Python 24 | build/ 25 | develop-eggs/ 26 | dist/ 27 | downloads/ 28 | eggs/ 29 | .eggs/ 30 | lib/ 31 | lib64/ 32 | parts/ 33 | sdist/ 34 | var/ 35 | wheels/ 36 | pip-wheel-metadata/ 37 | share/python-wheels/ 38 | *.egg-info/ 39 | .installed.cfg 40 | *.egg 41 | MANIFEST 42 | # PyInstaller 43 | # Usually these files are written by a python script from a template 44 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 45 | *.manifest 46 | *.spec 47 | # Installer logs 48 | pip-log.txt 49 | pip-delete-this-directory.txt 50 | # Unit test / coverage reports 51 | htmlcov/ 52 | .tox/ 53 | .nox/ 54 | .coverage 55 | .coverage.* 56 | .cache 57 | nosetests.xml 58 | coverage.xml 59 | *.cover 60 | .hypothesis/ 61 | .pytest_cache/ 62 | # Translations 63 | *.mo 64 | # Django stuff: 65 | db.sqlite3-journal 66 | # Flask stuff: 67 | instance/ 68 | .webassets-cache 69 | # Scrapy stuff: 70 | .scrapy 71 | # Sphinx documentation 72 | docs/_build/ 73 | # PyBuilder 74 | target/ 75 | # Jupyter Notebook 76 | .ipynb_checkpoints 77 | # IPython 78 | profile_default/ 79 | ipython_config.py 80 | # pyenv 81 | .python-version 82 | # pipenv 83 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 84 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 85 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 86 | # install all needed dependencies. 87 | #Pipfile.lock 88 | # celery beat schedule file 89 | celerybeat-schedule 90 | # SageMath parsed files 91 | *.sage.py 92 | # Environments 93 | .env 94 | .venv 95 | env/ 96 | venv/ 97 | ENV/ 98 | env.bak/ 99 | venv.bak/ 100 | # Spyder project settings 101 | .spyderproject 102 | .spyproject 103 | # Rope project settings 104 | .ropeproject 105 | # mkdocs documentation 106 | /site 107 | # mypy 108 | .mypy_cache/ 109 | .dmypy.json 110 | dmypy.json 111 | # Pyre type checker 112 | .pyre/ 113 | # End of https://www.gitignore.io/api/django 114 | -------------------------------------------------------------------------------- /Activity_Tracking_Web_App/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammedSamirMahmoud/Attendance-Tracking-System-Using-Computer-Vision/bc737bd76867f93a38b0bbae62d746f872d02cfc/Activity_Tracking_Web_App/__init__.py -------------------------------------------------------------------------------- /Activity_Tracking_Web_App/admin.py: -------------------------------------------------------------------------------- 1 | 2 | # Register your models here. 3 | from django.contrib import admin 4 | from django.apps import apps 5 | # Register your models here. 6 | from .models import Employee, Picture, Activity 7 | 8 | 9 | class EmployeeAdmin(admin.ModelAdmin): 10 | list_display = ['name'] 11 | pass 12 | 13 | 14 | class ActivityAdmin(admin.ModelAdmin): 15 | 16 | list_display = ['Employee', 'date', 'arrival_time', 'depart_time', 'on_working', 17 | 'off_working', 'fun_area_time', 'active', 'exception', 'comment'] 18 | list_filter = ('active', 'exception', 'on_working') 19 | search_fields = ['Employee__name'] 20 | 21 | pass 22 | 23 | 24 | class PictureAdmin(admin.ModelAdmin): 25 | list_display = ['employee', 'pic'] 26 | pass 27 | 28 | 29 | admin.site.register(Activity, ActivityAdmin) 30 | admin.site.register(Employee, EmployeeAdmin) 31 | admin.site.register(Picture, PictureAdmin) 32 | -------------------------------------------------------------------------------- /Activity_Tracking_Web_App/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ActivityTrackingWebAppConfig(AppConfig): 5 | name = 'Activity_Tracking_Web_App' 6 | -------------------------------------------------------------------------------- /Activity_Tracking_Web_App/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-09-18 16:37 2 | 3 | import Activity_Tracking_Web_App.models 4 | import datetime 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | initial = True 12 | 13 | dependencies = [ 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='Employee', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('name', models.CharField(max_length=200)), 22 | ], 23 | ), 24 | migrations.CreateModel( 25 | name='Test', 26 | fields=[ 27 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 28 | ('model_pic', models.ImageField(blank=True, null=True, upload_to=Activity_Tracking_Web_App.models.test_content_file_name)), 29 | ], 30 | ), 31 | migrations.CreateModel( 32 | name='Picture', 33 | fields=[ 34 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 35 | ('pic', models.ImageField(blank=True, null=True, upload_to=Activity_Tracking_Web_App.models.content_file_name)), 36 | ('Employee', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='Activity_Tracking_Web_App.Employee')), 37 | ], 38 | ), 39 | migrations.CreateModel( 40 | name='Activity', 41 | fields=[ 42 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 43 | ('date', models.DateField(default=datetime.datetime.now)), 44 | ('arrival_time', models.CharField(blank=True, max_length=10000, null=True)), 45 | ('depart_time', models.CharField(blank=True, max_length=10000, null=True)), 46 | ('on_working', models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True)), 47 | ('off_working', models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True)), 48 | ('fun_area_time', models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True)), 49 | ('active', models.BooleanField(default=True)), 50 | ('exception', models.BooleanField(default=False)), 51 | ('comment', models.CharField(blank=True, max_length=10000, null=True)), 52 | ('Employee', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='Activity_Tracking_Web_App.Employee')), 53 | ], 54 | ), 55 | ] 56 | -------------------------------------------------------------------------------- /Activity_Tracking_Web_App/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammedSamirMahmoud/Attendance-Tracking-System-Using-Computer-Vision/bc737bd76867f93a38b0bbae62d746f872d02cfc/Activity_Tracking_Web_App/migrations/__init__.py -------------------------------------------------------------------------------- /Activity_Tracking_Web_App/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from datetime import datetime 3 | import os 4 | 5 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 6 | # Create your models here. 7 | 8 | 9 | class Employee(models.Model): 10 | name = models.CharField(max_length=200) 11 | 12 | def __str__(self): 13 | return self.name 14 | 15 | 16 | class Activity(models.Model): 17 | Employee = models.ForeignKey(Employee, on_delete=models.DO_NOTHING) 18 | date = models.DateField(default=datetime.now) 19 | arrival_time = models.CharField(max_length=10000, blank=True, null=True) 20 | depart_time = models.CharField(max_length=10000, blank=True, null=True) 21 | on_working = models.DecimalField( 22 | max_digits=5, decimal_places=2, blank=True, null=True) 23 | off_working = models.DecimalField( 24 | max_digits=5, decimal_places=2, blank=True, null=True) 25 | fun_area_time = models.DecimalField( 26 | max_digits=5, decimal_places=2, blank=True, null=True) 27 | active = models.BooleanField(default=True) 28 | exception = models.BooleanField(default=False) 29 | comment = models.CharField(max_length=10000, blank=True, null=True) 30 | 31 | def Employee_name(self): 32 | return Employee.name 33 | 34 | 35 | def content_file_name(instance, filename): 36 | filename, ext = filename.split('.') 37 | file_path = 'photos/' + '{name}/user_{user_id}.{filename}.{ext}'.format( 38 | name=instance.Employee.name, user_id=instance.Employee.id, filename=filename, ext=ext) 39 | return file_path 40 | 41 | 42 | class Picture(models.Model): 43 | Employee = models.ForeignKey(Employee, on_delete=models.DO_NOTHING) 44 | pic = models.ImageField(upload_to=content_file_name, blank=True, null=True) 45 | 46 | def employee(self): 47 | return self.Employee.name 48 | 49 | def test_content_file_name(instance, filename): 50 | filename, ext = filename.split('.') 51 | file_path = 'testing/' + '{filename}.{ext}'.format( filename=filename, ext=ext) 52 | return file_path 53 | 54 | 55 | 56 | class Test(models.Model): 57 | model_pic = models.ImageField(upload_to =test_content_file_name, blank=True, null= True) -------------------------------------------------------------------------------- /Activity_Tracking_Web_App/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /Activity_Tracking_Web_App/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /Attendance_Logic_Module/clean_data.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | def clean_class(df_emp, confidence_interval = 5): 4 | 5 | doubted_entry = None 6 | confirmed_entry = None 7 | confidence_level = confidence_interval 8 | location = 0 9 | counter = 0 10 | first_entry = True 11 | clean_df = pd.DataFrame(columns= df_emp.columns.tolist()) 12 | 13 | for index, row in df_emp.iterrows(): 14 | 15 | if(first_entry == True): 16 | doubted_entry = row 17 | first_entry = False 18 | counter = counter + 1 19 | continue 20 | 21 | 22 | if(row['unified_id'] == doubted_entry['unified_id']): 23 | confidence_level = confidence_level - 1 24 | 25 | if((counter == len(df_emp.index) - 1) and confidence_level <= 0): 26 | confirmed_entry = doubted_entry 27 | clean_df.loc[location] = confirmed_entry.tolist() 28 | 29 | elif(row['unified_id'] != doubted_entry['unified_id'] and confidence_level <= 0): 30 | confirmed_entry = doubted_entry 31 | clean_df.loc[location] = confirmed_entry.tolist() 32 | 33 | location = location + 1 34 | doubted_entry = row 35 | confidence_level = confidence_interval 36 | else: 37 | doubted_entry = row 38 | confidence_level = confidence_interval 39 | 40 | counter = counter + 1 41 | 42 | return clean_df 43 | 44 | -------------------------------------------------------------------------------- /Attendance_Logic_Module/logic.py: -------------------------------------------------------------------------------- 1 | from clean_data import clean_class 2 | import pandas as pd 3 | 4 | 5 | for x in range(1, 5): 6 | globals()['data%s' % x] = pd.read_csv('test' + str(x) + '.csv', encoding ="latin1") 7 | # Concatanete them 8 | df = pd.concat([data1, data2 ,data3, data4]) 9 | df = df.sort_values(['employee_name' , 'timestamp', 'camera_id']) 10 | df['unified_id'] = df['camera_id'] 11 | cols = df.columns.tolist() 12 | cols = cols[-1:] + cols[:-1] 13 | df = df[cols] 14 | 15 | df['unified_id'] = df['unified_id'].replace(2, 1) 16 | df['unified_id'] = df['unified_id'].replace(4, 3) 17 | ####df['unified_id'] = df['unified_id'].replace(6, 5) 18 | 19 | 20 | ####temp = DataFrame(entry) 21 | ####df = df.append(temp) 22 | ####df.to_csv('final.csv', index = False) 23 | 24 | 25 | 26 | entries = {'employee_name': [], 27 | 'arrival_time': [], 28 | 'depart_time':[], 29 | 'on_working':[], 30 | 'off_working':[], 31 | 'fun_area_time':[] 32 | } 33 | 34 | entries_df = pd.DataFrame(entries) 35 | 36 | #df.to_csv('final.csv', index = False) 37 | 38 | location = 0 39 | for name in df.employee_name.unique(): 40 | 41 | df_emp = df[df['employee_name'] == name] 42 | df_emp = clean_class(df_emp) 43 | df_emp = df_emp.groupby((df_emp['unified_id'] != df_emp['unified_id'].shift()).cumsum().values).first() 44 | 45 | first_seen = -1 46 | last_seen = -1 47 | 48 | employee_data = {'entrance':0.0, 49 | 'exit': 0.0, 50 | 'on_working':0.0, 51 | 'off_working':0.0 52 | } 53 | 54 | for index, row in df_emp.iterrows(): 55 | 56 | if(row['unified_id'] == 1): 57 | if(first_seen == -1): 58 | first_seen = row['timestamp'] 59 | 60 | if(employee_data['entrance'] == 0): 61 | employee_data['entrance'] = row['timestamp'] 62 | if(employee_data['exit'] != 0): 63 | employee_data['off_working'] = employee_data['off_working'] + (employee_data['entrance'] - employee_data['exit']) 64 | employee_data['exit'] = 0 65 | else: 66 | continue 67 | 68 | 69 | 70 | elif(row['unified_id'] == 3): 71 | if(employee_data['entrance'] != 0): 72 | employee_data['exit'] = row['timestamp'] 73 | employee_data['on_working'] = employee_data['on_working'] + (employee_data['exit'] - employee_data['entrance']) 74 | last_seen = employee_data['exit'] 75 | employee_data['entrance'] = 0 76 | ######################################### 77 | entry = [name, first_seen, last_seen, employee_data['on_working'], employee_data['off_working'], 0] 78 | entries_df.loc[location] = entry 79 | location = location + 1 80 | 81 | entries_df.to_csv('result.csv', index = False) 82 | ########################################## -------------------------------------------------------------------------------- /Attendance_Logic_Module/result.csv: -------------------------------------------------------------------------------- 1 | employee_name,arrival_time,depart_time,on_working,off_working,fun_area_time 2 | Employee6,56.22033898,453.1666667,383.9463278,12.99999997,0 3 | Employee4,52.3559322,131.3666667,79.0107345,75.87062144,0 4 | Employee5,31.96666667,501.9666667,470,0,0 5 | Employee3,-1,-1,0,0,0 6 | Employee7,67.50847458,188.7666667,121.2581921,0,0 7 | Employee1,7,372.7666667,287.3073447,234.8960451,0 8 | Employee8,-1,-1,0,0,0 9 | Employee2,8.966666667,372.1666667,286.861582,76.33841805,0 10 | Employee9,-1,-1,0,0,0 11 | -------------------------------------------------------------------------------- /Attendance_Logic_Module/test1.csv: -------------------------------------------------------------------------------- 1 | camera_id,timestamp,employee_name,confidence,x,y,width,height 2 | 1,7,Employee1,0.999078266,716,315,31,37 3 | 1,7.305084746,Employee1,0.956679531,749,309,31,40 4 | 1,21.03389831,Employee1,0.999999534,632,282,31,43 5 | 1,21.13559322,Employee1,0.976714181,623,284,29,38 6 | 1,21.54237288,Employee1,0.999328495,578,281,33,45 7 | 1,21.6440678,Employee1,0.999273791,569,274,36,50 8 | 1,21.74576271,Employee1,0.986837205,563,275,35,44 9 | 1,21.84745763,Employee1,0.999999894,554,274,36,48 10 | 1,21.94915254,Employee1,0.99999993,542,277,37,49 11 | 1,22.05084746,Employee1,0.99999991,531,275,38,51 12 | 1,22.15254237,Employee1,0.999999938,529,273,38,50 13 | 1,22.25423729,Employee1,0.999999912,535,272,39,50 14 | 1,22.3559322,Employee1,0.999999916,545,278,40,51 15 | 1,22.45762712,Employee1,0.999999902,559,281,41,53 16 | 1,22.55932203,Employee1,0.999999905,579,277,42,53 17 | 1,22.66101695,Employee1,0.999999923,596,269,43,55 18 | 1,22.76271186,Employee1,0.9876532,610,262,43,55 19 | 1,22.86440678,Employee1,0.995136169,623,260,43,55 20 | 1,22.96610169,Employee1,0.999999909,635,263,45,58 21 | 1,23.06779661,Employee1,0.999999915,649,268,46,60 22 | 1,23.16949153,Employee1,0.999993519,666,264,48,58 23 | 1,23.27118644,Employee1,0.999999897,684,254,50,62 24 | 1,23.37288136,Employee1,0.999997904,713,251,49,62 25 | 1,23.47457627,Employee1,0.999998929,742,250,54,72 26 | 1,23.57627119,Employee1,0.999999922,783,253,53,72 27 | 1,23.6779661,Employee1,0.999999288,826,249,55,72 28 | 1,23.77966102,Employee1,0.97762252,867,238,59,77 29 | 1,23.88135593,Employee1,0.999999646,901,228,60,81 30 | 1,23.98305085,Employee1,0.999446975,938,232,62,81 31 | 1,24.08474576,Employee1,0.999999913,975,239,65,88 32 | 1,24.18644068,Employee1,0.999999662,1018,237,68,92 33 | 1,24.38983051,Employee1,0.977985147,1117,212,71,93 34 | 1,24.49152542,Employee1,0.953519636,1176,209,74,93 35 | 1,24.69491525,Employee3,0.999698361,1177,219,66,88 36 | 1,52.3559322,Employee4,0.985966835,116,279,33,41 37 | 1,53.16949153,Employee1,0.973349199,259,259,37,47 38 | 1,53.77966102,Employee4,0.997597881,380,249,40,54 39 | 1,54.49152542,Employee1,0.972923242,581,246,49,64 40 | 1,54.69491525,Employee4,0.99451365,644,241,53,70 41 | 1,54.79661017,Employee4,0.999902155,679,230,55,71 42 | 1,54.89830508,Employee4,0.999974558,720,223,56,72 43 | 1,55.10169492,Employee4,0.972426822,819,238,58,75 44 | 1,55.30508475,Employee4,0.999339695,923,216,63,85 45 | 1,55.40677966,Employee4,0.999456892,973,200,65,89 46 | 1,55.61016949,Employee4,0.960899681,1089,204,70,93 47 | 1,56.22033898,Employee6,0.966024923,511,278,38,49 48 | 1,56.42372881,Employee6,0.992991422,500,266,39,50 49 | 1,56.72881356,Employee6,0.953771109,502,272,41,53 50 | 1,56.83050847,Employee6,0.997661808,504,268,44,58 51 | 1,56.93220339,Employee6,0.994757492,507,265,44,55 52 | 1,57.13559322,Employee6,0.986275003,508,263,44,59 53 | 1,57.23728814,Employee6,0.970998655,506,267,45,59 54 | 1,57.74576271,Employee6,0.988983594,556,260,53,68 55 | 1,57.84745763,Employee6,0.999874913,576,264,55,71 56 | 1,57.94915254,Employee6,0.999992564,594,259,55,71 57 | 1,58.05084746,Employee6,0.998205586,603,255,54,70 58 | 1,58.15254237,Employee6,0.999998958,600,256,52,67 59 | 1,58.66101695,Employee6,0.997580745,582,250,53,72 60 | 1,67.50847458,Employee7,0.980465505,515,308,36,46 61 | 1,68.83050847,Employee8,0.999216568,651,290,49,63 62 | 1,69.33898305,Employee8,0.995592454,863,281,53,71 63 | 1,69.54237288,Employee8,0.999274693,948,283,57,78 64 | 1,80.01694915,Employee7,0.982140842,370,298,34,44 65 | 1,80.11864407,Employee7,0.990228816,366,300,34,44 66 | 1,80.3220339,Employee7,0.993708504,350,302,37,49 67 | 1,80.72881356,Employee7,0.993119717,327,298,40,52 68 | 1,80.83050847,Employee7,0.999992651,321,301,40,52 69 | 1,80.93220339,Employee7,0.983582502,317,304,39,53 70 | 1,81.13559322,Employee7,0.999802151,316,296,40,54 71 | 1,81.23728814,Employee7,0.986778229,322,293,42,57 72 | 1,81.33898305,Employee7,0.990681695,332,296,42,56 73 | 1,81.44067797,Employee7,0.999967514,348,302,40,55 74 | 1,81.54237288,Employee7,0.988409971,366,299,40,55 75 | 1,81.6440678,Employee7,0.998079051,387,295,40,55 76 | 1,81.74576271,Employee7,0.999508724,405,292,42,56 77 | 1,81.84745763,Employee7,0.998514567,426,292,40,53 78 | 1,81.94915254,Employee7,0.980529855,443,294,40,56 79 | 1,82.15254237,Employee6,0.987586582,303,279,39,47 80 | 1,82.15254237,Employee7,0.999999614,474,302,47,62 81 | 1,82.25423729,Employee6,0.998853948,300,276,39,50 82 | 1,82.25423729,Employee7,0.999999769,498,299,45,60 83 | 1,82.3559322,Employee6,0.993034455,298,276,38,50 84 | 1,82.3559322,Employee7,0.999950018,511,288,51,68 85 | 1,82.45762712,Employee6,0.999907345,297,277,41,52 86 | 1,82.45762712,Employee7,0.999999885,539,291,46,59 87 | 1,82.55932203,Employee6,0.960529688,295,277,40,51 88 | 1,82.55932203,Employee7,0.999999634,564,290,46,59 89 | 1,82.66101695,Employee6,0.990841725,295,274,40,51 90 | 1,82.66101695,Employee7,0.999599406,590,295,46,60 91 | 1,82.76271186,Employee6,0.986722447,299,273,40,51 92 | 1,82.86440678,Employee6,0.998647546,306,274,41,53 93 | 1,82.86440678,Employee7,0.999999715,646,294,54,77 94 | 1,82.96610169,Employee6,0.997619918,319,277,42,55 95 | 1,83.06779661,Employee6,0.999049875,339,278,42,56 96 | 1,83.06779661,Employee7,0.999864111,712,281,54,76 97 | 1,83.16949153,Employee6,0.96197714,363,273,43,58 98 | 1,83.16949153,Employee1,0.983889101,16,298,29,36 99 | 1,83.16949153,Employee7,0.999995999,745,281,53,74 100 | 1,83.27118644,Employee6,0.998842488,380,270,43,57 101 | 1,83.37288136,Employee6,0.999868919,395,267,43,57 102 | 1,83.47457627,Employee6,0.999864726,408,268,45,58 103 | 1,83.57627119,Employee6,0.999353402,420,272,46,62 104 | 1,83.57627119,Employee7,0.999954786,904,293,56,75 105 | 1,83.6779661,Employee1,0.950258202,96,300,30,36 106 | 1,83.77966102,Employee6,0.980980533,445,269,48,63 107 | 1,83.77966102,Employee1,0.987874284,112,303,30,38 108 | 1,83.98305085,Employee1,0.962936031,145,307,30,37 109 | 1,84.08474576,Employee2,0.974036406,164,298,31,39 110 | 1,84.08474576,Employee6,0.966911565,511,258,51,67 111 | 1,84.28813559,Employee2,0.952871058,205,302,32,40 112 | 1,84.49152542,Employee6,0.976404198,644,249,54,70 113 | 1,84.69491525,Employee6,0.998942298,702,255,56,73 114 | 1,84.79661017,Employee6,0.999548302,732,255,60,78 115 | 1,84.89830508,Employee6,0.992726906,770,250,59,78 116 | 1,85,Employee6,0.999963059,804,238,63,85 117 | 1,85.10169492,Employee2,0.998239119,395,292,35,44 118 | 1,85.10169492,Employee6,0.999075704,843,231,66,93 119 | 1,85.20338983,Employee2,0.992435428,420,292,36,45 120 | 1,85.20338983,Employee6,0.999978368,886,231,67,95 121 | 1,85.30508475,Employee2,0.965773725,449,299,35,46 122 | 1,85.30508475,Employee6,0.999990052,935,234,70,96 123 | 1,85.40677966,Employee2,0.997132564,479,303,36,47 124 | 1,85.40677966,Employee6,0.999782854,990,231,76,99 125 | 1,85.50847458,Employee6,0.998866785,1046,218,77,103 126 | 1,85.61016949,Employee2,0.999999937,536,291,37,49 127 | 1,85.71186441,Employee2,0.999999822,563,291,39,51 128 | 1,85.81355932,Employee2,0.995492134,592,299,40,52 129 | 1,85.91525424,Employee2,0.980548014,624,302,41,51 130 | 1,86.01694915,Employee2,0.999317503,657,293,42,54 131 | 1,86.3220339,Employee3,0.975882707,763,296,45,56 132 | 1,86.52542373,Employee2,0.96017783,845,291,47,60 133 | 1,86.62711864,Employee2,0.999999712,888,282,48,59 134 | 1,86.72881356,Employee2,0.996821912,926,280,50,65 135 | 1,86.93220339,Employee2,0.999999739,1012,296,54,69 136 | 1,87.03389831,Employee2,0.999998358,1058,285,56,72 137 | 1,87.13559322,Employee2,0.989030337,1105,272,58,75 138 | 1,87.23728814,Employee2,0.99876252,1157,271,60,80 139 | 1,87.33898305,Employee2,0.997798796,1212,280,63,86 140 | 1,100.6610169,Employee1,0.980308724,583,282,32,43 141 | 1,119.2711864,Employee4,0.991132237,71,276,28,37 142 | 1,120.2881356,Employee2,0.965040994,188,276,33,43 143 | 1,120.7966102,Employee7,0.974642131,259,277,33,40 144 | 1,121.7118644,Employee4,0.985204081,407,260,35,44 145 | 1,123.1355932,Employee3,0.999989515,426,254,37,52 146 | 1,124.4576271,Employee2,0.993493419,508,245,47,59 147 | 1,124.559322,Employee4,0.969433422,524,244,46,59 148 | 1,124.7627119,Employee4,0.999966269,554,249,49,62 149 | 1,124.9661017,Employee4,0.998910554,589,238,51,64 150 | 1,125.1694915,Employee4,0.989169736,607,239,52,63 151 | 1,125.4745763,Employee4,0.99518654,610,237,51,65 152 | 1,125.5762712,Employee4,0.999761252,602,232,52,66 153 | 1,125.779661,Employee4,0.997768174,582,231,53,69 154 | 1,125.8813559,Employee4,0.999993886,572,233,54,69 155 | 1,125.9830508,Employee4,0.998901293,567,240,44,62 156 | 1,185.8813559,Employee1,0.958673352,502,286,32,45 157 | 1,186.0847458,Employee1,0.97211458,456,275,34,44 158 | 1,186.4915254,Employee1,0.997082595,361,281,34,41 159 | 1,186.6949153,Employee1,0.964597947,305,272,33,40 160 | 1,196.2542373,Employee1,0.980871633,97,281,28,35 161 | 1,196.559322,Employee1,0.996011956,140,285,28,37 162 | 1,196.6610169,Employee1,0.996445485,150,280,29,38 163 | 1,196.7627119,Employee1,0.999999799,159,278,28,37 164 | 1,196.8644068,Employee1,0.999999915,165,280,30,40 165 | 1,196.9661017,Employee1,0.997497634,172,286,31,41 166 | 1,197.0677966,Employee1,0.997962317,176,288,30,39 167 | 1,197.1694915,Employee1,0.99502546,185,283,31,40 168 | 1,197.2711864,Employee1,0.999992333,194,274,36,46 169 | 1,197.3728814,Employee1,0.998821691,210,276,31,40 170 | 1,197.4745763,Employee1,0.980214044,227,280,32,41 171 | 1,198.2881356,Employee1,0.993452926,373,276,34,47 172 | 1,198.3898305,Employee1,0.997025571,394,270,35,47 173 | 1,198.4915254,Employee1,0.999999581,419,266,36,48 174 | 1,205.3050847,Employee2,0.970659217,546,305,34,45 175 | 1,205.4067797,Employee2,0.999999986,528,309,34,44 176 | 1,205.6101695,Employee2,0.999999849,502,296,38,48 177 | 1,205.8135593,Employee2,0.998996369,497,296,39,50 178 | 1,205.9152542,Employee2,0.999999986,509,303,37,49 179 | 1,206.0169492,Employee2,0.997565684,522,301,35,52 180 | 1,206.1186441,Employee2,0.98192395,534,297,38,53 181 | 1,206.220339,Employee2,0.958372326,550,294,36,53 182 | 1,206.9322034,Employee2,0.999999979,675,290,53,68 183 | 1,207.0338983,Employee2,0.999999973,708,298,57,71 184 | 1,207.1355932,Employee2,0.999999983,744,295,57,70 185 | 1,207.1355932,Employee1,0.962169274,509,250,41,55 186 | 1,207.2372881,Employee2,0.999999984,775,282,58,71 187 | 1,207.2372881,Employee4,0.987557629,511,250,43,57 188 | 1,207.3389831,Employee2,0.999258992,802,277,58,72 189 | 1,207.3389831,Employee4,0.992203831,517,249,44,61 190 | 1,207.440678,Employee2,0.999999979,826,281,60,79 191 | 1,207.5423729,Employee2,0.99999998,857,293,63,81 192 | 1,207.6440678,Employee2,0.99999993,886,290,63,80 193 | 1,207.7457627,Employee2,0.999999978,918,272,67,85 194 | 1,207.8474576,Employee4,0.994836754,592,240,47,60 195 | 1,207.8474576,Employee2,0.999999979,957,258,71,91 196 | 1,207.9491525,Employee4,0.983125066,609,242,51,64 197 | 1,208.1525424,Employee2,0.999999985,1111,272,89,109 198 | 1,208.2542373,Employee4,0.999991153,679,232,56,71 199 | 1,208.2542373,Employee2,0.999999984,1173,255,92,111 200 | 1,208.559322,Employee4,0.99947021,785,231,61,77 201 | 1,208.7627119,Employee4,0.999991774,873,218,66,89 202 | 1,208.8644068,Employee4,0.999962065,915,199,68,91 203 | 1,209.0677966,Employee4,0.992681772,1001,194,74,95 204 | 1,209.1694915,Employee4,0.984452644,1050,194,77,101 205 | 1,209.2711864,Employee4,0.968402325,1097,191,81,106 206 | 1,209.3728814,Employee4,0.95757687,1138,170,86,116 207 | 1,227.5762712,Employee1,0.998890575,571,273,33,46 208 | 1,227.8813559,Employee1,0.983205432,551,276,35,48 209 | 1,227.9830508,Employee1,0.966319703,547,283,37,50 210 | 1,228.0847458,Employee1,0.999999392,546,290,38,51 211 | 1,228.1864407,Employee1,0.999999843,551,288,40,52 212 | 1,228.4915254,Employee1,0.96946056,614,284,42,54 213 | 1,228.6949153,Employee1,0.998919553,673,274,48,62 214 | 1,228.7966102,Employee1,0.986549103,703,270,40,50 215 | 1,228.8983051,Employee1,0.99683541,722,260,46,58 216 | 1,229.1016949,Employee1,0.970451176,772,270,48,61 217 | 1,229.2033898,Employee1,0.999345439,797,266,53,67 218 | 1,229.3050847,Employee1,0.999125864,831,256,52,67 219 | 1,229.4067797,Employee1,0.999998594,871,242,53,72 220 | 1,229.6101695,Employee1,0.968781862,963,245,58,81 221 | 1,229.8135593,Employee1,0.999999865,1072,239,62,86 222 | 1,229.9152542,Employee1,0.992455171,1121,222,66,89 223 | 1,230.0169492,Employee1,0.98988064,1170,221,66,89 224 | 1,257.3728814,Employee4,0.967702146,0,276,27,35 225 | 1,257.5762712,Employee4,0.986446517,30,283,29,37 226 | 1,257.779661,Employee4,0.974551838,56,274,30,39 227 | 1,258.0847458,Employee4,0.998917959,94,278,29,39 228 | 1,258.2881356,Employee4,0.999794746,121,273,29,41 229 | 1,258.3898305,Employee4,0.999878317,137,269,30,42 230 | 1,258.5932203,Employee4,0.999914258,175,274,31,42 231 | 1,258.6949153,Employee4,0.9986796,198,277,30,40 232 | 1,372.3898305,Employee1,0.991233191,11,299,27,35 233 | 1,375.2372881,Employee1,0.985778206,73,286,28,36 234 | 1,375.3389831,Employee1,0.996151714,82,290,28,36 235 | 1,375.440678,Employee1,0.974093887,94,287,28,37 236 | 1,375.5423729,Employee1,0.959539124,109,281,27,36 237 | 1,375.8474576,Employee1,0.981459878,148,282,29,40 238 | 1,376.0508475,Employee1,0.992225076,175,279,25,36 239 | 1,446.5254237,Employee1,0.998414823,19,286,30,40 240 | 1,457.2033898,Employee1,0.97604858,355,285,33,46 241 | 1,471.0338983,Employee1,0.977779249,78,317,25,34 242 | 1,500.7288136,Employee5,0.959401138,22,289,27,36 243 | 1,500.9322034,Employee5,0.998721992,56,282,27,36 244 | 1,501.0338983,Employee5,0.997673781,71,280,28,37 245 | 1,501.1355932,Employee5,0.950552068,85,283,28,38 246 | 1,501.2372881,Employee5,0.956045857,103,289,25,35 247 | 1,501.440678,Employee5,0.973544749,134,283,27,38 248 | 1,529.2033898,Employee1,0.969999237,50,220,45,70 249 | 1,529.3050847,Employee1,0.999269521,60,224,41,61 250 | 1,529.4067797,Employee1,0.998129043,71,223,42,64 251 | 1,529.5084746,Employee1,0.99035039,92,231,37,50 252 | 1,530.8305085,Employee1,0.999994217,462,226,54,67 253 | 1,530.9322034,Employee1,0.958172328,482,229,56,69 254 | 1,531.1355932,Employee1,0.95651877,521,237,59,75 255 | 1,531.2372881,Employee1,0.991976486,531,228,62,78 256 | -------------------------------------------------------------------------------- /Attendance_Logic_Module/test2.csv: -------------------------------------------------------------------------------- 1 | camera_id,timestamp,employee_name,confidence,x,y,width,height 2 | 2,8.966666667,Employee2,0.996485677,735,70,27,34 3 | 2,13.16666667,Employee3,0.977232312,116,79,91,105 4 | 2,21.36666667,Employee1,0.979274497,791,50,28,37 5 | 2,31.96666667,Employee5,0.987617751,704,60,22,30 6 | 2,32.16666667,Employee5,0.956574011,706,63,22,30 7 | 2,32.56666667,Employee5,0.992334431,711,59,25,34 8 | 2,32.76666667,Employee5,0.996045646,718,57,24,32 9 | 2,32.96666667,Employee5,0.992509858,733,60,26,35 10 | 2,33.16666667,Employee5,0.998667887,749,53,27,37 11 | 2,33.36666667,Employee5,0.981367896,755,46,27,39 12 | 2,33.56666667,Employee5,0.999998621,752,52,30,41 13 | 2,33.76666667,Employee5,0.986442771,740,53,28,40 14 | 2,42.56666667,Employee9,0.995766473,703,87,28,37 15 | 2,62.16666667,Employee6,0.994086037,986,31,39,47 16 | 2,62.36666667,Employee6,0.950349918,963,33,37,44 17 | 2,62.56666667,Employee6,0.98708377,937,32,35,46 18 | 2,75.76666667,Employee6,0.997844991,710,34,38,50 19 | 2,75.96666667,Employee6,0.998275275,711,31,38,52 20 | 2,76.36666667,Employee6,0.999649947,714,36,37,50 21 | 2,76.56666667,Employee6,0.990911953,714,38,38,50 22 | 2,76.76666667,Employee6,0.996193446,709,38,40,53 23 | 2,76.96666667,Employee6,0.997462657,707,42,39,47 24 | 2,77.16666667,Employee6,0.959330783,703,43,39,49 25 | 2,126.3666667,Employee1,0.989566697,1034,26,29,35 26 | 2,129.5666667,Employee7,0.99668104,403,82,56,67 27 | 2,185.9666667,Employee3,0.99338774,671,22,47,56 28 | 2,188.3666667,Employee6,0.999980633,682,37,40,50 29 | 2,188.5666667,Employee6,0.999329313,685,34,40,52 30 | 2,189.7666667,Employee6,0.999861528,593,32,51,63 31 | 2,190.1666667,Employee6,0.99999643,563,24,54,69 32 | 2,190.3666667,Employee6,0.999548761,531,29,58,71 33 | 2,191.1666667,Employee6,0.999989342,345,32,71,86 34 | 2,191.3666667,Employee6,0.982781528,306,22,79,96 35 | 2,201.9666667,Employee1,0.957181093,683,83,21,28 36 | 2,224.3666667,Employee5,0.956431366,709,57,23,30 37 | 2,224.5666667,Employee5,0.973016497,706,59,24,32 38 | -------------------------------------------------------------------------------- /Attendance_Logic_Module/test3.csv: -------------------------------------------------------------------------------- 1 | camera_id,timestamp,employee_name,confidence,x,y,width,height 2 | 3,79.36666667,Employee1,0.958999874,536,242,27,34 3 | 3,79.76666667,Employee1,0.999999155,538,228,30,39 4 | 3,80.76666667,Employee1,0.980880238,625,221,44,54 5 | 3,81.36666667,Employee1,0.999986619,774,208,60,75 6 | 3,81.56666667,Employee1,0.999238159,848,182,68,86 7 | 3,130.3666667,Employee1,0.995503982,685,275,24,30 8 | 3,130.7666667,Employee1,0.992273754,682,290,27,33 9 | 3,133.5666667,Employee4,0.987319286,668,253,42,53 10 | 3,133.9666667,Employee4,0.979703483,696,290,48,61 11 | 3,174.5666667,Employee1,0.98895786,536,299,26,35 12 | 3,174.7666667,Employee1,0.962626913,554,303,30,38 13 | 3,175.1666667,Employee1,0.965532067,564,294,33,41 14 | 3,175.9666667,Employee1,0.986720203,642,290,42,53 15 | 3,176.1666667,Employee1,0.999999868,667,285,45,59 16 | 3,176.3666667,Employee1,0.999999755,690,271,49,64 17 | 3,176.5666667,Employee1,0.999999944,731,257,54,71 18 | 3,176.7666667,Employee1,0.999999937,775,267,54,78 19 | 3,176.9666667,Employee6,0.999940039,595,294,28,36 20 | 3,178.9666667,Employee6,0.967156653,734,279,36,44 21 | 3,180.1666667,Employee6,0.999937048,820,279,44,57 22 | 3,180.3666667,Employee6,0.999505547,823,278,45,58 23 | 3,180.5666667,Employee6,0.99974868,824,274,45,59 24 | 3,180.7666667,Employee6,0.998861775,810,274,47,61 25 | 3,187.9666667,Employee1,0.9794706,618,280,23,29 26 | 3,190.3666667,Employee7,0.998853725,793,314,53,67 27 | 3,190.5666667,Employee7,0.998644634,860,314,60,73 28 | 3,199.7666667,Employee1,0.999999882,485,225,29,37 29 | 3,199.9666667,Employee1,0.999998631,477,235,29,37 30 | 3,200.1666667,Employee1,0.99851821,479,226,30,40 31 | 3,201.3666667,Employee1,0.996903229,575,215,46,55 32 | 3,201.5666667,Employee1,0.999999925,600,217,51,68 33 | 3,201.7666667,Employee1,0.999998224,640,197,56,70 34 | 3,201.9666667,Employee1,0.999098548,707,211,59,77 35 | 3,202.1666667,Employee1,0.997661227,803,194,69,92 36 | 3,260.5666667,Employee4,0.99907525,745,280,47,59 37 | 3,373.9666667,Employee1,0.967227155,542,289,22,27 38 | 3,375.5666667,Employee1,0.991842675,559,257,24,31 39 | 3,375.7666667,Employee1,0.999998433,560,245,28,37 40 | 3,375.9666667,Employee1,0.999999827,565,249,28,37 41 | 3,376.1666667,Employee2,0.980550732,701,260,41,51 42 | 3,376.1666667,Employee1,0.992845605,565,247,29,36 43 | 3,376.5666667,Employee1,0.969848526,592,248,34,41 44 | 3,376.7666667,Employee1,0.992610149,612,231,36,47 45 | 3,376.9666667,Employee1,0.999941155,627,239,41,53 46 | 3,377.1666667,Employee1,0.98668307,647,225,45,58 47 | 3,377.3666667,Employee1,0.999999909,682,221,51,65 48 | 3,377.5666667,Employee1,0.999999939,748,224,56,72 49 | 3,377.7666667,Employee1,0.9999999,812,194,62,80 50 | 3,377.9666667,Employee1,0.996397005,881,208,72,92 51 | 3,454.7666667,Employee6,0.987447025,563,237,27,36 52 | 3,454.9666667,Employee6,0.998973551,564,239,29,37 53 | 3,455.3666667,Employee6,0.984769595,565,231,31,40 54 | 3,455.5666667,Employee6,0.998552179,557,229,33,42 55 | 3,456.3666667,Employee6,0.967814411,588,231,32,38 56 | 3,456.5666667,Employee6,0.970188604,587,228,33,41 57 | 3,456.7666667,Employee6,0.998596017,587,227,33,40 58 | 3,457.3666667,Employee6,0.951436335,589,228,31,38 59 | 3,457.9666667,Employee6,0.993673281,612,227,33,41 60 | 3,458.1666667,Employee6,0.991616562,621,228,35,44 61 | 3,458.9666667,Employee6,0.980815855,690,217,40,52 62 | 3,459.1666667,Employee6,0.999085792,711,214,42,56 63 | 3,459.3666667,Employee6,0.999977656,735,225,45,56 64 | 3,459.5666667,Employee6,0.999450177,763,212,48,63 65 | 3,459.7666667,Employee6,0.999841941,803,207,51,66 66 | 3,459.9666667,Employee6,0.999904014,861,212,57,74 67 | 3,460.1666667,Employee6,0.999999133,918,200,63,81 68 | 3,487.1666667,Employee9,0.999999222,726,259,32,43 69 | 3,487.5666667,Employee9,0.991094585,765,263,37,50 70 | 3,487.7666667,Employee9,0.999999871,787,254,38,51 71 | 3,487.9666667,Employee9,0.999182955,807,263,42,56 72 | 3,488.1666667,Employee7,0.954935707,822,265,45,56 73 | 3,488.3666667,Employee9,0.999999999,833,260,48,60 74 | 3,488.5666667,Employee9,0.991783903,843,262,52,64 75 | 3,488.5666667,Employee3,0.992390593,606,255,31,38 76 | 3,488.7666667,Employee9,0.986237098,857,260,54,67 77 | 3,488.9666667,Employee9,0.999999979,877,258,55,70 78 | 3,489.1666667,Employee9,0.9999999,896,264,58,74 79 | 3,489.3666667,Employee9,0.99887768,920,266,59,72 80 | 3,489.5666667,Employee9,0.996240993,957,263,65,84 81 | 3,489.7666667,Employee7,0.972528438,695,256,46,57 82 | 3,490.5666667,Employee3,0.956698633,831,231,67,82 83 | 3,502.9666667,Employee5,0.967951394,576,257,24,31 84 | 3,503.1666667,Employee5,0.995277248,569,256,24,31 85 | 3,503.5666667,Employee5,0.994511786,580,258,27,34 86 | 3,503.9666667,Employee5,0.992620043,599,250,29,37 87 | 3,504.5666667,Employee5,0.992682823,650,244,37,50 88 | 3,504.7666667,Employee5,0.999999799,676,228,42,54 89 | 3,504.9666667,Employee5,0.999996365,702,229,48,62 90 | 3,505.1666667,Employee5,0.999919878,739,234,51,62 91 | 3,505.3666667,Employee5,0.962503483,794,204,59,71 92 | 3,524.5666667,Employee8,0.958777813,723,253,36,47 93 | -------------------------------------------------------------------------------- /Attendance_Logic_Module/test4.csv: -------------------------------------------------------------------------------- 1 | camera_id,timestamp,employee_name,confidence,x,y,width,height 2 | 4,78.36666667,Employee1,0.999999872,622,282,35,42 3 | 4,78.96666667,Employee1,0.965550911,546,284,38,48 4 | 4,79.36666667,Employee1,0.960040117,476,269,44,59 5 | 4,79.96666667,Employee1,0.999987316,338,271,69,89 6 | 4,128.9666667,Employee2,0.996439109,727,316,29,39 7 | 4,129.1666667,Employee2,0.974472318,727,315,32,42 8 | 4,129.3666667,Employee2,0.999999974,722,308,33,43 9 | 4,129.5666667,Employee2,0.997239513,705,319,36,47 10 | 4,129.7666667,Employee2,0.999999502,681,319,37,47 11 | 4,129.9666667,Employee2,0.999999984,665,312,40,50 12 | 4,130.1666667,Employee2,0.999999956,653,328,45,56 13 | 4,130.3666667,Employee2,0.999999979,634,318,48,58 14 | 4,130.3666667,Employee3,0.999715611,785,281,31,41 15 | 4,130.5666667,Employee2,0.99999932,605,331,52,66 16 | 4,130.7666667,Employee2,0.999999981,564,326,57,73 17 | 4,130.7666667,Employee3,0.997338652,729,274,31,39 18 | 4,130.9666667,Employee2,0.999999697,523,320,63,77 19 | 4,130.9666667,Employee3,0.99316832,690,278,32,41 20 | 4,131.1666667,Employee3,0.999612293,661,267,35,43 21 | 4,131.1666667,Employee2,0.999999816,475,341,73,95 22 | 4,131.3666667,Employee2,0.999999872,398,320,84,106 23 | 4,131.3666667,Employee4,0.997614109,638,278,37,44 24 | 4,131.5666667,Employee3,0.999984476,618,275,38,47 25 | 4,131.7666667,Employee2,0.999999965,94,339,136,172 26 | 4,131.9666667,Employee4,0.986945777,548,267,40,51 27 | 4,132.1666667,Employee4,0.999930042,500,259,43,54 28 | 4,132.5666667,Employee4,0.999447755,409,277,54,66 29 | 4,132.7666667,Employee4,0.999984343,354,270,60,75 30 | 4,172.9666667,Employee1,0.99277772,690,304,31,37 31 | 4,173.1666667,Employee5,0.957373896,725,297,26,34 32 | 4,173.3666667,Employee1,0.997465408,648,303,30,37 33 | 4,173.5666667,Employee1,0.999671729,646,302,34,44 34 | 4,174.9666667,Employee1,0.999378765,378,284,58,74 35 | 4,175.1666667,Employee1,0.995363015,320,272,62,81 36 | 4,175.3666667,Employee6,0.999998428,719,313,33,42 37 | 4,175.5666667,Employee1,0.999999911,290,279,73,95 38 | 4,175.5666667,Employee6,0.971898015,722,306,33,45 39 | 4,175.7666667,Employee1,0.999999945,315,287,68,91 40 | 4,175.9666667,Employee6,0.999971618,683,308,35,48 41 | 4,176.1666667,Employee6,0.999998082,663,302,38,49 42 | 4,176.3666667,Employee6,0.999969897,659,300,39,50 43 | 4,176.5666667,Employee6,0.999765696,666,300,42,53 44 | 4,176.7666667,Employee6,0.997213915,690,301,42,55 45 | 4,176.9666667,Employee6,0.999963327,716,302,42,54 46 | 4,177.1666667,Employee6,0.999999689,722,302,43,56 47 | 4,177.3666667,Employee6,0.99999967,721,299,43,59 48 | 4,177.5666667,Employee6,0.99999969,705,300,47,60 49 | 4,177.7666667,Employee6,0.999999692,687,296,49,68 50 | 4,178.7666667,Employee6,0.999990347,660,303,54,67 51 | 4,178.9666667,Employee6,0.999994905,639,300,58,74 52 | 4,179.1666667,Employee6,0.999999702,604,290,62,82 53 | 4,179.3666667,Employee6,0.999999405,572,289,60,77 54 | 4,185.3666667,Employee3,0.998707026,764,344,26,33 55 | 4,185.5666667,Employee8,0.998703496,764,339,28,36 56 | 4,186.3666667,Employee8,0.997806797,752,358,29,36 57 | 4,186.5666667,Employee8,0.999999164,750,353,30,40 58 | 4,186.9666667,Employee8,0.999999478,702,354,33,42 59 | 4,187.3666667,Employee8,0.992884374,653,347,36,45 60 | 4,187.5666667,Employee8,0.999999937,642,345,38,47 61 | 4,187.7666667,Employee8,0.999999936,630,337,41,51 62 | 4,187.9666667,Employee8,0.999999931,605,340,44,55 63 | 4,188.5666667,Employee8,0.99999683,502,345,54,73 64 | 4,188.7666667,Employee7,0.9954713,468,344,61,80 65 | 4,189.1666667,Employee8,0.968514228,329,370,73,92 66 | 4,197.9666667,Employee1,0.99698922,716,252,31,39 67 | 4,199.3666667,Employee1,0.96273265,461,229,38,50 68 | 4,199.5666667,Employee1,0.967630177,437,219,41,52 69 | 4,199.9666667,Employee1,0.998273964,389,212,50,65 70 | 4,200.1666667,Employee1,0.983415769,350,216,53,67 71 | 4,200.5666667,Employee1,0.999999917,248,193,66,87 72 | 4,200.7666667,Employee1,0.999106125,205,212,72,92 73 | 4,259.3666667,Employee3,0.970940493,476,297,135,186 74 | 4,372.1666667,Employee2,0.96688019,749,284,28,37 75 | 4,372.3666667,Employee2,0.968224806,741,288,28,36 76 | 4,372.7666667,Employee1,0.975867413,716,296,29,36 77 | 4,372.9666667,Employee2,0.999999981,699,304,31,39 78 | 4,374.1666667,Employee1,0.988811864,739,273,31,38 79 | 4,374.3666667,Employee2,0.996206415,613,279,41,52 80 | 4,374.3666667,Employee1,0.999999925,717,268,31,42 81 | 4,374.5666667,Employee2,0.999999981,590,281,46,58 82 | 4,374.5666667,Employee1,0.992073181,684,255,36,43 83 | 4,374.7666667,Employee2,0.999999982,569,282,51,65 84 | 4,374.7666667,Employee1,0.95302107,651,263,37,45 85 | 4,374.9666667,Employee2,0.999999801,545,277,53,67 86 | 4,374.9666667,Employee1,0.970288631,621,249,38,48 87 | 4,375.1666667,Employee2,0.990433022,512,292,57,74 88 | 4,375.1666667,Employee1,0.984125804,595,255,40,47 89 | 4,375.3666667,Employee1,0.999958085,565,253,40,53 90 | 4,375.5666667,Employee1,0.99929344,528,236,45,57 91 | 4,375.5666667,Employee3,0.994082782,447,290,66,90 92 | 4,376.1666667,Employee1,0.987397145,351,234,54,63 93 | 4,376.5666667,Employee1,0.995122213,192,185,82,102 94 | 4,453.1666667,Employee6,0.999452003,768,239,31,42 95 | 4,453.3666667,Employee6,0.999727394,758,237,32,44 96 | 4,453.5666667,Employee6,0.999985339,749,239,33,44 97 | 4,453.7666667,Employee6,0.999999298,742,243,36,46 98 | 4,453.9666667,Employee6,0.99999333,731,238,34,45 99 | 4,454.1666667,Employee6,0.999759315,716,235,37,47 100 | 4,454.3666667,Employee6,0.99978175,698,236,37,48 101 | 4,454.5666667,Employee6,0.999998465,674,231,41,52 102 | 4,454.7666667,Employee6,0.999999697,673,232,42,52 103 | 4,454.9666667,Employee6,0.999982377,694,238,38,48 104 | 4,455.3666667,Employee6,0.996636602,721,239,38,48 105 | 4,455.5666667,Employee6,0.999919299,722,236,38,50 106 | 4,455.7666667,Employee6,0.999777424,724,237,39,48 107 | 4,455.9666667,Employee6,0.999992187,729,238,36,45 108 | 4,456.1666667,Employee6,0.999997811,730,236,39,49 109 | 4,456.3666667,Employee6,0.999936614,737,232,36,49 110 | 4,456.5666667,Employee6,0.999996153,739,237,40,50 111 | 4,456.7666667,Employee6,0.99827446,740,236,37,48 112 | 4,456.9666667,Employee6,0.999999458,723,233,44,55 113 | 4,457.1666667,Employee6,0.999922284,695,230,43,54 114 | 4,457.3666667,Employee6,0.999999444,673,225,47,60 115 | 4,457.5666667,Employee6,0.999982364,659,230,46,60 116 | 4,457.7666667,Employee6,0.999998446,652,224,51,65 117 | 4,457.9666667,Employee6,0.999999703,644,216,53,74 118 | 4,458.1666667,Employee6,0.999999711,616,230,56,74 119 | 4,458.3666667,Employee6,0.999999675,573,224,60,79 120 | 4,458.5666667,Employee6,0.999999712,540,211,63,85 121 | 4,458.7666667,Employee6,0.999999705,509,221,72,93 122 | 4,458.9666667,Employee6,0.999999406,471,204,80,108 123 | 4,459.1666667,Employee6,0.999679701,401,204,84,101 124 | 4,459.3666667,Employee6,0.999991596,290,214,104,121 125 | 4,484.9666667,Employee9,0.999999999,761,281,35,45 126 | 4,485.1666667,Employee9,0.999999978,757,281,35,46 127 | 4,485.1666667,Employee1,0.992490918,790,267,23,29 128 | 4,485.3666667,Employee9,1,753,276,38,48 129 | 4,485.5666667,Employee9,1,750,278,38,51 130 | 4,485.7666667,Employee9,0.999999825,741,290,43,55 131 | 4,485.7666667,Employee7,0.991061874,705,266,30,38 132 | 4,485.9666667,Employee9,0.999999978,733,283,44,58 133 | 4,486.1666667,Employee9,1,708,285,48,65 134 | 4,486.3666667,Employee9,1,668,295,48,64 135 | 4,486.5666667,Employee9,1,626,282,53,70 136 | 4,486.9666667,Employee9,1,536,299,57,80 137 | 4,487.1666667,Employee9,1,481,284,62,92 138 | 4,487.1666667,Employee7,0.999978263,630,270,37,50 139 | 4,487.3666667,Employee7,0.999999715,625,271,38,48 140 | 4,487.3666667,Employee9,1,442,284,60,98 141 | 4,487.5666667,Employee7,0.999999863,614,266,38,51 142 | 4,487.5666667,Employee9,1,410,290,65,92 143 | 4,487.7666667,Employee7,0.999993784,589,272,40,52 144 | 4,487.7666667,Employee9,1,366,282,78,106 145 | 4,487.9666667,Employee7,0.999998949,547,276,43,54 146 | 4,487.9666667,Employee9,0.997871803,330,293,72,98 147 | 4,488.1666667,Employee9,0.999999999,305,297,72,94 148 | 4,488.1666667,Employee7,0.99999903,505,258,46,64 149 | 4,488.3666667,Employee9,1,276,296,83,108 150 | 4,488.3666667,Employee7,0.999892925,462,265,50,67 151 | 4,488.5666667,Employee7,0.973097501,411,275,54,69 152 | 4,488.7666667,Employee9,0.999486465,183,300,99,122 153 | 4,488.9666667,Employee9,1,116,294,110,137 154 | 4,489.1666667,Employee9,0.967396985,10,305,131,168 155 | 4,489.3666667,Employee7,0.954072149,119,254,83,98 156 | 4,501.9666667,Employee5,0.999999809,773,260,33,43 157 | 4,502.1666667,Employee5,0.999999822,751,263,33,44 158 | 4,502.3666667,Employee5,0.999999502,735,267,36,45 159 | 4,502.5666667,Employee5,0.999999801,711,250,39,49 160 | 4,502.7666667,Employee5,0.999997544,678,256,39,51 161 | 4,502.9666667,Employee5,0.99999368,635,253,40,53 162 | 4,503.1666667,Employee5,0.999999823,600,235,43,59 163 | 4,503.3666667,Employee5,0.999999802,566,246,46,62 164 | 4,503.5666667,Employee5,0.999999792,526,236,52,69 165 | 4,503.7666667,Employee5,0.999999553,464,223,59,79 166 | 4,503.9666667,Employee5,0.999996664,386,241,61,80 167 | 4,504.1666667,Employee5,0.999999824,297,205,74,93 168 | 4,504.3666667,Employee5,0.980864865,215,205,81,104 169 | 4,520.7666667,Employee1,0.989536496,894,248,20,25 170 | 4,521.3666667,Employee8,0.99996216,859,266,31,38 171 | 4,521.9666667,Employee8,0.999999406,793,262,33,42 172 | 4,522.1666667,Employee8,0.999999717,784,258,35,46 173 | 4,522.3666667,Employee8,0.999999759,764,255,38,48 174 | 4,522.5666667,Employee8,0.999999933,732,263,36,48 175 | 4,522.7666667,Employee8,0.999999922,693,260,39,48 176 | 4,522.9666667,Employee8,0.999998081,664,262,41,52 177 | 4,523.1666667,Employee8,0.999996398,637,259,45,57 178 | 4,523.3666667,Employee8,0.999999881,605,250,48,62 179 | 4,523.5666667,Employee8,0.999999926,558,259,53,67 180 | 4,523.7666667,Employee8,0.999999922,496,258,59,71 181 | 4,523.9666667,Employee8,0.999999897,444,251,65,83 182 | 4,524.1666667,Employee8,0.999899682,387,264,68,85 183 | -------------------------------------------------------------------------------- /Attendance_Tracking_System_Using_Computer_Vision/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MohammedSamirMahmoud/Attendance-Tracking-System-Using-Computer-Vision/bc737bd76867f93a38b0bbae62d746f872d02cfc/Attendance_Tracking_System_Using_Computer_Vision/__init__.py -------------------------------------------------------------------------------- /Attendance_Tracking_System_Using_Computer_Vision/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for Attendance_Tracking_System_Using_Computer_Vision project. 3 | 4 | Generated by 'django-admin startproject' using Django 2.2.5. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.2/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/2.2/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'sb1t)*u#*t&n&eu5!v=^8b-7isi#c#^^cjp^-n0nv60au0(h8w' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 'Activity_Tracking_Web_App.apps.ActivityTrackingWebAppConfig' 41 | ] 42 | 43 | MIDDLEWARE = [ 44 | 'django.middleware.security.SecurityMiddleware', 45 | 'django.contrib.sessions.middleware.SessionMiddleware', 46 | 'django.middleware.common.CommonMiddleware', 47 | 'django.middleware.csrf.CsrfViewMiddleware', 48 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 49 | 'django.contrib.messages.middleware.MessageMiddleware', 50 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 51 | ] 52 | 53 | ROOT_URLCONF = 'Attendance_Tracking_System_Using_Computer_Vision.urls' 54 | 55 | TEMPLATES = [ 56 | { 57 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 58 | 'DIRS': [], 59 | 'APP_DIRS': True, 60 | 'OPTIONS': { 61 | 'context_processors': [ 62 | 'django.template.context_processors.debug', 63 | 'django.template.context_processors.request', 64 | 'django.contrib.auth.context_processors.auth', 65 | 'django.contrib.messages.context_processors.messages', 66 | ], 67 | }, 68 | }, 69 | ] 70 | 71 | WSGI_APPLICATION = 'Attendance_Tracking_System_Using_Computer_Vision.wsgi.application' 72 | 73 | 74 | # Database 75 | # https://docs.djangoproject.com/en/2.2/ref/settings/#databases 76 | 77 | DATABASES = { 78 | 'default': { 79 | 'ENGINE': 'django.db.backends.sqlite3', 80 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 81 | } 82 | } 83 | 84 | 85 | # Password validation 86 | # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators 87 | 88 | AUTH_PASSWORD_VALIDATORS = [ 89 | { 90 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 91 | }, 92 | { 93 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 94 | }, 95 | { 96 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 97 | }, 98 | { 99 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 100 | }, 101 | ] 102 | 103 | 104 | # Internationalization 105 | # https://docs.djangoproject.com/en/2.2/topics/i18n/ 106 | 107 | LANGUAGE_CODE = 'en-us' 108 | 109 | TIME_ZONE = 'UTC' 110 | 111 | USE_I18N = True 112 | 113 | USE_L10N = True 114 | 115 | USE_TZ = True 116 | 117 | 118 | # Static files (CSS, JavaScript, Images) 119 | # https://docs.djangoproject.com/en/2.2/howto/static-files/ 120 | 121 | 122 | # insta_project/settings.py 123 | MEDIA_URL = '/media/' 124 | MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 125 | 126 | 127 | 128 | STATIC_URL = '/static/' 129 | -------------------------------------------------------------------------------- /Attendance_Tracking_System_Using_Computer_Vision/urls.py: -------------------------------------------------------------------------------- 1 | """Attendance_Tracking_System_Using_Computer_Vision URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/2.2/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path 18 | from django.conf import settings # new 19 | from django.urls import path, include # new 20 | from django.conf.urls.static import static # new 21 | 22 | 23 | urlpatterns = [ 24 | path('admin/', admin.site.urls), 25 | ] 26 | 27 | if settings.DEBUG: # new 28 | urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) -------------------------------------------------------------------------------- /Attendance_Tracking_System_Using_Computer_Vision/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for Attendance_Tracking_System_Using_Computer_Vision project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Attendance_Tracking_System_Using_Computer_Vision.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /Computer_Vision_Module/Adding_New_Person_And_Training.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from numpy import load 3 | from numpy import asarray 4 | from numpy import savez_compressed 5 | from .Variables import EMBEDDINGS_PATH,model,PATH_TO_ADDED_PERSON_FOLDER 6 | from .Load_Dataset import load_dataset 7 | from .Get_Embeddings import get_embedding 8 | from .SVM_Classifier import svm_train 9 | 10 | def add_person(): 11 | ''' 12 | Gets Images Embeddings of new person and concatenate them with the old Embeddings 13 | ''' 14 | 15 | # load train dataset --> Returns NewTrainx & NewTrainY 16 | #print("Data is at:",PATH_TO_ADDED_PERSON_FOLDER) 17 | trainX_new_person, trainy_new_person ,_ = load_dataset(PATH_TO_ADDED_PERSON_FOLDER + '/') 18 | #print("SHAPE OF ADDED TRAINING EXAMPLES:",trainX.shape,"SHAPE OF LABELS:" ,trainy_new_person.shape) 19 | 20 | # CONVERT EACH FACE IN THE TRAIN SET TO AN EMBEDDING 21 | newTrainX_Images = list() 22 | for face_pixels in trainX_new_person: 23 | embedding = get_embedding(model, face_pixels) 24 | newTrainX_Images.append(embedding) 25 | newTrainX_Images = asarray(newTrainX_Images) 26 | print("SHAPE OF ADDED EMBEDDINGS:",newTrainX_Images.shape,"SHAPE OF LABELS:" ,trainy_new_person.shape) 27 | 28 | 29 | data = load( EMBEDDINGS_PATH + '/Embeddings-dataset.npz' ) 30 | old_embeddings , old_labels = data['arr_0'] , data['arr_1'] 31 | print("OLD EMBEDDINGS:", old_embeddings.shape ,"OLD LABELS:" ,old_labels.shape) 32 | new_embeddings , new_labels = newTrainX_Images,trainy_new_person 33 | print("NEW EMBEDDINGS:", new_embeddings.shape ,"NEW LABELS:" ,new_labels.shape) 34 | trainX = np.concatenate((old_embeddings, new_embeddings), axis=0) 35 | trainy_all_persons = np.concatenate((old_labels, new_labels), axis=0) 36 | print("FINAL EMBEDDINGS:", trainX.shape ,"FINAL LABELS:" ,trainy_all_persons.shape) 37 | savez_compressed( EMBEDDINGS_PATH + '/Embeddings-dataset.npz' , trainX,trainy_all_persons) 38 | svm_train(trainX, trainy_all_persons) 39 | return -------------------------------------------------------------------------------- /Computer_Vision_Module/Extract_Faces.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | import mtcnn 3 | from mtcnn.mtcnn import MTCNN 4 | from numpy import asarray 5 | from numpy import load 6 | from .Variables import detector 7 | 8 | 9 | def extract_face(filename, required_size=(160, 160)): 10 | ''' 11 | THIS FUNCTION TAKES (ONE) IMAGE AS INPUT 12 | DETECT AND RETURN (ONE) FACE ARRAY RESIZED --> Using the MTCNN Detector 13 | ''' 14 | image = Image.open(filename) # load image from file 15 | image = image.convert('RGB') # convert to RGB, if needed 16 | pixels = asarray(image) # convert to array 17 | results = detector.detect_faces(pixels) # detect faces in the image 18 | if(len(results) == 0): 19 | return [] 20 | x1, y1, width, height = results[0]['box'] # extract the bounding box from the first face 21 | x1, y1 = abs(x1), abs(y1) 22 | x2, y2 = x1 + width, y1 + height 23 | face = pixels[y1:y2, x1:x2] # extract the face 24 | image = Image.fromarray(face) 25 | image = image.resize(required_size) # resize pixels to the model size 26 | face_array = asarray(image) 27 | return face_array -------------------------------------------------------------------------------- /Computer_Vision_Module/Get_Embeddings.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | global graph 3 | from numpy import expand_dims 4 | 5 | graph = tf.get_default_graph() 6 | 7 | 8 | def get_embedding(model, face_pixels): 9 | ''' 10 | GET EMBEDDINGS FOR ONLY ONE FACE 11 | ''' 12 | print("Shape of image" ,face_pixels.shape ) 13 | face_pixels = face_pixels.astype('float32') # scale pixel values 14 | mean, std = face_pixels.mean(), face_pixels.std() # standardize pixel values across channels (global) 15 | face_pixels = (face_pixels - mean) / std 16 | samples = expand_dims(face_pixels, axis=0) # transform face into one sample 17 | print("Shape of normalized image" ,samples.shape ) 18 | 19 | with graph.as_default(): 20 | yhat = model.predict(samples) # make prediction to get embedding 21 | print("Shape of yhat" ,yhat.shape ) 22 | return yhat[0] 23 | -------------------------------------------------------------------------------- /Computer_Vision_Module/Load_Dataset.py: -------------------------------------------------------------------------------- 1 | from .Load_Faces import load_faces 2 | from .Variables import EMPLOYEES_NAMES,EMBEDDINGS_PATH 3 | 4 | import os 5 | import numpy as np 6 | from numpy import savez_compressed 7 | from numpy import asarray 8 | from numpy import load 9 | from numpy import expand_dims 10 | from numpy import asarray 11 | from numpy import savez_compressed 12 | from numpy import load 13 | from os.path import isdir 14 | from os import listdir 15 | 16 | 17 | 18 | # load a dataset that contains one subdir for each class that in turn contains images 19 | def load_dataset(directory): 20 | ''' 21 | THIS FUNCTION TAKE DATABASE DIRECTORY WITH PERSONS' NAMES AS SUBDIRECTORY 22 | RETURNS LABELS AND NUMPY ARRAYS 23 | ''' 24 | flag = None 25 | X, y = list(), list() 26 | # savez_compressed( EMBEDDINGS_PATH + '/Embeddings-dataset.npz', newTrainX,trainy) # save arrays to one file in compressed format WILL BE USED WHEN WE ADD NEW PERSON TO THE DATABASE WE'LL LOAD THIS AND APPEND 27 | # data = load( EMBEDDINGS_PATH + '/Embeddings-dataset.npz') 28 | # trainy = data['arr_1'] 29 | 30 | if os.path.isfile( EMPLOYEES_NAMES +'/Employees-dataset.npz') == True: 31 | data = load( EMPLOYEES_NAMES + '/Employees-dataset.npz') 32 | Employees = data['arr_0'] # List 33 | # Already exist 34 | flag = False 35 | else: 36 | Employees = np.array([]) 37 | flag = True 38 | 39 | print("CURRENT EMPLOYEE DATABASE:" ,Employees ) 40 | 41 | 42 | for subdir in listdir(directory): # LOOP OVER SUB-FOLDERS, on per class 43 | if subdir in Employees: 44 | print("SKIPPING EMPLOYEE" , subdir) 45 | continue 46 | Employees = np.append(Employees , subdir) 47 | path = directory + subdir + '/' # PATH = SUBFOLDER 48 | if not isdir(path): # skip any files that might be in the dir 49 | print("WARNING: FILES EXIST IN THE DATA DIRECTORY (ONLY FOLDERS ARE READ)!") 50 | print("SKIPPING FILE" , path , "...") 51 | continue 52 | 53 | faces = load_faces(path) # load all faces in the subdirectory 54 | labels = [subdir for _ in range(len(faces))] # create labels FOR THE PERSON, WE DO RANGE BECAUSE DETECTOR CAN MISS SOME IMAGES AND DETECT 0 FACES 55 | print(' >LOADED %d EXAMPLES FOR CLASS: %s' % (len(faces), subdir)) # summarize progress 56 | X.extend(faces) # store 57 | y.extend(labels) # store 58 | savez_compressed( EMPLOYEES_NAMES + '/Employees-dataset.npz', Employees ) # save arrays to one file in compressed format WILL BE USED WHEN WE ADD NEW PERSON TO THE DATABASE WE'LL LOAD THIS AND APPEND 59 | return asarray(X), asarray(y) , flag -------------------------------------------------------------------------------- /Computer_Vision_Module/Load_Faces.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | from os import listdir 4 | from numpy import asarray 5 | from numpy import load 6 | 7 | 8 | from .Extract_Faces import extract_face 9 | 10 | 11 | # load images and extract faces for all images in a directory 12 | def load_faces(directory): 13 | ''' 14 | THIS FUNCTION TAKES DIRECTORY OF (ONE) PERSON IMAGES AS INPUT 15 | OUTPUTS A FACE NUMPY ARRAY 16 | ''' 17 | faces = list() 18 | # enumerate files 19 | for filename in listdir(directory): 20 | path = directory + filename 21 | face = extract_face(path) # get face 22 | if(len(face) == 0): 23 | continue 24 | faces.append(face) # store 25 | return faces -------------------------------------------------------------------------------- /Computer_Vision_Module/Model_Training.py: -------------------------------------------------------------------------------- 1 | from .Load_Dataset import load_dataset 2 | from .Get_Embeddings import get_embedding 3 | from .SVM_Classifier import svm_train 4 | from .Variables import model,TRAINING_IMAGES_PATH,EMBEDDINGS_PATH 5 | import sys 6 | import os 7 | from os import listdir 8 | from os.path import isdir 9 | import numpy as np 10 | from numpy import asarray 11 | from numpy import savez_compressed 12 | from numpy import load 13 | import keras 14 | 15 | 16 | 17 | 18 | def trainModel(): 19 | # load train dataset 20 | print("STARTING THE TRAINING PROCESS...") 21 | print("DATA PATH IS:",TRAINING_IMAGES_PATH) 22 | 23 | if not isdir(TRAINING_IMAGES_PATH): 24 | print("ERROR: GIVEN PATH IS NOT A DIRECTORY, PATH IS:", TRAINING_IMAGES_PATH) 25 | print("TERMINATING...") 26 | sys.exit(0) 27 | trainX, trainy , flag = load_dataset(TRAINING_IMAGES_PATH + '/') 28 | print("SHAPE OF TRAINING EXAMPLES:",trainX.shape,"SHAPE OF LABELS:" ,trainy.shape) 29 | 30 | # CONVERT EACH FACE IN THE TRAIN SET TO AN EMBEDDING 31 | newTrainX = list() 32 | for face_pixels in trainX: 33 | embedding = get_embedding(model, face_pixels) 34 | newTrainX.append(embedding) 35 | newTrainX = asarray(newTrainX) 36 | print("SHAPE OF TRAINING EMBEDDINGS:",newTrainX.shape,"SHAPE OF LABELS:" ,trainy.shape) 37 | # If true save if false append? 38 | print("SAVING THE EMBEDDINGS NUMBY ARRAY...") 39 | if flag == True: 40 | # Data base is empty, save new numpy array and keep newTrainX 41 | savez_compressed( EMBEDDINGS_PATH + '/Embeddings-dataset.npz', newTrainX,trainy) # save arrays to one file in compressed format WILL BE USED WHEN WE ADD NEW PERSON TO THE DATABASE WE'LL LOAD THIS AND APPEND 42 | print("STARTING TRAINING THE SVM MODEL...") 43 | svm_train(newTrainX, trainy) 44 | elif flag == False: 45 | data = load( EMBEDDINGS_PATH + '/Embeddings-dataset.npz' ) 46 | old_embeddings , old_labels = data['arr_0'] , data['arr_1'] 47 | print("OLD EMBEDDINGS:", old_embeddings.shape ,"OLD LABELS:" ,old_labels.shape) 48 | new_embeddings , new_labels = newTrainX , trainy 49 | print("NEW EMBEDDINGS:", new_embeddings.shape ,"NEW LABELS:" ,new_labels.shape) 50 | trainX = np.concatenate((old_embeddings, new_embeddings), axis=0) 51 | trainy = np.concatenate((old_labels, new_labels), axis=0) 52 | print("FINAL EMBEDDINGS:", trainX.shape ,"FINAL LABELS:" ,trainy.shape) 53 | savez_compressed( EMBEDDINGS_PATH + '/Embeddings-dataset.npz' , trainX,trainy) 54 | svm_train(trainX, trainy) 55 | -------------------------------------------------------------------------------- /Computer_Vision_Module/Multiple_Faces_Prediction.py: -------------------------------------------------------------------------------- 1 | from .Variables import EMBEDDINGS_PATH, SVM_MODEL_PATH,SVM_CONFIDENCE, model 2 | from .Get_Embeddings import get_embedding 3 | import pickle 4 | import cv2 5 | import numpy as np 6 | from numpy import asarray 7 | from numpy import savez_compressed 8 | from numpy import load 9 | from numpy import expand_dims 10 | from sklearn.metrics import accuracy_score 11 | from sklearn.preprocessing import LabelEncoder 12 | from sklearn.preprocessing import Normalizer 13 | from PIL import Image 14 | import mtcnn 15 | from mtcnn.mtcnn import MTCNN 16 | 17 | 18 | detector = MTCNN() # Creating instance from the class MTCNN 19 | 20 | def multiple_faces(filename, required_size=(160, 160)): 21 | data = load( EMBEDDINGS_PATH + '/Embeddings-dataset.npz') 22 | trainy = data['arr_1'] 23 | out_encoder = LabelEncoder() 24 | out_encoder.fit(trainy) 25 | trainy = out_encoder.transform(trainy) 26 | 27 | # LOAD THE MODEL 28 | print("TESTING ON AN IMAGE") 29 | print("LOADING THE MODEL...") 30 | svm_model = pickle.load(open(SVM_MODEL_PATH + '/svm_model.sav', 'rb')) 31 | print("DONE LOADING THE MODEL!") 32 | print("LOADING THE IMAGE...") 33 | image = Image.open(filename) # load image from file 34 | print("DONE LOADING THE IMAGE!") 35 | image = image.convert('RGB') # convert to RGB, if needed 36 | pixels = asarray(image) # convert to array 37 | results = detector.detect_faces(pixels) # detect faces in the image 38 | 39 | if(len(results) == 0): 40 | return False 41 | 42 | 43 | # LOOP OVER ALL FOUND FACE AND ANNOTATE THEM 44 | for i in range(len(results)): 45 | 46 | x1, y1, width, height = results[i]['box'] # extract the bounding box from the i-th first face 47 | x1, y1 = abs(x1), abs(y1) 48 | x2, y2 = x1 + width, y1 + height 49 | face = pixels[y1:y2, x1:x2] # extract the face 50 | image = Image.fromarray(face) 51 | image = image.resize(required_size) # resize pixels to the model size 52 | face_array = asarray(image) 53 | face_emb = get_embedding(model, face_array) # get the embeddings 54 | samples = expand_dims(face_emb, axis=0) 55 | prediction = svm_model.predict(samples) 56 | predict_name = out_encoder.inverse_transform(prediction) 57 | pred_proba = svm_model.predict_proba(samples) 58 | 59 | # predict_name = out_encoder.inverse_transform(prediction) 60 | # print("Prediction is",predict_name ,prediction,pred_proba ) 61 | 62 | print(pred_proba[0][prediction[0]]) 63 | if(pred_proba[0][prediction[0]] >= SVM_CONFIDENCE): # SVM Thresholding to Get Known vs UnKnown People was 0.999 64 | predict_name = out_encoder.inverse_transform(prediction) 65 | print("Prediction is",predict_name) 66 | else: 67 | predict_name = ['UNKNOWN'] 68 | print("Prediction is",predict_name) 69 | 70 | font = cv2.FONT_HERSHEY_TRIPLEX 71 | cv2.putText(pixels, predict_name[0], (x1, y1), font, 0.7, (255, 255, 0), 2) 72 | 73 | print("SAVING OUTPUT IMAGE...") 74 | cv2.imwrite( filename , pixels) 75 | print("IMAGE SAVED TO:" , 'D:\\Work\\Attendance\\media\\testing\\IMG_1607.JPG' ) 76 | return filename -------------------------------------------------------------------------------- /Computer_Vision_Module/SVM_Classifier.py: -------------------------------------------------------------------------------- 1 | from sklearn.metrics import accuracy_score 2 | from sklearn.preprocessing import LabelEncoder 3 | from sklearn.preprocessing import Normalizer 4 | from sklearn.svm import SVC 5 | import pickle 6 | import os 7 | from .Variables import SVM_MODEL_PATH 8 | 9 | 10 | def svm_train(newTrainX, trainy ): 11 | in_encoder = Normalizer(norm='l2') 12 | newTrainX = in_encoder.transform(newTrainX) 13 | out_encoder = LabelEncoder() # label encode targets 14 | out_encoder.fit(trainy) 15 | trainy = out_encoder.transform(trainy) 16 | svm_model = SVC(kernel='linear', probability=True) 17 | svm_model.fit(newTrainX, trainy) 18 | print("SUCCESSFULLY FINISHED TRAINING THE SVM MODEL SUCCES!") 19 | yhat_train = svm_model.predict(newTrainX) 20 | score_train = accuracy_score(trainy, yhat_train) # score 21 | print('ACCURACY: TRAIN=%.3f' % (score_train*100)) 22 | # SAVING THE MODEL 23 | print("SAVING SVM MODEL TO:", SVM_MODEL_PATH + '/svm_model.sav ...') 24 | filename = SVM_MODEL_PATH + '/svm_model.sav' 25 | pickle.dump(svm_model, open(filename, 'wb')) 26 | print("DONE SAVING THE MODEL!") 27 | return -------------------------------------------------------------------------------- /Computer_Vision_Module/Variables.py: -------------------------------------------------------------------------------- 1 | import os 2 | import mtcnn 3 | from mtcnn.mtcnn import MTCNN 4 | 5 | detector = MTCNN() # Creating instance from the class MTCNN 6 | 7 | # EMBEDDINGS PATH 8 | EMBEDDINGS_PATH = os.getcwd() 9 | 10 | # EMPLOYEES PATH 11 | EMPLOYEES_NAMES = os.getcwd() 12 | 13 | # SVM Model Path 14 | SVM_MODEL_PATH = os.getcwd() 15 | 16 | 17 | # Create Folders/Classes under photos dir in your Django Project 18 | TRAINING_IMAGES_PATH = os.getcwd() + '\\..\\media\\photos' 19 | 20 | 21 | 22 | # Path of facenet_keras.h5 file 23 | PATH_TO_FACENET_MODEL = os.getcwd() 24 | FACENET_MODEL = PATH_TO_FACENET_MODEL + '\\facenet_keras.h5' 25 | 26 | 27 | if os.path.isfile(FACENET_MODEL) == True: 28 | print("facenet_keras.h5 already exist, no need to re-download it \n") 29 | else: 30 | print("Working directory where detector model will be saved in:",FACENET_MODEL) 31 | bashCommand = "wget --no-check-certificate 'https://docs.google.com/uc?export=download&id=1PZ_6Zsy1Vb0s0JmjEmVd8FS99zoMCiN1' -O " + FACENET_MODEL 32 | os.system(bashCommand) 33 | 34 | model = load_model(FACENET_MODEL) 35 | 36 | 37 | # Variables Specefic for Adding New Persons 38 | PATH_TO_ADDED_PERSON_FOLDER = '/content/Added' 39 | 40 | 41 | # Variables Specific for Video Function 42 | PATH_TO_VIDEO_DIRECTORY = '/content/Test_videos' # Without Slash 43 | PATH_TO_OUTPUT_VIDEOS_DIRECTORY = '/content/Output' # Without slash 44 | PATH_TO_OUTPUT_LOGFILE_DIRECTORY = '/content/LogFiles' # Without slash 45 | DETECTOR_CONFIDENCE = 0.99 46 | SVM_CONFIDENCE = 0.999 -------------------------------------------------------------------------------- /Computer_Vision_Module/Video_Test.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | import re 4 | import progressbar 5 | import pickle 6 | from PIL import Image 7 | from os import listdir 8 | from os.path import isdir 9 | from pandas import DataFrame 10 | from numpy import asarray 11 | from numpy import savez_compressed 12 | from numpy import expand_dims 13 | from numpy import load 14 | from .Variables import EMBEDDINGS_PATH,detector,model,SVM_MODEL_PATH,PATH_TO_OUTPUT_VIDEOS_DIRECTORY,PATH_TO_OUTPUT_LOGFILE_DIRECTORY,PATH_TO_VIDEO_DIRECTORY,DETECTOR_CONFIDENCE,SVM_CONFIDENCE 15 | from sklearn.preprocessing import LabelEncoder 16 | from .Get_Embeddings import get_embedding 17 | 18 | 19 | def video_test(video_path, svm_model): 20 | name = video_path[video_path.find("CAMERA"):] 21 | CAMERA_ID = int(re.search(r'\d+', name).group()) 22 | data = load(EMBEDDINGS_PATH + '/Embeddings-dataset.npz') 23 | trainy = data['arr_1'] 24 | out_encoder = LabelEncoder() 25 | out_encoder.fit(trainy) 26 | trainy = out_encoder.transform(trainy) 27 | 28 | 29 | entries = {'camera_id': [], 30 | 'timestamp': [], 31 | 'employee_name':[], 32 | 'confidence':[], 33 | 'x':[], 34 | 'y':[], 35 | 'width':[], 36 | 'height':[] 37 | } 38 | df = DataFrame(entries) 39 | vidcap = cv2.VideoCapture(video_path) 40 | fps = int(vidcap.get(5)) 41 | success = True 42 | fourcc = cv2.VideoWriter_fourcc(*'mp4v') # Be sure to use lower case 43 | out = cv2.VideoWriter(PATH_TO_OUTPUT_VIDEOS_DIRECTORY + '/CAMERA' + str(CAMERA_ID) +'.mp4', fourcc, fps, (int(vidcap.get(3)), int(vidcap.get(4)))) 44 | success, pixels = vidcap.read() 45 | bar = progressbar.ProgressBar(maxval=int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT)), widgets=[progressbar.Bar('#', '[', ']'), ' ', progressbar.Percentage()]) 46 | counter = 0 47 | while success: 48 | current_frame_time = counter/fps 49 | bar.update(counter+1) 50 | counter = counter + 1 51 | success, pixels = vidcap.read() 52 | if(success == False): # DIVIDING FPS/6 counter%3 != 0 or 53 | continue 54 | results = detector.detect_faces(pixels) 55 | for i in range(len(results)): 56 | if(results[i]['confidence'] < DETECTOR_CONFIDENCE): 57 | continue 58 | x1, y1, width, height = results[i]['box'] # extract the bounding box from the first face 59 | x1, y1 = abs(x1), abs(y1) 60 | x2, y2 = x1 + width, y1 + height 61 | face = pixels[y1:y2, x1:x2] # extract the face 62 | image = Image.fromarray(face) 63 | image = image.resize((160, 160)) # resize pixels to the model size 64 | face_array = asarray(image) 65 | face_emb = get_embedding(model, face_array) 66 | 67 | samples = expand_dims(face_emb, axis=0) 68 | prediction = svm_model.predict(samples) 69 | pred_proba = svm_model.predict_proba(samples) 70 | 71 | if(pred_proba[0][prediction[0]] > SVM_CONFIDENCE): 72 | predict_name = out_encoder.inverse_transform(prediction) 73 | font = cv2.FONT_HERSHEY_SIMPLEX 74 | cv2.putText(pixels, predict_name[0], (x1, y1), font, 1, (255, 255, 0), 2) 75 | 76 | ######################## WRITING TO CSV FILES ################################ 77 | entry = {'camera_id': [str(CAMERA_ID)], 78 | 'timestamp': [current_frame_time], 79 | 'employee_name':[predict_name[0]], 80 | 'confidence':[pred_proba[0][prediction[0]]], 81 | 'x':[int(x1)], 82 | 'y':[int(y1)], 83 | 'width':[int(width)], 84 | 'height':[int(height)] 85 | } 86 | temp = DataFrame(entry) 87 | df = df.append(temp) 88 | 89 | out.write(pixels) 90 | if cv2.waitKey(10) == 27: # exit if Escape is hit 91 | break 92 | 93 | #update_progress(1) 94 | bar.finish() 95 | out.release() 96 | df.to_csv( PATH_TO_OUTPUT_LOGFILE_DIRECTORY + '/CAMERA' +str(CAMERA_ID)+ '_logfile.csv' , index = False) 97 | return 98 | 99 | 100 | 101 | 102 | def video(): 103 | ''' 104 | This image takes a directory that has several videos, each video is names as: CAMERA0.mp4 / CAMERA1.mp4 and so on 105 | ''' 106 | svm_model = pickle.load(open( SVM_MODEL_PATH + '/svm_model.sav' , 'rb')) 107 | directory = PATH_TO_VIDEO_DIRECTORY 108 | for subdir in listdir(directory): # LOOP OVER SUB-FOLDERS, on per class 109 | path = directory + '/' + subdir # PATH = SUBFOLDER 110 | print("CURRENTLY PROCESSING VIDEO:", path) 111 | video_test(path , svm_model) 112 | print("FINISHED PROCESSING VIDEO FILES!") 113 | return 114 | 115 | 116 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Mohammed Samir 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Attendance-Tracking-System-Using-Computer-Vision 2 | 3 | ![Alt Text](https://www.olloltd.com/images/2020/02/sssss.gif) 4 | ## Introduction: 5 | Tracking Systems nowadays are in high demand starting from the very basic attendance systems to most critical security systems. With the powerful rise of AI & Computer Vision. These Tracking Systems have become more accurate & more precise resulting in more reliability and stability. 6 | Our Project is basically Leveraging The power of Image & Video Detection, Recognition & Tracking. 7 | We have applied the best-in-class Computer Vision Algorithms to Build a full Attendance Tracking System Enabling the following Features: 8 | - Real Time Face Detection & Recognition applied on Video Camera Streams. “Based on your Computational Resources Power” 9 | - Ability to Add new Employees to the System and Retrain the Algorithm Using Only 1~2 Images. 10 | - A Web Application Showing Employees Attendance & Activities. 11 | - Extras: Faces Detector & Recognizer 12 | 13 | **Final Target** : Monitor How Much Time Does an employee stays in the Work Environment vs how much 14 | does he/she waste per day either outside the environment or in fun area. 15 | 16 | ## System Architecture Overview: 17 | Let’s define it in simple forms, Any System has its Own Input Data, Output Data, Processing Unit, Storage Unit. 18 | INPUT 🡪 Data Source for this project is mainly live streams (Videos) from environment cameras. 19 | Desired (Output) 🡪 A Reliable Employees Attendance/Activity DATABASE on a Web Application. 20 | In Between (Target) 🡪 Build an Attendance Tracking System Using Computer Vision. 21 | Storage 🡪 Videos HDD + Store Employees Final Activity in a MySQL Database. 22 | ![image](https://drive.google.com/uc?export=view&id=139tuRPWjPuxKi8LcYqPIxHKq7wDUDZzt) 23 | Now that we have seen the overall System Overview, Let's Build the Pipeline for this Application. 24 | ## System Pipeline: 25 | The Project will mainly be separated into 4 modules: 26 | Module A: Getting Data in Either from Videos or From Images 27 | Module B: Computer Vision Part (Face Detector & Face Recognizer) 28 | Module C: Attendance Logic (Based on Your Environment) 29 | Module D: Web Application (Attendance Admin Panel & Testing Interface) 30 | ![image](https://drive.google.com/uc?export=view&id=15D50d7XtIne48o0_eI_o4EFJmcqlgHgQ) 31 | Let’s dig into each module in a brief: 32 | 33 | ## Module A: Getting Data in Either from Videos or From Images 34 | Since this is an attendance Tracking System then we have some cameras installed at some location in your environment 35 | ![image](https://drive.google.com/uc?export=view&id=1B9AHRKxJQ0hJB6Pr2rkER9q0XOD1Fk70) 36 | We have Installed 6 Cameras at the following Critical Locations: 37 | A – Entrance Door from Outside (Camera 3 & 4) 🡪 To get Employees leaving Environment. 38 | B – Entrance Door from Inside (Camera 1 & 2) 🡪 To get Employees Coming into The Environment. 39 | C – Fun Area Door (Camera 5 & 6) 🡪 To Capture Employees Going in or Out of Fun Area. 40 | You may ask Why at these locations: It’s as simple as we want to know whenever an employee arrives to the Environment using cameras 1 & 2 and whenever he/she leaves using cameras 3 &4 . And how much time does he/she wastes at Fun Area. 41 | N.B : We have used 2 cameras at each zone to cover all possible face angels. 42 | We need for Each Video Frame to detect faces inside each frame & Recognize it. (You may think of a frame as an image). 43 | 44 | ## Module B: Computer Vision Part (Face Detector + Face Recognizer) 45 | Here we want to do 2 main tasks first detecting if an image contains a face or not (Detection). then if the image has a face we want to know who is this person (Recognition). 46 | ### Module B.1 Face Detection 47 | At this step we have some Input Videos from different Cameras. Videos are composed of Frames, you could think of each frame as a 48 | normal image. And we just want to detect if there is a face in an image or not. 49 | ### Detection Trials: 50 | #### B.1.1 HAAR 51 | We have started our trials using traditional image processing algorithms “HAAR” it is a feature based cascade classifier using some basic filter we can get: 52 | -The region of the eyes is often darker than the region of the nose and cheeks. 53 | -The eyes are darker than the bridge of the nose 54 | ![image](https://drive.google.com/uc?export=view&id=1uV2H8A2GXLl_23yFJ5Flz0NjoYS8y_ZO) 55 | Since that HAAR is very inefficient in difficult lighting conditions we didn’t expect a good output from it. Also because Haar Features have to be determined manually, there is a certain limit to the types of things it can detect. If you give a classifier (a network, or any algorithm that detects faces) edge and line features, then it will only be able to detect objects with clear edges and lines. Even as a face detector, if we manipulate the face a bit (say, cover up the eyes with sunglasses, or tilt the head to a side), a Haar-based classifier may not be able to recognize the face. 56 | However HAAR Has its own Bright Side when it’s applied on high quality clear images: Since that we don’t need to train HAAR Features as they are manually selected we just need a relatively small amount of Data for faces also HAAR execution speed is high and requires less computational resources when compared to other detection algorithms. 57 | HAAR Output on Our Environment: 58 | ![image](https://drive.google.com/uc?export=view&id=1WyHh8uVqDhezY-eoh4CXUE-N0U0n6Lo_) 59 | As you can see HAAR failed to get our faces in this poor position & lightning however it detected basic edges in the image. 60 | 61 | #### B.1.2 YOLO (You Only Look Once) 62 | YOLO is an object detector which detects objects in both images and video streams using Deep Learning, OpenCV, and Python. We call YOLO as single stage detector ,there are other multi stage detectors that are more accurate but are very slow. 63 | The “You Only Look Once,” or YOLO, family of models are a series of end-to-end deep learning models designed for fast object detection, developed by Joseph Redmon, et al. and first described in the 2015 paper titled “ You Only Look Once: Unified, Real-Time Object Detection” , details an object detector capable of super real-time object detection, obtaining 45 FPS on a GPU. 64 | ![image](https://drive.google.com/uc?export=view&id=1_0gRQtEZ-wMSR7H2w4aOIkNQympjN9GD) 65 | YOLO Detection Method: Sliding Window 66 | This approach involves a single deep convolutional neural network (originally a version of GoogLeNet, later updated and called DarkNet based on VGG) that splits the input into a grid of cells and each cell directly predicts a bounding box and object classification “Called Sliding Window”. The result is a large number of candidate bounding boxes that are consolidated into a final prediction by a post-processing step. Since YOLO is an Object Detector then it will be able to detect different objects in the image, including people. 67 | 68 | ![image](https://drive.google.com/uc?export=view&id=1cpmIA-x5QLOZQiUArsyqgSIy_eIkOHAb) 69 | 70 | Perfect Object (Human) Detection isn’t it ?! 71 | Simple answer is --> Yes it’s very good. But only in Full Object Detection. I mean the output of the detector is a box containing the person. 72 | ![image](https://drive.google.com/uc?export=view&id=1pCDALqHllSpHZhOai42u3NsuCxPd-GtH) 73 | When we feed these images to a classifier (Person A “left” & Person B “Right”), a classifier will always look at unique easy features at the beginning, this includes the background out there ,T-shirts Colors,etc which is not a good thing. 74 | I.e After some training whenever we pass to the classifier an image of Any person standing for example at the location that has green background where Person_B Stands “Right Image” ,the classifier will always predicts Whoever passes by this location as Person_B because it fires based on the background not actual features. 75 | 76 | #### B.1.3 Segmentation 77 | Now we have seen that YOLO is a good detector , but the detection outputs a full box including a background which we want to eliminate. The Segmentation Concept Comes into play here. 78 | Segmentation will allow us to crop the Region of Interest (ROI) that we want from the image i.e eliminating the whole background. 79 | ![image](https://drive.google.com/uc?export=view&id=1U0VRZm2bqkEwHpM-lGOIMszd4xT1t8mV) 80 | 81 | This Result is relatively perfect but actually we don’t want neither the background nor the whole body. And the detector still getting the whole body. 82 | We just want the faces! That's why we have checked for other face detectors and we found something called YOLO FACES. 83 | 84 | #### B.1.4 YOLO FACES 85 | This is a Special Version of YOLO Object Detectors that focuses only on detecting faces as an objects rather than detecting the whole body. 86 | We have tried it however it wasn’t very good in detecting all faces whenever they are aligned to the right or the left. 87 | 88 | ![image](https://drive.google.com/uc?export=view&id=1cLS2x4xN8OIQHoFROgbVeGFwMZztWG4i) 89 | 90 | Finally we have found a much better detector than most of the previously mentioned algorithms. 91 | 92 | #### B.1.5 MTCNN 93 | Multitask Cascaded Convolutional Neural Networks (MTCNN), The MTCNN is popular because it achieved then state-of-the-art results on a range of benchmark datasets, and because it is capable of also recognizing other facial features such as eyes and mouth, called landmark detection. 94 | 95 | ![image](https://drive.google.com/uc?export=view&id=1xNF6GMGnj06reV4iZBGcxmYmgGh6hLRx) 96 | Obama Face Landmarks 97 | 98 | 99 | ### Detection Summary: 100 | 101 | Detection Algorithm Detection Accuracy 102 | HAAR 70 % 103 | YOLO 92 % 104 | Segmentation 90 % 105 | YOLO Faces 80 % 106 | MTCNN 96 % 107 | 108 | ### Module B.2 Face Recognition 109 | At this step we have some Images that contain boxes around any face in the picture. Now it’s time to recognize the faces and know who is the exact person appearing. 110 | This could be considered as a normal image classification problem. 111 | Where we can use either traditional ML Algorithms or Deep Learning ones. We have tried the very basic ML Algorithms to the most advanced ones & Mixing between them. Here is our Trials 112 | - Logistic Regression & Random Forests (Very Poor Accuracy). 113 | - Neural Networks (Poor Accuracy on Images). 114 | - Convolutional Neural Networks “CNN” (Excellent Accuracy on Images, However Since this is an Attendance System hence we have only a few registered images for each employee “1~4 Images” which aren’t enough at all to train a CNN From Scratch). 115 | - Siamese Networks (Based on 2 CNNs) → Good one with decent accuracy = 84% . 116 | - CNN + Deep NN → Using Transfer Learning we have used a pre trained CNN to Extract Face Features then we have applied the output 117 | features (128 Embeddings) to a NN which resulted in an overall accuracy = 90% . 118 | - CNN + SVM → Using Transfer Learning we have used a pre trained CNN to Extract Face Features then we have applied the output 119 | features (128 Embeddings per Face) to SVM which resulted in mostly an overall system accuracy = 96% . 120 | 121 | N.B You may think how come CNN + NN doesn’t achieve high accuracy like CNN+SVM, It’s simply because Deep learning requires alot of data to get good accuracy. In the best scenario we will have only 5 images per employee and for example 100 Employees. (i.e 100 x 5 x 128 Embeddings) which is not enough for any deep learning model. 122 | Therefore we can conclude all of these by saying that the main pillars for the Recognition phase are CNNs , Transfer Learning & SVM.. 123 | 124 | #### Final Pipeline: 125 | ![image](https://drive.google.com/uc?export=view&id=1Fq8eNMrHuLMSXCyDYXkWKemVMT6f3lSo) 126 | 127 | ## Module C: Attendance Logic (Based on Your Environment) 128 | This part is going to be purely SW Logic, Covering 2 Parts 129 | - Firstly, what about the 4% Error rate in our Classification, how can we make sure that the person recognized is 100% that person 130 | not 96%. → Solved using Confidence Interval 131 | - Secondly we need some logic to handle the first seen & last seen of a person including his/her wasted time in fun area or outside 132 | the company & then calculate the final working & wasted hours . 133 | Let's Start, Each of our cameras will produce a log file at the end of the day. the logic module combines and process on them. 134 | ![image](https://drive.google.com/uc?export=view&id=13zsinfQrZZaI5aHgP3JEh5TCE8E1T-Z4) 135 | Sample log from camera_id 1 136 | 137 | Before applying the confidence interval concept, firstly, we will combine all of the six log files produced by the 6 cameras and sort by: 138 | - The employee name 139 | - Timestamp 140 | - The Camera ID 141 | ![image](https://drive.google.com/uc?export=view&id=1xEkVxnXt19e1afesKHM4jAwAfM7yvf07) 142 | Then we unify the cameras Id’s and reduce them from 6 Ids to 3 Ids “Since each 2 cameras capture the same area but from different angles”. ( 1 & 2 → Reduced to 1 , 3 & 4 → Reduced to 3 , 5 & 6 → Reduced to 6 ) 143 | ![image](https://drive.google.com/uc?export=view&id=1bRaWL76osgX8igB8uz9bzthUhlPH13nB) 144 | We have set our confidence interval threshold to be 5 , Which means if a person was detected in a video stream in 5 consecutive frames then most probably he/she is the same person. However if less than 5 then mostly due to light conditions or face angel the classifier model has mistaken the classification task. Therefore drop these log entries from your log file. 145 | Here is the final accurate log file: 146 | ![image](https://drive.google.com/uc?export=view&id=19E8SZ3HrUv_15VrOvg93LbokySGwiapJ) 147 | Then by doing some pair successive subtractions, we can obtain the time an employee spent in each area “you can check the code at the GitHub repository for further investigation. 148 | And here is the final log file to be imported in the web application database containing all employees activity data. “Note that we scaled the 8 of the working day to 8 minutes for computational reasons” 149 | ![image](https://drive.google.com/uc?export=view&id=1TNBTjdE3-n4kyzYy_44JXKmVPOuZ6Shb) 150 | Now it’s time to package all of this work inside a web application. 151 | 152 | 153 | ## Module D: Web Application (Attendance Admin Panel) 154 | Now we have reached the state of having a really good model without real life application using it, so it’s useless so far in our case we have built a web application that track a company’s employees activities/attendance, activities like when has employee arrive workplace, how many hours the employee was off working, and how many hours the employee was on desk and different types of activities that the employees usually do during a working day in the company’s workplace. 155 | 156 | In the web application module we will go through how we have built our web application using Django Framework. 157 | ### Activity Tracking Web Application will help us to 158 | 159 | 1. Add, Edit, Delete Employees to our Database. 160 | 2. Train our model for our newly added employees. 161 | 3. Test our model on a single picture. 162 | 4. Take a live snapshot and test the snapshot against our machine learning model. 163 | 164 | ### Web Application Database Entities 165 | Our web application will consist of Employees, Activities that occurred by employees and Employees Pictures and Test Image model, each of these models represents an Entity with following responsibility: 166 | 167 | A. Employee: Responsible for adding, removing, editing employees. 168 | B. Activity: Responsible for employees activities. 169 | C. Picture: Responsible for adding picture to an employee. 170 | D. Test: Responsible for testing an image against our machine learning model. 171 | 172 | Each employee has a set of activities for each working day associated with him, each employee has a set of pictures that the machine learning model will use to train and test the employee’s face and a Test entity to be able to test an image or video against machine learning model through the web application. 173 | Django comes with a grateful built-in admin panel that will help us to build our Web Application admin panel quickly, all we have to do is to register our models in the admin panel so the admin user will be able to make CRUD operations in all models. 174 | 175 | ### Django Project installation: 176 | To install django on our machine it’s recommended to install it on Python virtual environment. 177 | I will suppose that you have python3 and virtual environment on linux machine already installed on your machine, so we will create new virtual environment as following 178 | 1. make a new directory that will represent our web project and application. 179 | 180 | $ mkdir Attendance_Tracking_System_Using_Computer_Vision 181 | 2. Inside Attendance_Tracking_System_Using_Computer_Vision we will run the following to create our virtual environment with the name 182 | venv 183 | 184 | $ virtualenv ./venv 185 | 3. After creating our virtual environment we need to activate it, we will run the following command in the same directory. 186 | 187 | $ source ./venv/bin/activate 188 | 4. After activating our virtual environment we will need to install python-pip, if you have pip already installed you don’t have to 189 | reinstall it. 190 | 191 | $ sudo apt install python3-pip 192 | 5. Now we need to install the requirements to get our web application working, you will find the requirements file in the Github 193 | repository link below, after copying file to your project root directory run the below command to install packages. 194 | 195 | $ pip install -r /path/to/requirements.txt 196 | 197 | 6. Now let’s create our new project that will host our web application, to create a new Django project just run the following 198 | command, note the “./’ tell django to create a project in the same directory which should be the root directory to our web 199 | application. 200 | 201 | $ django-admin createproject 202 | $ Attendance_Tracking_System_Using_Computer_Vision ./ 203 | 204 | 7. A django project consists of multiple applications each application should represent a component of the project components, so now we need to create an application that will represent our activity tracking application on the Attendance Tracking System Project, 205 | to create new application just run the following command. 206 | 207 | $ ./manage.py createapp Activity_Tracking_Web_App 208 | 209 | 8. After that you should have a specific folder for your machine learning function in the project root directory, so you will add all 210 | your machine learning scripts in a subfolder named “Computer_Vision_Module” 211 | 9. Very good till now we have installed our project environment and initialize the project structure, now you should see a file 212 | structure like the following in your project root directory. 213 | 214 | │ .gitignore 215 | │ manage.py 216 | │ requirements.txt 217 | ├───Activity_Tracking_Web_App 218 | │ │ admin.py 219 | │ │ apps.py 220 | │ │ models.py 221 | │ │ tests.py 222 | │ │ views.py 223 | │ │ __init__.py 224 | │ │ 225 | │ ├───migrations 226 | │ │ │ __init__.py 227 | ├───Attendance_Tracking_System_Using_Computer_Vision 228 | │ │ settings.py 229 | │ │ urls.py 230 | │ │ wsgi.py 231 | │ │ __init__.py 232 | └───Computer_Vision_Module 233 | Extract_Faces.py 234 | Load_Dataset.py 235 | Load_Faces.py 236 | Variables.py 237 | 238 | 10. Now we should run our local server to make sure that we have correctly set up our project, run the following command to run local 239 | development server. 240 | 241 | $ ./manage.py runserver 242 | The output should be 243 | 244 | Django version 2.2.4, using settings 'Attendance_Tracking_System_Using_Computer_Vision.settings' 245 | Starting development server at http://127.0.0.1:8000/ 246 | Quit the server with CTRL-BREAK. 247 | 248 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Attendance_Tracking_System_Using_Computer_Vision.settings') 9 | try: 10 | from django.core.management import execute_from_command_line 11 | except ImportError as exc: 12 | raise ImportError( 13 | "Couldn't import Django. Are you sure it's installed and " 14 | "available on your PYTHONPATH environment variable? Did you " 15 | "forget to activate a virtual environment?" 16 | ) from exc 17 | execute_from_command_line(sys.argv) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | django 2 | numpy 3 | Pillow 4 | sklearn 5 | pandas 6 | progressbar 7 | mtcnn 8 | tensorflow 9 | keras 10 | --------------------------------------------------------------------------------