Trick or (screen) lock!

『画面ロックしないとイタズラしちゃうぞ!』

みなさん、離席するとき画面ロックしてますか?
今の職場はユーモア溢れるので、画面ロックを忘れると、こんな楽しいイタズラが待ち構えてます。

f:id:horihiro:20190407070500p:plain

同僚の成り済ましによって奢り宣言しちゃってます。こっちが奢ってほしいくらいです。

あと、フルスクリーンのWebページのキャプチャ画像を壁紙に設定して、『クリックしても閉じない!』なんてイタズラも見ました。

ユーモアです。「離席時は画面ロックしましょう」という戒めです。

このように、うっかり画面ロックを忘れて離席するとユーモア溢れるイタズラが待ち構えているので、生き残るためには Win + L みたいな画面ロックのショートカットキーも自ずと覚えます。

でも片手じゃ届かないし、急いでいると忘れる、みたいなことも多々あるので、

  • Web カメラで常時顔検出
  • 10秒間くらい、顔が検出できなかったら自動で画面ロック

みたいなオレオレアプリを作ってみました。
# 一応、1、2分くらいはググりましたが、作った方が面白そうだったので、即やめました。

できた

こんな感じです。

github.com

最初の PoC は正味1時間くらいでしたが、その後、常駐アプリっぽい見栄えの細かい修正とかに2日くらい、あとバグがまだまだありますね。

当然、macで確認とかしてないです。持ってないんで。
ただ、OS に依存したコードは書いていない(つもり)です。

使った技術

Electron

最近 Windows しかさわる機会がないのですが、サクッと作りたかったので、Electron を採用です。
C#Windows Formはいまだによくわかっていません。

Shape Detection API

Electron はレンダラープロセスが Chromium なので、Shape Detection APIを使えば、OpenCV とか定義ファイルとか、専用ライブラリを追加せずに、顔検出ができます。
便利な世の中になりました。

Shape Detection APIによる顔検出は、下のりぃさんのブログが参考になりました。
ほぼそのままです。

lealog.hateblo.jp

Chromeの場合、"chrome://flags" から試験運用版ウェブ プラットフォームの機能 ("Experimental Web Platform features")を有効にすることで、使えるようになります。

Electronの BrowserWindow 場合は、new する時にパラメーターで指定してあげれば、同じように Shape Detection API が使えるようになります。

const {BrowserWindow} = require('electron');
const win = new BrowserWindow({webPreferences: { experimentalFeatures: true }});

electronjs.org

画面ロック

画面のロックは専用のモジュールを使ってます。

www.npmjs.com

マルチプラットフォームらしいので、mac でも使えると信じています。

ざっくり動作説明

起動したら、顔検出用の BrowserWindow 上の HTML / javascript で getUserMedia を使って Web カメラの画像を video タグに表示、そこから毎フレームの画像データを引っこ抜いて Shape Detection API の FaceDetector に食わせます。

顔検出を実行してだれもいなかったら、カウントダウン用の BrowserWindow を起動して、setTimeout/setInterval を使って画面ロックまでのカウントダウンを表示します。
その後、カウントが 0 になるまで検出できなかったら、カウントダウン用の BrowserWindow がメインプロセスを介して画面をロックします。

ロックまでカウントダウン中に顔検出用の BrowserWindow が再度顔を検出したら、メインプロセスを介して、キャンセルします。

細かい芸としては、カウントダウン用の BrowserWindow だけは無駄に凝って、時限装置的にしてみました。
カウントダウンの数字用に、けしかんさんの web フォント (今回は DSEG14 )を使っています。

www.keshikan.net

素敵なフォントを公開してくれている、けしかんさんに感謝いたします。

弱点

あげたらキリないですが、個人的にイケてない点だけ。

顔検出がシビア

Chromium の中の話なので、手も足も出ないのですが、顔検出が結構厳しいです。

真横を向くと検出されませんし、コーヒー飲んだり、マスクしたり鼻かんだりしても(花粉症シーズンなので)、無情にもカウントダウンが始まります。

正直 video タグの挙動がわからない

当初、BrowserWindow 上の video タグで画像取得をしている都合上、どこか (他のアプリの裏とかでも可) に BrowserWindow を表示していないと、video タグが表示されず、画像の取得できませんでした。最小化もダメです。

でも、show: false を指定して顔検出用 BrowserWindow 自体を非表示にしたら当然 video タグは表示されませんが、問題なくカメラ画像は更新されていて、顔検出も動作しているようでした。

謎です。

カメラアクセスが不安定

一応、画面ロック&解除の度に顔検出用の BrowserWindow を作り直したりしてますが、たまにカメラ自体へアクセスできなくなります。。。
外付けカメラの場合は挿し直し、内蔵カメラの場合はデバイスマネージャーからいったん無効->有効にしたら、復帰できます(多分)。

モリーの使いっぷりが富豪

Electron アプリ / Chromium の宿命なのか、アプリ内での画像の扱いが下手くそなのかわかりませんが、大量のメモリー使います。

Windows でしか試してません

Electron なのに。
だって、mac持ってないんだもん。

以上です。

しばらく職場の PC で使って、身を守ってみようと思います。

「また下らぬものを作ってしまった」
でわでわ。