Skip to content

Commit

Permalink
Only run face recognition on trigger from external notification. (#156)
Browse files Browse the repository at this point in the history
  • Loading branch information
mike4192 authored Nov 27, 2024
1 parent 5012f98 commit d7f0132
Show file tree
Hide file tree
Showing 7 changed files with 251 additions and 136 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# 2.0.2 (2024-11-12)
- Added feature to conditionally trigger face recognition to start and stop via a Magic Mirror notification. Use of this feature is optional. Use for example with MMM-Pir to turn off face recognition when monitor is off, and back on when monitor is on.
- node_helper sends commands to the python child process via its std input upon receiving an external notfication.
- CPU utilization of python process is substatially reduced while face recognition is paused. RPi power consumption also reduced
- Added SIGTERM signal handling to recognition.py so python process reliably stops when Magic Mirror application is terminated
- Improved recognition.py loop timing so the target interval specified by `checkInterval` is better enforced by the main loop

# 2.0.1 (2023-11-01)

- After a lot of install issues. We removed `pipenv` again and changed the install-instructions
Expand Down
13 changes: 13 additions & 0 deletions MMM-Face-Reco-DNN.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ Module.register('MMM-Face-Reco-DNN', {
outputmm: 0,
// turn on extra debugging 0=no, 1=yes
debug: 0,
// If specified, conditionally run face recognition when a notification with a name as specified by this
// option is received with a boolean true/false payload. A True payload activates face recognition, False
// deactivates it. An empty string here disables this functionality so face recognition always runs. Use for
// exmaple with with MMM-Pir with notification name 'MMM_PIR-SCREEN_POWERSTATUS' to only run face
// recognition when screen is on.
external_trigger_notification: '',
},

timouts: {},
Expand Down Expand Up @@ -466,6 +472,13 @@ Module.register('MMM-Face-Reco-DNN', {
Log.log(this.name + ' get logged in users ' + this.users);
this.sendNotification('LOGGED_IN_USERS', this.users);
}

// If an external trigger notification name is specified, forward
// notification payload received on that notification name.
if (this.config.external_trigger_notification !== "" &&
notification === this.config.external_trigger_notification) {
this.sendSocketNotification(notification, payload);
}
},

getDom: function () {
Expand Down
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ This module works in the background, and so no screenshots are available.

The installation is much more simplified now. You can run `npm ci` to install all the node packages and after that it will install all packages with pip. This can take a while to compile the whole opencv stuff.

Be sure that your raspberry pi has enough cooling to do this job, it will be heavy used.
Be sure that your raspberry pi has enough cooling to do this job, it will be heavily used. It is also
likely necessary to increase the available SWAP space for opencv and dlib to succesfully compile. SWAP
can be increased by editing the file: `sudo nano /etc/dphys-swapfile` and changing
the value of `CONF_SWAPSIZE`. 1024 MB was enough to work on a RPi 4 (i.e. `CONF_SWAPSIZE=1024`).

But that this is working you need installed system wide tools before:
For the installation procedure to work, you first need the following installed beforehand system wide:

- node with nvm
- [install instructions](https://github.com/nvm-sh/nvm#installing-and-updating)
Expand All @@ -35,15 +38,16 @@ But that this is working you need installed system wide tools before:
- `sudo apt install libcap-dev`
- install python dependencies
- If you working with Bookworm you need to create first an virtual environment, please have a look in the next chapter
- `pip install face-recognition numpy dlib picamera2 opencv-python`
- Numpy versions 2.0+ do not seem to work with this module
- `pip install face-recognition numpy==1.26.4 dlib picamera2 opencv-python`

### Some additional steps for Bookworm and above to run it with an virtual environment

If you want/need to install it with an virtual environment, you need to do following steps before you install the packages with pip

- create environment with `python3 -m venv ~/python-facereco`
- activate environment with `source ~/python-facereco/bin/activate`
- install pip packages with `pip install face-recognition numpy dlib picamera2 opencv-python`
- install pip packages with `pip install face-recognition numpy==1.26.4 dlib picamera2 opencv-python`
- Because some libraries uses global installed libs which are not available with pip, you need to change the config of your virtual environment
- `nano ~/python-facereco/pyvenv.cfg`
- Change line `include-system-site-packages = false` to `include-system-site-packages = true`
Expand Down Expand Up @@ -166,6 +170,12 @@ To setup the module in MagicMirror², add the following section to the `config.j
outputmm: 0,
// turn on extra debugging 0=no, 1=yes
debug: 0,
// If specified, conditionally run face recognition when a notification with a name as specified by this
// option is received with a boolean true/false payload. A True payload activates face recognition, False
// deactivates it. An empty string here disables this functionality so face recognition always runs. Use for
// exmaple with with MMM-Pir with notification name 'MMM_PIR-SCREEN_POWERSTATUS' to only run face
// recognition when screen is on.
external_trigger_notification: '',
}
}
```
Expand Down
28 changes: 22 additions & 6 deletions node_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ module.exports = NodeHelper.create({
const extendedDataset = this.config.extendDataset ? 'True' : 'False';
const options = {
mode: 'json',
pythonOptions: ['-u'], // Immediately flush buffer for std out/in monitoring/writing to work
stderrParser: line => JSON.stringify(line),
args: [
'--cascade=' + this.config.cascade,
Expand All @@ -38,6 +39,7 @@ module.exports = NodeHelper.create({
'--contrast=' + this.config.contrast,
'--resolution=' + this.config.resolution,
'--processWidth=' + this.config.processWidth,
'--run-only-on-notification=' + (this.config.external_trigger_notification !== '' ? '1' : '0'),
],
};

Expand Down Expand Up @@ -81,22 +83,26 @@ module.exports = NodeHelper.create({
}
});

// Shutdown node helper
self.pyshell.end(function (err) {
if (err) throw err;
console.log('[' + self.name + '] ' + 'finished running...');
});

onExit(function (_code, _signal) {
self.destroy();
});
},

send_python_cmd: function (cmd) {
this.pyshell.send(cmd);
},

python_stop: function () {
this.destroy();
},

destroy: function () {
const self = this
this.pyshell.end(function (err) {
if (err) throw err;
console.log('[' + self.name + '] ' + 'finished running...');
});

console.log('[' + this.name + '] ' + 'Terminate python');
this.pyshell.childProcess.kill();
},
Expand All @@ -112,6 +118,16 @@ module.exports = NodeHelper.create({
this.python_start();
}
}

// Notification for triggering face recognition received. Only send to python subprocess
// if it has been started
if (notification === this.config.external_trigger_notification && pythonStarted) {
if (payload === true) {
this.send_python_cmd('start');
} else {
this.send_python_cmd('stop');
}
}
},

stop: function () {
Expand Down
Loading

0 comments on commit d7f0132

Please sign in to comment.