『画面ロックしないとイタズラしちゃうぞ!』
みなさん、離席するとき画面ロックしてますか?
今の職場はユーモア溢れるので、画面ロックを忘れると、こんな楽しいイタズラが待ち構えてます。
同僚の成り済ましによって奢り宣言しちゃってます。こっちが奢ってほしいくらいです。
あと、フルスクリーンのWebページのキャプチャ画像を壁紙に設定して、『クリックしても閉じない!』なんてイタズラも見ました。
ユーモアです。「離席時は画面ロックしましょう」という戒めです。
このように、うっかり画面ロックを忘れて離席するとユーモア溢れるイタズラが待ち構えているので、生き残るためには Win + L みたいな画面ロックのショートカットキーも自ずと覚えます。
でも片手じゃ届かないし、急いでいると忘れる、みたいなことも多々あるので、
- Web カメラで常時顔検出
- 10秒間くらい、顔が検出できなかったら自動で画面ロック
みたいなオレオレアプリを作ってみました。
# 一応、1、2分くらいはググりましたが、作った方が面白そうだったので、即やめました。
できた
こんな感じです。
最初の PoC は正味1時間くらいでしたが、その後、常駐アプリっぽい見栄えの細かい修正とかに2日くらい、あとバグがまだまだありますね。
当然、macで確認とかしてないです。持ってないんで。
ただ、OS に依存したコードは書いていない(つもり)です。
使った技術
Electron
最近 Windows しかさわる機会がないのですが、サクッと作りたかったので、Electron を採用です。
C#、Windows Formはいまだによくわかっていません。
Shape Detection API
Electron はレンダラープロセスが Chromium なので、Shape Detection APIを使えば、OpenCV とか定義ファイルとか、専用ライブラリを追加せずに、顔検出ができます。
便利な世の中になりました。
Shape Detection APIによる顔検出は、下のりぃさんのブログが参考になりました。
ほぼそのままです。
Chromeの場合、"chrome://flags" から試験運用版ウェブ プラットフォームの機能 ("Experimental Web Platform features")を有効にすることで、使えるようになります。
Electronの BrowserWindow 場合は、new する時にパラメーターで指定してあげれば、同じように Shape Detection API が使えるようになります。
const {BrowserWindow} = require('electron'); const win = new BrowserWindow({webPreferences: { experimentalFeatures: true }});
画面ロック
画面のロックは専用のモジュールを使ってます。
マルチプラットフォームらしいので、mac でも使えると信じています。
ざっくり動作説明
起動したら、顔検出用の BrowserWindow 上の HTML / javascript で getUserMedia を使って Web カメラの画像を video タグに表示、そこから毎フレームの画像データを引っこ抜いて Shape Detection API の FaceDetector に食わせます。
顔検出を実行してだれもいなかったら、カウントダウン用の BrowserWindow を起動して、setTimeout/setInterval を使って画面ロックまでのカウントダウンを表示します。
その後、カウントが 0 になるまで検出できなかったら、カウントダウン用の BrowserWindow がメインプロセスを介して画面をロックします。
ロックまでカウントダウン中に顔検出用の BrowserWindow が再度顔を検出したら、メインプロセスを介して、キャンセルします。
細かい芸としては、カウントダウン用の BrowserWindow だけは無駄に凝って、時限装置的にしてみました。
カウントダウンの数字用に、けしかんさんの web フォント (今回は DSEG14 )を使っています。
素敵なフォントを公開してくれている、けしかんさんに感謝いたします。
弱点
あげたらキリないですが、個人的にイケてない点だけ。
顔検出がシビア
Chromium の中の話なので、手も足も出ないのですが、顔検出が結構厳しいです。
真横を向くと検出されませんし、コーヒー飲んだり、マスクしたり鼻かんだりしても(花粉症シーズンなので)、無情にもカウントダウンが始まります。
正直 video タグの挙動がわからない
当初、BrowserWindow 上の video タグで画像取得をしている都合上、どこか (他のアプリの裏とかでも可) に BrowserWindow を表示していないと、video タグが表示されず、画像の取得できませんでした。最小化もダメです。
でも、show: false を指定して顔検出用 BrowserWindow 自体を非表示にしたら当然 video タグは表示されませんが、問題なくカメラ画像は更新されていて、顔検出も動作しているようでした。
謎です。
カメラアクセスが不安定
一応、画面ロック&解除の度に顔検出用の BrowserWindow を作り直したりしてますが、たまにカメラ自体へアクセスできなくなります。。。
外付けカメラの場合は挿し直し、内蔵カメラの場合はデバイスマネージャーからいったん無効->有効にしたら、復帰できます(多分)。
メモリーの使いっぷりが富豪
Electron アプリ / Chromium の宿命なのか、アプリ内での画像の扱いが下手くそなのかわかりませんが、大量のメモリー使います。
Windows でしか試してません
Electron なのに。
だって、mac持ってないんだもん。
以上です。
しばらく職場の PC で使って、身を守ってみようと思います。
「また下らぬものを作ってしまった」
でわでわ。