Autor Thema: Raspi + OpenCV (Gesichtserkennung) Verknüpfung mit FHEM - Problem Benutzerrechte  (Gelesen 3367 mal)

Offline renardfm

  • New Member
  • *
  • Beiträge: 14
Hallo zusammen,
ich habe mir über die Feiertage einen dritten Raspi gegönnt und jetzt auch erfolgreich OpenCV ans Laufen gebracht, da ich über diesen besser erkennen möchte wer da ist (Bewegungsmelder lösen bei unseren Katzen zu oft aus, Presence Modul ist tlw. unpraktisch).

Meine letzte Hürde ist aktuell der Aufruf des Python Scriptes. Es scheitert m.E. an den nicht ausreichenden Rechten fhems.
Der Plan ist, dass FHEM das Python Script aufruft um Gesichter zu erkennen - z.B. wenn eine Tür sich öffnet, oder ein Bewegungsmelder auslöst (Erkennungsalgorithmen für Katzen gibt es übrigens auch  ;) ).

In den myUtils habe ich dazu qx() bzw. system() als Aufruf probiert:
sub ActivateOpenCV(){
  my $returnCode=system("python ./home/pi/facereco/reco.py");
}

Das Logfile ergibt nach mehreren Versuchen (Schreibweisen,..):
python: can't open file '~/facereco/recognition.py': [Errno 2] No such file or directory
python: can't open file '~/facereco/recognition.py': [Errno 2] No such file or directory
python: can't open file './home/pi/facereco/recognition.py': [Errno 2] No such file or directory

Ich dachte erst an ein Problem mit Zugriff auf Homeverzeichnis.. also den Scriptordner in das FHEM Verzeichnis kopiert.
Das ergibt folgenden Fehler, da ja weitere Pythonmodule verwendet werden. :
OpenCV Error: Unspecified error (File can't be opened for writing!) in load, file /home/pi/opencv_contrib-3.1.0/modules/face/src/facerec.cpp, line 61
Traceback (most recent call last):
  File "facereco/reco.py", line 10, in <module>
    rec.load("recognizer/trainingData.yml")
cv2.error: /home/pi/opencv_contrib-3.1.0/modules/face/src/facerec.cpp:61: error: (-2) File can't be opened for writing! in function load

Ich dachte schon an Anpassung des Users fhem für Adminrechte.. das finde ich aber schlecht.
Ich bin leider mit Linux nicht besonders virtuos. Mit chown und chmod habe ich bereits rumgespielt, hat aber keine Verbesserung gebracht.
Ein einfacheres Python Skript (Ausgabe der Uhrzeit) habe ich auch aufrufen können.

Habt ihr Ideen?




Zum Nachmachen:

Anleitung für die Installation auf dem Raspi3+ USB Webcam
http://www.pyimagesearch.com/2016/04/18/install-guide-raspberry-pi-3-raspbian-jessie-opencv-3/
Ich habe allerdings keine Virtual Environment verwendet und für Python 2.7 installiert.
Achtung. In OpenCV 3.0 gibt es einen Bug, der verhindert dass die Genauigkeit der Erkennung mit ausgegeben wird (predict confidence).
Vor dem Build, bitte folgenden Workaround durchführen - dann geht es: http://answers.opencv.org/question/82294/cant-get-predict-confidence/

OpenCV Tutorial, auf dessen Basis ich das Python Script geschrieben habe:
https://www.youtube.com/watch?v=oqMTdjcrAGk  --> Teil eins und zwei sind notwendig um das Erkennungsmodell zu trainieren.


« Letzte Änderung: 03 Januar 2017, 21:59:15 von renardfm »
Gefällt mir Gefällt mir x 2 Liste anzeigen

Offline franky08

  • Hero Member
  • *****
  • Beiträge: 4177
  • jetzt DBLog befreit
Ich kann dir da zwar nicht helfen aber wollte dir sagen das ich das ziemlich spannend finde. Wenn du das zum laufen bekommst wäre das auf jeden Fall etwas für WIKI.

VG
Frank
« Letzte Änderung: 03 Januar 2017, 22:50:30 von franky08 »
Debian Wheezy auf ZBOX nano (240GB SSD) FHEM2FHEM an 2xRaspiB
22Zoll ViewSonic als Infodislay (WVC)
3xHMLAN mit vccu ,fhem5.8, WH1080 fowsr an 2.RaspiB
Raspi B mit COC für ESA 2000 und CO2-Sensor
ECMD an AVR-NET-IO mit DAC u. ADC an Junkers Stetigregelung, Siemens LOGO!8, JeeLink

Offline bugster_de

  • Sr. Member
  • ****
  • Beiträge: 849
Hi,

ich habe keine Ahnung, was das python Skript sonst noch so alles aufruft, aber es scheint mir an den User Rechten zu liegen. FHEM läuft unter dem User fhem, der ohne Home Verzeichnis und Passowrt etc. angelegt ist. Der User darf erstmal nicht so viel und er ist auch nicht in der sudo Liste eingetragen. Sprich auch ein Aufruf des Skriptes mit vorangestelltem sudo wird eher nicht gehen.

Frage vorab: dein Skript Pfad ist ./home/pi/facereco/reco.py  Ist das mit dem vorangestellten Punkt so richtig? Ich glaueb eher nein. Denn der erste Punkt heisst "aktuelles Verzeichnis" und dann darunter nach ./home/pi/facereco/. Der absolute Pfad wäre aber /home/pi/facereco/reco.py   also ohne den Punkt.

Schöner ist es erstmal, wenn das Skript direkt ausführbar ist. Dazu wie folgt vorgehen
in der ersten Zeile des Skriptes folgendes eintragen:
#!/usr/bin/env pythonDann das Skript ausführbar machen
sudo chmod u+x /home/pi/facereco/reco.py
sudo chmod g+x /home/pi/facereco/reco.py
jetzt kannst Du das Skript durch direkten Aufruf von /home/pi/facereco/reco.py ausführen (als user pi).

Nun noch dem User fhem die Ausfürhung des Skriptes ohne passwort etc. erlauben:
Du musst den fhem User in der Datei /etc/sudoers eintragen und ihm die Ausführung des Skripts erlauben:
fhem     ALL = NOPASSWD: "/home/pi/facereco/reco.py"
Nun sollte es schon mal gehen und probieren , ob es auch als User fhem funktioniert dann so:
sudo -u fhem /home/pi/facereco/reco.py
Wenn nach diesem Aufruf immer noch Fehler kommen, dann hangele dich mit den entsprechenden Rechten nach obigem Muster durch zu allen den Skripten und Executables die sonst noch aufgerufen werden.

Falls dein Skript eine Datei oder so als Ausgabe erzeugt, dann muß der User fhem natürlich auf das Verzeichnis, wo die Ausgabedatei hinsoll Schreibrechte haben. Ich lege mir für sowas immer eine extra Gruppe im Linux an
sudo addgroup meinegruppe
dann fhem in diese Gruppe aufnehmen
sudo usermod -aG meinegruppe fhemdann den entsprechenden Ordner der Gruppe zuweisen
sudo chown -R pi:meinegruppe /home/pi/ausgabeordnerund den Ordner mit Schreibrechten versehen
sudo chmod g+w /home/pi/ausgabeordner


« Letzte Änderung: 04 Januar 2017, 10:36:28 von bugster_de »

Offline renardfm

  • New Member
  • *
  • Beiträge: 14
Vielen Dank für die Antwort.
Nachdem ich das System neu aufgesetzt habe (anfängerfehler ... sudoers ohne visudo editiert  ;) ), habe ich die Ordner dem user fhem und einer Gruppe zugeordnet. Rechte immer noch nicht ausreichen. Dann allen Ordnern  (sudo chmod -R a+w ..) Schreibrechte zugefügt.
drwxrwxrwx  4 fhem groupcv     4096 Jan  4 23:06 facereco
drwxrwxrwx 12 fhem groupcv     4096 Jan  4 17:53 opencv-3.1.0
drwxrwxrwx  5 fhem groupcv     4096 Dec 17  2015 opencv_contrib-3.1.0

Mit
sudo -u fhem /home/pi/facereco/reco.py
kommt noch der Fehler:
pi@raspberrypi:~ $ sudo -u fhem facereco/reco.py
OpenCV Error: Unspecified error (File can't be opened for writing!) in load, file /home/pi/opencv_contrib-3.1.0/modules/face/src/facerec.cpp, line 61
Traceback (most recent call last):
  File "facereco/reco.py", line 13, in <module>
    rec.load("recognizer/trainingData.yml")
cv2.error: /home/pi/opencv_contrib-3.1.0/modules/face/src/facerec.cpp:61: error: (-2) File can't be opened for writing! in function load

pi@raspberrypi:~ $



dann habe ich mal in den Ordner geschaut:
pi@raspberrypi:~/opencv_contrib-3.1.0/modules/face/src $ ls -l
total 52
-rw-rw-rw- 1 fhem groupcv  5707 Dec 17  2015 eigen_faces.cpp
-rw-rw-rw- 1 fhem groupcv  5719 Dec 17  2015 face_basic.hpp
-rw-rw-rw- 1 fhem groupcv  2894 Dec 17  2015 facerec.cpp


Read und Write - Rechte sind wohl vorhanden..


ich versuche mal alle Ordner/ dateien mit chmod a+rwx  zu versehen...

Offline renardfm

  • New Member
  • *
  • Beiträge: 14
jetzt kommt nur noch der Fehler:
pi@raspberrypi:~/facereco $ sudo -u fhem /home/pi/facereco/reco.py
0
OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cvtColor, file /home/pi/opencv-3.1.0/modules/imgproc/src/color.cpp, line 8000
Traceback (most recent call last):
  File "/home/pi/facereco/reco.py", line 24, in <module>
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.error: /home/pi/opencv-3.1.0/modules/imgproc/src/color.cpp:8000: error: (-215) scn == 3 || scn == 4 in function cvtColor


der Quelltext der reco.py ist:
#!/usr/bin/env python

import os
import cv2
import numpy as np
from PIL import Image

faceDetect = cv2.CascadeClassifier('haarcascade_frontalface_default.xml');
#catDetect = cv2.CascadeClassifier('haarcascade_frontalcatface.xml');

cam=cv2.VideoCapture(0);
rec=cv2.face.createLBPHFaceRecognizer();
rec.load("recognizer/trainingData.yml")

id=0
counter = 0

font = cv2.FONT_HERSHEY_DUPLEX

print(id)

while(True):
   ret,img=cam.read();
   gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

   faces=faceDetect.detectMultiScale(gray,
     scaleFactor=1.3,
     minNeighbors=5,
     minSize=(30, 30),
    )
   for(x,y,w,h) in faces:
      cv2.rectangle(img, (x,y), (x+w, y+h),(255,255,255),2)
      id,conf=rec.predict(gray[y:y+h,x:x+w])

      if(conf<85):
        if(id==4):
          id=str("flo ")
          counter=counter+1
          cv2.putText(img,str(id),(x,y+h),font,1,(0,255,0),2, cv2.LINE_AA);
          print(id + str(counter))
        if(id==5):
          id=str("nadl ")
          cv2.putText(img,str(id),(x,y+h),font,1,(0,255,0),2, cv2.LINE_AA);
          print(id)
      else:
        id=str("?: "+str(int(conf)))
        cv2.putText(img,str(id),(x,y+h),font,1,(0,0,255),2, cv2.LINE_AA);
        print(id)


#   cv2.imshow("Face",img);
   if(cv2.waitKey(1)==ord('q')):
      break;
   if(counter>20):
      break;



cam.release()
cv2.destroyAllWindows()





in der Zeile 21 wird im Prinzip der von der Kamera geholte Frame in Graustufen umgewandelt... kann es sein, dass ein Temp Ordner verwendet wird, den ich nicht berücksichtigt habe??

edit:
wie kann ich prüfen, ob der User fhem Zugriff auf die USB Kamera hat?? Es wäre auch eine Idee, dass kein Frame ankommt.

edit: 07.01:
okay, läuft soweit - die Pfade in den Funktionen mussten absolut angegeben werden. Die Kamera habe ich zusätzlich auch dem User fhem zugeschrieben. Außerdem sollten keine print("...") vorhanden sein, ohne Aufruf einer Konsole kommt sonst ein tty Fehler ...

Nächstes Thema: Das Script so aufzurufen, dass es FHEM nicht blockiert (&) und eine HTTP Methode einbauen, die ein Dummy in FHEM beschreiben kann.
« Letzte Änderung: 07 Januar 2017, 12:35:31 von renardfm »

Offline renardfm

  • New Member
  • *
  • Beiträge: 14
Es geht vorwärts.
Die Übergabe an FHEM wollte ich zunächst als Rückgabewert einer Funktion gestalten. Ich habe jetzt allerdings den Weg gewählt, das über ein HTTP Get mit BasicAuth direkt aus dem Python Skript zu lösen und einen in FHEM angelegten Dummy zu beschreiben. Es handelt sich ja auch um die Hauptinstanz auf einem anderen Rpi.

dazu in das Skript die Library -->import requests einbauen und so aufrufen:
text = "http://192.168.x.y:8083/fhem?cmd.Test=set%20OpenCV%20PersonXY"
      r = requests.get(text, auth=('user', 'passwort'))
         

Wird jetzt dieser Dummy mit PersonXY beschrieben, greift ein DOIF und ruft eine Funktion aus der myUtils auf.
In dieser Funktion kann ich jetzt z.B. abfragen welche Person erkannt wurde und zielorientiert Sprachausgabe über Text2Speech ablaufen lassen :-). Meine Frau interessiert z.B. nicht wie viel Downstream wir hatten oder wie viel kwh Schaltsteckdose xy gemessen hat. Sie hört dann nur, dass die Waschmaschine fertig ist  ::)


Die Geschwindigkeit der Erkennung und vor allem auch Genauigkeit habe ich erhöhen können, indem ich das NoIR picam Modul mit IR-Scheinwerfern verwende (statt anfangs über USB Webcam). Der Stream zur Kamera wird über einen separaten Thread abgegriffen, was auch die Erkennungsgeschwindigkeit massiv erhöht (<2 Sekunden wenn ich in den Erfassungsbereich laufe).
Quelle: http://www.pyimagesearch.com/2015/12/28/increasing-raspberry-pi-fps-with-python-and-opencv/






Offline ralfix

  • Jr. Member
  • **
  • Beiträge: 76
Hallo renardfm
Wo kommen in dem Skript reco.py überhaupt die Pfade her? Das muss man doch irgendwie einstellen?

Ich bekomme auf OpenSuse folgenden Fehler
./reco.py
OpenCV Error: Unspecified error (File can't be opened for writing!) in load, file /home/abuild/rpmbuild/BUILD/opencv-3.1.0/modules/face/src/facerec.cpp, line 61

Der Pfad muss irgendein einkompillierter default sein.

Gruß Ralf


Offline Kuzl

  • Sr. Member
  • ****
  • Beiträge: 875
Hi,

ich hab damit mal mit einem Raspi 2 rumgespielt und hatte bei einer halbwegs guten Framerate eine 100%ige Auslastung.

Wie ist das bei dir?
Welche Framerate hast du und Welche Auslastung des Systems ist damit verbunden?

viele Grüße,
Kuzl

Offline renardfm

  • New Member
  • *
  • Beiträge: 14
Hallo Ralfix,
der Aufruf der OpenCV Bibliothek geschieht so wie ich es verstehe über python. die Bibliothek muss dazu zu Beginn importiert werden. (import cv2).
Die Pfade zu der Datei mit Trainingsdaten (bekannte Gesichter) wie das Haarcascade File muss man selbst angeben (hier die yml Datei und Frontalface...

@Kuzl
Die Framerate hängt stark davon ab welche Auflösung man mit der Kamera abruft. ich habe das 5MP Modul des Raspi verwendet und stelle die Größe 640x480 ein. So umgehe ich mutmaßlich den Flaschenhals USB.
Da der Kamerastream als extra Thread läuft habe ich ungefähr 10 Erkennungen pro Sekunde wenn ich davor sitze und eine Auslastung von ~60% bei vorhandenen Gesichtern und ~30% wenn kein Gesicht im Erfassungsbereich ist. 
(Wenn man sich das Videobild nicht anzeigen lässt ist die Geschwindigkeit höher!)

Hier ist das sehr gut aufbereitet und diente mir auch als Quelle:
http://www.pyimagesearch.com/2015/12/28/increasing-raspberry-pi-fps-with-python-and-opencv/
« Letzte Änderung: 09 Januar 2017, 18:38:58 von renardfm »

Offline Kuzl

  • Sr. Member
  • ****
  • Beiträge: 875
Damit lässt sich sehr gut leben - dann muss ich mir das wohl doch nochmal ansehen  8)
Hatte damals eine USB-Cam und so ein Beispielscript verwendet, das keinen 2. Thread aufmacht.

Offline tomster

  • Sr. Member
  • ****
  • Beiträge: 784
Hab mir jetzt auch mal opencv auf den RasPi kompiliert. Ich musste allerdings einiges "wegkonfigurieren" im cmake, weil sonst der freie Speicherplatz von 3,5GB(!) nicht ausgereicht hätte.
Mein Testscript zum Anzeigen eines Live-Bilds der PiCam mit Default-Face-Cascade brachte es im top allerdings auf 160-250% CPU-Auslastung (RasPi2 und sogar RasPi3)...
Hab noch nicht herausgefunden, warum das soo viel Rechenleistung zieht. Ebenso wenig, warum der raspi die PiCam-Treiber (bcm2835-v4l2) nicht beim Booten automatisch laden mag.

Aber Danke renardfm für's Wecken meines Interesses an diesem usecase. Das kann glaub ich echt gut mit meinem MagicMirror-Projekt zusammenpassen. Gesichtserkennung und/ oder Gestensteuerung des Spiegels wäre echt interessant. Ist zwar sicher noch ein langer Weg, aber egal.

Offline Thorsten Pferdekaemper

  • Developer
  • Hero Member
  • ****
  • Beiträge: 4679
  • Finger weg von der fhem.cfg
Antw:Raspi + OpenCV (Gesichtserkennung) Verknüpfung mit FHEM -
« Antwort #11 am: 17 Februar 2017, 08:28:05 »
Hi,
ist das Thema hier jetzt eigentlich gelöst?
Gruß,
   Thorsten
RasPi
Heizkessel-Steuerung per Arduino und HTTPMOD
und einen Haufen Homematic (Wired)

Offline renardfm

  • New Member
  • *
  • Beiträge: 14
Hallo zusammen. Auf Grund Nachwuchs komme ich nur noch zu sehr wenig momentan  ::) .. ich habe es zum Schluss so gelöst, dass ich basic Auth. in das Skript integriert habe und eine Funktion mit Übergabeparameter (die erkannte Person) direkt als URL aufgerufen habe. Dazu läuft das Skript dauerhaft (wie ein sensor). Die Verarbeitung übernimmt dann das Hauptsystem.

Ich habe es noch nicht im dauerhaften Einsatz. Zum Schluss war die Herausforderung noch eine zuverlässig Erkennung bei verschiedenen Entfernungen, Tageszeiten etc offen. Ein Smart Mirror scheint da eventuell besser geeignet zu sein, da man wahrscheinlich definierter davor steht.

Offline Thorsten Pferdekaemper

  • Developer
  • Hero Member
  • ****
  • Beiträge: 4679
  • Finger weg von der fhem.cfg
Antw:Raspi + OpenCV (Gesichtserkennung) Verknüpfung mit FHEM -
« Antwort #13 am: 18 Februar 2017, 10:07:26 »
Hallo zusammen. Auf Grund Nachwuchs komme ich nur noch zu sehr wenig momentan  ::)
Das kenne ich auch...

Zitat
.. ich habe es zum Schluss so gelöst,
Könntest Du noch so nett sein, vor den Thread-Titel ein [Gelöst] zu packen?
Danke&Gruß,
   Thorsten
RasPi
Heizkessel-Steuerung per Arduino und HTTPMOD
und einen Haufen Homematic (Wired)

Offline tomster

  • Sr. Member
  • ****
  • Beiträge: 784
Ich hab die letzten Tage ein bisschen weiterprobiert.
Die fertige Lösung hab ich zwar noch immer nicht aber eine Idee wie es funktionieren könnte; zumindest im Bezug auf Prozessorlast.
Derzeit geht bei mir eine generelle Gesichtserkennung. Also openCV reagiert auf Gesichter. Dummerweise produziert das aber immer noch eine sehr hohe Prozessorlast (100-140%).
Das liegt wohl vornehmlich am Prozessablauf der Verarbeitung:
RasPiCam -> Raw-Daten werden nach RGB gewandelt -> RGB wird nach schwarz-weiß gewandelt -> openCV packt den Haar-Filter drüber -> Gesichtserkennung

Mein Lösungsansatz dazu ist direkt die Raw-Daten der Kamera zu verwenden. Der Zugriff auf den BAYER-Stream geht aber nur in nativer Auflösung. Da ist dann ohnehin schnell Essig von wegen Prozessorlast und es kommen gerade einmal 1-2 FpS raus. Zu wenig für eine Realtime-Erkennung.
Also habe ich mir etwas anderes überlegt:
Zunächst greife ich über das picamera-Modul in Python auf den YUV-Stream der Kamera zu. Soweit geht es wunderbar.
Nun würde ich aber gerne nur den ersten Channel (Y) ausgeben. Dieser wäre nämlich schon ein wunderbarer Schwarzweißstream. Und hier scheitere ich.
openCV erwartet anscheinend eine Art Array als Input. So wie ich es verstanden habe, müsste man deshalb ein Array "vortäuschen". Sprich man übergibt den YUV-Stream in ein numpy-Array und lässt die beiden anderen einfach Channels "leer".
Erste Versuche mit einem 320*240 kompletten YUV-Bild ergeben bei mir nur eine Prozessorlast von 25-35%. Also eine deutlich Verbesserung im Vergleich zum Ansatz über RGB.
Das dürfte sich sogar nochmals etwas reduzieren, wenn nur der Y-Channel verwendet wird. Eventuell "lohnt" sich sogar der Umweg über den H264-Encoder (weil der ja hardwareaccelerated ist) um die GPU zu entlasten. Ob aber openCV einen H264-Stream verarbeiten kann, hab ich noch nicht herausgefunden.

Nur leider bin ich hier mit meinem Latein Prozeßverständnis/Pythonwissen am Ende. Wenn irgendjemand einen Ansatz hierzu hat, würde ich mich um ein kurzes Reply-Posting sehr freuen. Ansonsten berichte ich natürlich hier über eventuelle Fortschritte.