Function Blocks
Just continuing from the previous post, we will start writing each function that will be assigned to the buttons.
The Button 1
Let’s start with the button 1. This button has the largest function block.
- Pressed in “Detecting” mode to record
- Released in “Recording” mode to go to next mode
- Pressed in “Naming” mode to save the name
### Button 1
def button1_callback(channel):
global cap
global trainingImg
global newTrainer
global mode
global name
global indicator
if mode in {'Detecting', 'Recording'}:
if GPIO.input(Button_1):
if len(trainingImg) > 0:
if newTrainer:
mode = 'Naming'
else:
mode = 'Predicting'
else:
mode = 'Detecting'
else:
while(False == GPIO.input(Button_1)):
if '>'==indicator:
indicator = '+'
else:
indicator = '>'
print('Recording')
mode = 'Recording'
for i in range(5):
ret, frame = cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(frame, 1.3, 5)
for (x,y,w,h) in faces:
trainingImg.append(frame[y:y+h, x:x+w])
print('trainImg:', len(trainingImg))
break
elif 'Naming' == mode:
print('Button 1 Naming mode')
if len(name)>0:
mode = 'Saving'
else:
trainingImg = []
mode = 'Detecting'
Line 3-8: Making global variables available in this function
Line 10: If the program mode is either “Detecting” or “Recording” then execute the lines 11-34
Line 11: If the Button 1 is released then stop recording
Line 12 If there are recorded face images accumulated
Line 13: If nothing in the training file
Line 14: Switch to “Naming” mode to enter a new name
Line 15: If something in the training file
Line 16: Switch to “Predicting” mode to find similar faces
Line 17: If there are no face image accumulated for training
Line 18: Switch to “Detecting” mode to look for faces
Line 19: If the button 1 is pressed
Line 20: Repeat the lines 21-33 while button is pressed
Line 21-24: Alternating letter “+” & “>” to indicate process
Line 26: Switch to “Recording” mode
Line 27 & 28: Get 5th frame of captured video to avoid getting a similar image
Line 29: Converting image colour to grayscale for face detection
Line 30: Detect face within the image using detector
Line 31 – 34: Cut out one face from a frame of image and append to image array used for training later.
Line 35: If the program mode is “Naming” then “Save” execute “Save” actions lines 36-41
Line 36: If a name is given then switch to “Save” mode
Line 37: If no name is given then back to “Detecting” mode
The Button 2
- Pressed in “Naming” mode to pick the previous alphabet
- Pressed in “Predicting” mode to answer “Yes”
### Button 2
def button2_callback(channel):
global mode
global alphabet
global alphabet_index
if 'Naming' == mode:
if not GPIO.input(Button_2):
print('Button 2 Naming mode')
alphabet_index-=1
if alphabet_index < 0:
alphabet_index = len(alphabet) - 1
elif mode in {'Predicting'}:
mode = 'Updating'
Line 3-5: Making global variables available in this function
Line 7: If the program mode is “Naming” then execute lines 8-12
Line 8 -10: If the Button 2 is pressed then pick the previous alphabet
Line 11 & 12: If the alphabet already is “A” then go to “z”
Line 13: If the program mode is “Predicting” then “Yes” is pressed for the predicted name so switch to “Updating” mode
The Button 3
- Pressed in “Naming” mode to pick the next alphabet
### Button 3
def button3_callback(channel):
global mode
global alphabet
global alphabet_index
if 'Naming' == mode:
if not GPIO.input(Button_3):
print('Button 3 Naming mode')
alphabet_index+=1
if alphabet_index >= len(alphabet):
alphabet_index = 0
Line 3-5: Making global variables available in this function
Line 7: If the program mode is “Naming” then execute lines 8-12
Line 8 -10: If the Button 3 is pressed then pick the next alphabet
Line 11 & 12: If the alphabet already is “z” then go to “A”
The Button 4
- Pressed in “Naming” mode to add alphabet to the name
- Pressed in “Predicting” mode to answer “No”
### Button 4
def button4_callback(channel):
global mode
global alphabet
global name
global alphabet_index
if 'Naming' == mode:
if not GPIO.input(Button_4):
print('Button 4 Naming mode')
if len(name) < 11:
name += alphabet[alphabet_index]
alphabet_index = 0
elif 'Predicting'== mode: #Pressed 'No' in predictedName mode
print('Button 4 Predicting mode')
if len(predictedIDset)==0:
resetPrediction()
mode = 'Naming' #Name entry mode
else:
predictedIDset.discard(predictedID)
if len(predictedIDset)==0:
resetPrediction()
mode = 'Naming'
Line 3-6: Making global variables available in this function
Line 7: If the program mode is “Naming” then execute lines 8-12
Line 8 -10: If the Button 3 is pressed and the name isn’t too long
Line 11 & 12: Add alphabet to the name
Line 13 If the program mode is “Predicting” then execute lines 14-22
Line 15-17: If no more prediction then switch to “Naming” mode
Line 19: Remove a prediction
Line 20-22: If no more prediction then switch to “Naming” mode
The Button 5
- Pressed in “Naming” mode to remove alphabet from the name (when the name has some characters)
- Pressed in “Naming” mode to switch back to “Detecting” mode (when the name does not have any character)
- Pressed in other modes to begin shutdown sequence
- Released in other modes to stop shutdown sequence
### Button 5
def button5_callback(channel):
global endProgramCount
global alphabet
global name
global alphabet_index
global mode
global trainingImg
if 'Naming' == mode:
if not GPIO.input(Button_5):
print('Button 5 Naming mode')
if len(name)>0:
alphabet_index = alphabet.index(name[-1:])
name = name[:-1]
else:
trainingImg = []
mode = 'Detecting'
else:
if GPIO.input(Button_5):
endProgramCount = 0
mode = 'Detecting'
else:
while(not GPIO.input(Button_5)):
sleep(1)
endProgramCount += 1
mode = 'Ending'
Line 3-8: Making global variables available in this function
Line 10: If the program mode is “Naming” then execute lines 11-18
Line 11: If the button is pressed
Line 13-15: If the name has some characters, then remove a character from the name
Line 16-18: If the name does not have any character then clear accumulated image and go back to “Detecting” mode
Line 19: If the program mode is not in “Naming”
Line 20-22: If the button is released, then stop & shutdown sequence and back to “Detecting” mode
Line 23-24: Loop line 25-27 while the button is kept being pressed
Line 25: Pause program for a second to allow count down
Line 26: Add 1 to shutdown count
Line 27: Switch mode to “Ending”
Reset Previous Prediction
The next function just simplifies a common operation used 4 times in the program.
### Reset prediction
def resetPrediction():
global predictedIDset
global predictedID
predictedIDset.clear
predictedID = -1
Line 3-4: Making global variables available in this function
Line 5: Clear the set of predicted IDs
Line 6: Set default value to the predicted ID
Pico Voice Output
The PicoSpeech function to make it easier to use Pico Text-to-Speech.
### Speech
def PicoSpeech(speech):
call('pico2wave -w ' + ScriptLocation + '/voice.wav \"' + speech + '\" && paplay ' + ScriptLocation + '/voice.wav', shell=True)
Line 3: Call external command “pico2wave” to record the voice in the “voice.wav” sound file, then use another external command “paplay” (PulseAudio player) to play the “voice.wav”
Shutdown Sequence
The last function is used to shutdown the program.
### Program shutdown sequence
def quit_program(ShutDown):
print('[INFO] Quit Program')
cap.release()
c.close()
conn.close()
lcd.lcd_clear()
lcd.backlight(0)
GPIO.cleanup()
if ShutDown:
call('sudo shutdown -h now', shell=True)
else:
quit()
Line 4: Release the video capturing process
Line 5 & 6: Close the database cursor and the connection
Line 7 & 8: Clear LCD screen and turn off the backlight
Line 9: Clean up GPIO settings
Line 10 & 11: If “ShutDown” is “True” then call an external command to shutdown Raspberry Pi
Line 12 & 13: If “ShutDown” is “False” the simply quit the Python program.
What’s Next?
That is all for the function blocks. The next part “Final Preparation” will be continued in the next post.