Ich hatte vor längerer Zeit einen Beitrag über Gesichtserkennung auf dem Raspberry veröffentlicht. Vor ein paar Tagen habe ich dieses Script erweitert. Nun ist es möglich sich mittels Gesichtserkennung an der GUI des Raspberrys anzumelden und das sogar, wenn der Benutzer ein Password hat. Dazu habe ich mich ein wenig an den Scripts vom Raspberry bedient. Mittels Rasp-Config kann das Login-Verhalten des PI’s verändert werden. Es gibt die Möglichkeit den Benutzer ohne Password anzumelden(Autologin) oder eben mit. Das alles ist in einer Funktion enthalten, die ich mir zu Nutze gemacht habe.
Damit das Python Script automatisch beim Start mit läuft, habe ich eine neue Systemd Datei erstellt.
/etc/systemd/system/facerecognition.service
[Unit] Description=Facerecognition Python After=network.target [Service] ExecStart=/usr/bin/python3 -u facerec_on_raspberry_pi.py WorkingDirectory=/home/pi/dlib/face_recognition/examples StandardOutput=inherit StandardError=inherit Restart=always User=pi [Install] WantedBy=multi-user.target
Das WorkingDirectory ist der Ort, an dem euer Python Script liegt. Starten wir den Service nun und schauen, ob dieser ordnungsgemäß läuft.
systemctl start facerecognition.service systemctl status facerecognition.service
Es sollte eine Ausgabe wie im Bild erfolgen
Das Python Script hat sich im Grunde nicht geändert, da es nur das Shell Script aufruft. Dafür importieren wir in Zeile 14 das Modul subprocess und verwenden es in Zeile 88, um den Shell Code aufzurufen.
# This is a demo of running face recognition on a Raspberry Pi. # This program will print out the names of anyone it recognizes to the console. # To run this, you need a Raspberry Pi 2 (or greater) with face_recognition and # the picamera[array] module installed. # You can follow this installation instructions to get your RPi set up: # https://gist.github.com/ageitgey/1ac8dbe8572f3f533df6269dab35df65 try: import face_recognition import picamera import numpy as np import os import subprocess import pygame import datetime except: print("failed to load module") exit() # Initialize some variables face_locations = [] face_encodings = [] image = [] known_face_encoding = [] known_faces = [] last_welcome = {} def WelcomePeople(name): #this functions is trying to load the music file in welcome/. #if it cannot find a file a exception raise #if that file exist it is starting a voice message for that recognized person music = name + ".wav" print(music) pygame.mixer.init() try: pygame.mixer.music.load("welcome/" + music) pygame.mixer.music.play() except: print("could not find welcome file") # Get a reference to the Raspberry Pi camera. # If this fails, make sure you have a camera connected to the RPi and that you # enabled your camera in raspi-config and rebooted first. try: camera = picamera.PiCamera() camera.resolution = (320, 240) output = np.empty((240, 320, 3), dtype=np.uint8) except: print("something went wrong while initialize camera") exit() # Load pictures and learn how to recognize it. print("Loading known face image(s)") #is loading all images in faces/ and create a stamp try: for faces,i in zip(os.listdir("faces"),range(len(os.listdir("faces")))): known_faces.append("faces/"+faces) image.append(face_recognition.load_image_file("faces/" + faces)) known_face_encoding.append(face_recognition.face_encodings(image[i])[0]) except: print("could not find known pictures") exit() while True: print("Capturing image.") # Grab a single frame of video from the RPi camera as a numpy array camera.capture(output, format="rgb") # Find all the faces and face encodings in the current frame of video face_locations = face_recognition.face_locations(output) print("Found {} faces in image.".format(len(face_locations))) face_encodings = face_recognition.face_encodings(output, face_locations) # Loop over each face found in the frame to see if it's someone we know. for face_encoding in face_encodings: for face, i in zip(os.listdir("faces"), range(len(known_faces))): # See if the face is a match for the known face(s) if face_recognition.compare_faces([known_face_encoding[i]], face_encoding,0.6)[0]: #print found face all upper case subprocess.call('sudo -S /etc/autologin.sh', shell=True) print("<found: ".upper() + known_faces[i].upper() + ">") #check when the person has been welcomed already. If that person has been welcomed it must wait 10 minutes to hear the message again if not last_welcome: last_welcome[face.split(".")[0]] = datetime.datetime.now() WelcomePeople(face.split(".")[0]) elif face.split(".")[0] not in last_welcome: last_welcome[face.split(".")[0]] = datetime.datetime.now() WelcomePeople(face.split(".")[0]) else: if (last_welcome[face.split(".")[0]] + datetime.timedelta(seconds=10)) >= datetime.datetime.now(): last_welcome[face.split(".")[0]] = datetime.datetime.now() WelcomePeople(face.split(".")[0]) else: print("already greeted")
Neben dem Python Script gibt es noch die Shell Datei. Diese enthält den Part aus der Raspberry Funktion, die ich oben erwähnt hatte. Im Grunde erstellen wir zum Login eine autologin.conf im /etc/systemd/system/getty@tty1.service.d Verzeichnis. In der lightdm.conf entkommentieren wir den autologin-user Flag und geben den Autologin User an. Danach wird lightdm per Befehl neugestartet und die Änderungen rückgängig gemacht. Der PI öffnet nun automatisch den Desktop. Bei einem Neustart muss dann wieder das Password oder die Gesichtserkennung benutzt werden.
#!/bin/sh if [ -e /etc/init.d/lightdm ]; then sudo systemctl set-default graphical.target sudo ln -fs /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty1.service sudo cat > /etc/systemd/system/getty@tty1.service.d/autologin.conf << EOF [Service] ExecStart= ExecStart=-/sbin/agetty --autologin $SUDO_USER --noclear %I \$TERM EOF sudo sed /etc/lightdm/lightdm.conf -i -e "s/^\(#\|\)autologin-user=.*/autologin-user=$SUDO_USER/" sudo systemctl restart lightdm sudo systemctl set-default graphical.target sudo ln -fs /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty1.service sudo rm /etc/systemd/system/getty@tty1.service.d/autologin.conf sudo sed /etc/lightdm/lightdm.conf -i -e "s/^autologin-user=.*/#autologin-user=/" fi exit 0
Leider hat diese Vorgehensweise einen kleinen Hacken. Durch den Neustartet von lightdm, wird der Desktop “neu aufgebaut”. Falls ihr vorher schon angemeldet wart und ihr den PI nur entsperren wollt, werden eure Programme vorher geschlossen. Bisher habe ich dafür noch keine Lösung gefunden.