nischi / MMM-Face-Reco-DNN

Face recognition with opencv and deep neural network
MIT License
90 stars 46 forks source link

Suspend Face Recognition process #132

Open fred2nice opened 1 year ago

fred2nice commented 1 year ago

Hi,

Everything works fine, thank you so much 👍

I would like to know if there is a way to suspend "modules/MMM-Face-Reco-DNN/tools/facerecognition.py" I have a sensor light to power off the screen when no light, and power on the screen when light is detected. I would like to suspend the face recognition if no light to avoid CPU heating. I don't know if it's easy to do, or not, if you could listen notifications by example FACE_RECO_PAUSE and FACE_RECO_RESUME it would be wonderful ;-)

King regards Fred

nischi commented 1 year ago

Hi @fred2nice

Thank you for using my module. Hmm thats a good case. But at the moment it is not supported to do this. But i marked this as enhancement. Maybe i do have some time to implementing this. Or you have time to do so and create a pull request :)

goldyfruit commented 1 year ago

Just wondering, not sure if it's possible to implement, but maybe instead of a light sensor, the camera could be used to detect if there is light as facerecognition.py is always running.

Maybe this could inspire (it's in Node.js...) https://github.com/skrollme/homebridge-picamera-lightsensor/blob/master/index.js

nischi commented 1 year ago

Interesting thoughts. Need to check this.

fred2nice commented 1 year ago

It's possible, but it will still cost cpu, I did it in another dev if no light stop screen, send mqtt message etc, and finally I change my mind and use a simple light sensor. A system with MMM notifcation could be used by several other modules.

Below my piece of code to test brightness. My camera is hidden behind the mirror, a servo motor allows it to be positioned when the light is on, and it is retracted when the light is off. I would like to add gesture recognition in same time ( shutdown the screen, trigger actions etc ) , but right now too heavy to do ,-)


    print("Capturing image.")
   # Grab a single frame of video from the RPi camera as a numpy array
   camera.capture(output, format="rgb")
   # if no light nothing to do.
   with picamera.array.PiRGBArray(camera) as stream:
       camera.exposure_mode = 'auto'
       camera.awb_mode = 'auto'
       camera.capture(stream, format='rgb')
       pixAverage = int(np.average(stream.array[...,1]))
   print ("Light Meter pixAverage=%i" % pixAverage)
   if (pixAverage<50):
    if screenIsOn == "1" :
      if alreadyDown == 0:
          os.system("/home/pi/downCam.py")
          alreadyDown = 1
          alreadyUp = 0
      client.publish("MMM-Face-Recognition-MQTT/Screen","OFF")
      time.sleep(4)
      os.system(stopScreen)
    continue
    else:
     if screenIsOn == "0" :
        if alreadyUp == 0:
           os.system("/home/pi/upCam.py")
           alreadyUp = 1
           alreadyDown = 0
        os.system(startScreen)
     client.publish("MMM-Face-Recognition-MQTT/Screen","ON")
     time.sleep(5)
     os.system(startScreen)

To go fast, I just add a file exists test inside facerecognition.py, not pretty, put simple to do ,-)

124 while True:
125         # grab the frame from the threaded video stream and resize it
126         # to 500px (to speedup processing)
127         while not os.path.exists('/tmp/light.on'):
128             printjson("status", "Pas de lumiere pas de cam !")
129             time.sleep(args["interval"] / 1000)
nischi commented 1 year ago

true, this cost cpu time. i think i can implement the message thing. Or you can do if you have time :)

fred2nice commented 1 year ago

Ok, I think there is at least two ways to do it. The simple way, use Linux OS feature, kill -STOP and kill -CONT. node_helper.js, inside socketNotificationReceived

   if (notification === 'FACE_RECOGNITION') {
      if (pythonStarted) {
              if (payload=="PAUSE"){
                        this.pyshell.childProcess.kill(19);
              }
              if (payload=="RESUME"){
                        this.pyshell.childProcess.kill(18);
                }
      }
   }

MMM-Face-Reco-DNN.js inside notificationReceived

    if (notification === 'FACE_RECOGNITION') {
      this.sendSocketNotification('FACE_RECOGNITION', payload);
    }

So now to pause/resume recognition, use FACE_RECOGNITION with PAUSE or RESUME payload

Other way, use signals to set a sleep inside may loop of facerecognition.py. This way is not the best, because CPU is used by while True, but it's more os independant

( can't use SIGSTOP, so I used SIGABRT )

def signalHandler(signalnum, frame):
        global closeSafe, pauseRecog
        if signalnum == signal.SIGINT:
            printjson("status","SIGINT")
            closeSafe = True
            return
        if signalnum == signal.SIGCONT:
            printjson("status","SIGCONT Resume facerecognition")
            pauseRecog = False
            return
        if signalnum == signal.SIGABRT:
            printjson("status","SIGABRT Pause facerecognition")
            pauseRecog = True
            return

signal.signal(signal.SIGINT, signalHandler)
signal.signal(signal.SIGCONT, signalHandler)
signal.signal(signal.SIGABRT, signalHandler)
closeSafe = False
pauseRecog = False
        while pauseRecog:
            printjson("status", "facerecognition paused")
            time.sleep(args["interval"] / 1000)