Juan Carlos Argueta
Published © GPL3+

SaniStation - Face mask detect sanitize station for Covid-19

Sanitation station for hands and shoes, the procedure detects if the person is wearing a mask on their face, to avoid the spread of COVID-19

IntermediateFull instructions provided2 days6,273

Things used in this project

Hardware components

Raspberry Pi 3 Model B+
Raspberry Pi 3 Model B+
×1
Ultrasonic Sensor - HC-SR04 (Generic)
Ultrasonic Sensor - HC-SR04 (Generic)
×2
Sony PS-3 Eye cam
×1
2k Resistor
×2
Resistor 1k ohm
Resistor 1k ohm
×1
Water pump
×2
Grove - 2-Channel SPDT Relay
Seeed Studio Grove - 2-Channel SPDT Relay
×1

Story

Read more

Schematics

SaniStation electronic diagram

SaniStation electronic diagram

Code

say.sh

SH
Script to receive language and text parameters to be spoken through PicoTTS
#!/bin/bash


if [ "$1" == "EN" ]
then
    pico2wave -l en-US -w  say.wav "$2"
    aplay say.wav
    rm say.wav
elif [ "$1" == "ES" ]
then
    pico2wave -l es-ES -w  say.wav "$2"
    aplay say.wav
    rm say.wav
elif [ "$1" == "BR" ]
then
    pico2wave -l en-GB -w  say.wav "$2"
    aplay say.wav
    rm say.wav
elif [ "$1" == "FR" ]
then
    pico2wave -l fr-FR -w  say.wav "$2"
    aplay say.wav
    rm say.wav
elif [ "$1" == "IT" ]
then
    pico2wave -l it-IT -w  say.wav "$2"
    aplay say.wav
    rm say.wav
elif [ "$1" == "DE" ]
then
    pico2wave -l de-DE -w  say.wav "$2"
    aplay say.wav
    rm say.wav
fi

mask.py

Python
Script in Python that executes the main functions of facial recognition and mask detection, then sends messages to be spoken and activates relays to turn on water pumps at sanitation stations
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
from tensorflow.keras.preprocessing.image import img_to_array
from tensorflow.keras.models import load_model
from imutils.video import VideoStream
import numpy as np
import argparse
import imutils
import time
import cv2
import os


import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
r1=17
r2=18
GPIO.setup(r1, GPIO.OUT)
GPIO.setup(r2, GPIO.OUT)



def say(text_tts):
	os.system('pico2wave -l en-GB -w  say.wav "%s" ' % text_tts)
	os.system("sudo aplay say.wav")
	os.system("sudo rm say.wav")

def detect_mask():
	while True:
		frame = vs.read()
		frame = imutils.resize(frame, width=400)

		(locs, preds) = detect_and_predict_mask(frame, faceNet, maskNet)

		for (box, pred) in zip(locs, preds):
			(startX, startY, endX, endY) = box
			(mask, withoutMask) = pred

			label = "Mask" if mask > withoutMask else "No Mask"
			color = (0, 255, 0) if label == "Mask" else (0, 0, 255)

			if label == "Mask":
				if (max(mask, withoutMask) * 100) > 98 :
					say("You can continue with the hand sanitizing station, follow the instructions.")
					time.sleep(0.5)
					say("Put your hand close and wait for the liquid to be applied.")
					time.sleep(1.2)

					#********** TURN ON HAND SANITIZER 
					GPIO.output(r1,GPIO.HIGH)
					time.sleep(1.2)
					GPIO.output(r1,GPIO.LOW)
					time.sleep(0.5)
					#********** TURN OFF HAND SANITIZER 

					say("Continue with the shoes sanitizing station and wait fot the liquid to be applied.")
					time.sleep(1.2)

					#********** TURN ON HAND SANITIZER 
					GPIO.output(r2,GPIO.HIGH)
					time.sleep(1)
					GPIO.output(r2,GPIO.LOW)
					time.sleep(0.5)
					#********** TURN OFF HAND SANITIZER 

					say("You have completed the protocol to continue, you can enter to the venue")
					time.sleep(0.5)
					say("Remember, it is everyone'sresponsability to mantain social distance.")
			else:
				say("No face mask detected, You cannot enter to the venue")
				say("Please put on a mask to enter")

			label = "{}: {:.2f}%".format(label, max(mask, withoutMask) * 100)

			cv2.putText(frame, label, (startX, startY - 10),
				cv2.FONT_HERSHEY_SIMPLEX, 0.45, color, 2)
			cv2.rectangle(frame, (startX, startY), (endX, endY), color, 2)

		# cv2.imshow("Frame", frame)
		key = cv2.waitKey(1) & 0xFF

		# if the `q` key was pressed, break from the loop
		if key == ord("q"):
			GPIO.cleanup()
			break


def stop_mask_detect():
	# do a bit of cleanup
	cv2.destroyAllWindows()
	vs.stop()

def detect_and_predict_mask(frame, faceNet, maskNet):
	(h, w) = frame.shape[:2]
	blob = cv2.dnn.blobFromImage(frame, 1.0, (300, 300),
		(104.0, 177.0, 123.0))

	faceNet.setInput(blob)
	detections = faceNet.forward()

	faces = []
	locs = []
	preds = []

	for i in range(0, detections.shape[2]):
		confidence = detections[0, 0, i, 2]

		if confidence > args["confidence"]:
			box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
			(startX, startY, endX, endY) = box.astype("int")

			(startX, startY) = (max(0, startX), max(0, startY))
			(endX, endY) = (min(w - 1, endX), min(h - 1, endY))

			face = frame[startY:endY, startX:endX]
			face = cv2.cvtColor(face, cv2.COLOR_BGR2RGB)
			face = cv2.resize(face, (224, 224))
			face = img_to_array(face)
			face = preprocess_input(face)
			face = np.expand_dims(face, axis=0)

			faces.append(face)
			locs.append((startX, startY, endX, endY))

	if len(faces) > 0:
		preds = maskNet.predict(faces)

	return (locs, preds)

ap = argparse.ArgumentParser()
ap.add_argument("-f", "--face", type=str,
	default="face_detector",
	help="path to face detector model directory")
ap.add_argument("-m", "--model", type=str,
	default="mask_detector.model",
	help="path to trained face mask detector model")
ap.add_argument("-c", "--confidence", type=float, default=0.5,
	help="minimum probability to filter weak detections")
args = vars(ap.parse_args())

print("[INFO] loading face detector model...")
prototxtPath = os.path.sep.join([args["face"], "deploy.prototxt"])
weightsPath = os.path.sep.join([args["face"],
	"res10_300x300_ssd_iter_140000.caffemodel"])
faceNet = cv2.dnn.readNet(prototxtPath, weightsPath)

print("[INFO] loading face mask detector model...")
maskNet = load_model(args["model"])

print("[INFO] starting video stream...")
vs = VideoStream(src=0).start()
time.sleep(2.0)


#  Read Ultrasonic proximity sensor
#  If value of sensor if less tha 50 cm call detect_mask
#  and if the value is lather than 2m, continue 
detect_mask()



# If mask detect is true, continue to hand alcohol gel dispeneser
# Read sensor, if the value es less than 15 cm, activate pump to dispense liquid
# and store value: hand = true
# Continue to foot sanitizer station
# Read sensor, if the value es less than 15 cm, activate pump to dispense sanitizer liquid
# and store value: foot = true
# If mask  = true & hand = true & foot = true --> Can coninue to enter and open door
# If any of those variables is false, repeat process from begining.

Credits

Juan Carlos Argueta

Juan Carlos Argueta

2 projects • 7 followers

Comments