DIY Portable Face Recogniser Python Part 1

Start Writing Python Program

A Python program is just a text file.

Use your favorite text editor to create an empty file “main.py” in the Program Folder.

I personally use Notepad++ (link below) but there are so many options you can choose from. https://notepad-plus-plus.org/downloads/

The Program Structure

Program in high-level can be devided into 5 parts:

  1. Initial Preparation & Definition
  2. Function Blocks
  3. Final Preparation
  4. Main Loop
  5. Program Shutdown
The Program Mode

It is also worth noting that I used the “mode” concept to make the program behave differently using the same set of buttons.

  • Detecting – Default mode which device is looking for a face
  • Recording – Capturing faces to update the face recognition model
  • Predicting – Assessing if the captured face already has a name
  • Naming – When a user is entering a new name
  • Saving – Saving a new name and the face recognition model
  • Updating – Updating the face recognition model with the existing name
  • Ending – While in the program shutdown sequence

We will now start writing a program in the empty “main.py” file.

Initial Preparation & Definition

The first part of the program has couple of user configurations and script to make LCD screen working.

#!/usr/bin/env python3.7

#####################################################################
## Author: Taka@FunIncomplete
## Updated: Apr-2020
## Visit: www.FunIncomplete.com
#####################################################################

### User configurations
Reset = False
endProgramAfter = 10

### Preparing LCD screen
import I2C_LCD_driver
lcd = I2C_LCD_driver.lcd()

### Importing other libraries
lcd.lcd_display_string('Importing Libs..'.ljust(16), 1, 0)
print('[INFO] Importing Libs...')

Line 10: Flag “False” to delete database and custom trained model
Line 11: Device shutdown countdown from 10
Line 14 & 15: Prepare LCD screen driver
Line 18: Displaying text “Importing Libs..” on the LCD screen

The next part imports required libraries for this program.

#Importing Libraries
import cv2
import sqlite3
import RPi.GPIO as GPIO
from numpy import array as np_array
from subprocess import call
from os import getcwd
from os import remove
from time import sleep
from pathlib import Path
from datetime import date, datetime

Line 2: OpenCV for face detection & recognition
Line 3: SQLite for database
Line 4: GPIO control to detect button input
Line 5: Numpy array to pass image labels to OpenCV
Line 6: Subprocess to call Pico to speech
Line 7: “getcwd” command to get programme location
Line 8: “remove” command to delete file
Line 9: “sleep” command to pause program
Line 10: “Path” command to check file
Line 11: “datetime” command to show date & time on LCD screen

Prepare global variables.

### Initialising Variables
lcd.lcd_display_string('Init Variables'.ljust(16), 1, 0)
print('[INFO] Init Variables...') 

ScriptLocation = getcwd()
newTrainer = True
newDB = True
NameCursorBlink = True
endProgramCount = 0
mode = 'Detecting'
trainingImg = []
predictedIDset = set()
predictedID = -1
predictedName = '...'
name = ''
msg1 = ''
msg2 = ''
NewSpeech = ''
OldSpeech = ''
indicator = '>'
alphabet_index = 1
alphabet = ['','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',' ','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
WeekDay = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]

Line 2: Show “Init Variables” on LCD
Line 5: Get program location
Line 10: The program start from “Detecting” mode
Line 24: Prepare a letter array for entring name
Line 25: prepare weekday array to convert week number to name

Then delete 3 files that automatically created by program if “Reset” flag is “True”.

### Reset program
if Reset:
	lcd.lcd_display_string('Resetting Data'.ljust(16), 1, 0)
	if Path(ScriptLocation + '/face_recogniser.db').is_file():
		remove(ScriptLocation + '/face_recogniser.db')
	if Path(ScriptLocation + '/face_recogniser.yml').is_file():
		remove(ScriptLocation + '/face_recogniser.yml')
	if Path(ScriptLocation + '/voice.wav').is_file():
		remove(ScriptLocation + '/voice.wav')

Line 2: If Reset flag is True
Line 3: Show “Resetting Data” on LCD
Line 4 & 5: Delete database if exist
Line 6 & 7: Delete trained face recognition model if exist
Line 8 & 9: Delete temporary voice file if exist

Prepare buttons to be detected.

### Initialising buttons
lcd.lcd_display_string('Init Buttons...'.ljust(16), 1, 0)
print('[INFO] Init Buttons...') 
Button_1 = 17
Button_2 = 23
Button_3 = 24
Button_4 = 22
Button_5 = 27 

GPIO.setmode(GPIO.BCM)
GPIO.setup(Button_1, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(Button_2, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(Button_3, GPIO.IN, pull_up_down=GPIO.PUD_UP) 
GPIO.setup(Button_4, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(Button_5, GPIO.IN, pull_up_down=GPIO.PUD_UP) 

Line 2: Show “Init Buttons…” on LCD
Line 4 – 8: Name buttons attached to GPIO
Line 10: Use GPIO numbering instead of BOARD numbering
Line 11-15: Setup GPIO pins to detect when it is connected to ground pin.

Prepare the general face detector.

### Initialising face detector & recogniser
lcd.lcd_display_string('Init Detector'.ljust(16), 1, 0)
print('[INFO] Init Detector...') 
face_cascade = cv2.CascadeClassifier(ScriptLocation + '/haarcascade_frontalface_default.xml')

Line 2: Show “Init Detector” on LCD
Line 4: Tell OpenCV to use “haarcascade_frontalface_default.xml” to classify image

Prepare the database to record names.

### Initialising SQLite database
lcd.lcd_display_string('Preparing SQLite'.ljust(16), 1, 0)
print('[INFO] Preparing SQLite...')  

if Path(ScriptLocation + '/face_recogniser.db').is_file():
	newDB = False
	
conn = sqlite3.connect(ScriptLocation + '/face_recogniser.db')
c = conn.cursor()

if newDB:
	sql = '''CREATE TABLE 'people' ( 'name' TEXT, 'date_created' TEXT )'''
	c.execute(sql)

Line 2: Show “Preparing SQLite” on LCD
Line 5 & 6: Check if the database exists and flag accordingly
Line 8 & 9: Connect/Create database
Line 11 – 13: Prepare the database table if it is a new database

Prepare face recogniser.

### Initialising face recogniser
lcd.lcd_display_string('Init Recogniser'.ljust(16), 1, 0)
print('[INFO] Init Recogniser...') 
recogniser = cv2.face.LBPHFaceRecognizer_create()
if Path(ScriptLocation + '/face_recogniser.yml').is_file():
	recogniser.read(ScriptLocation + '/face_recogniser.yml')
	newTrainer = False

Line 2: Show “Init Recogniser” on LCD
Line 4: Initialise face recogniser
Line 5-7: Read face trained data if exist, and set the flag accordingly

What’s Next?

The Initial Preparation is done. The next part “Function Blocks” will be continued in the next post.