こんにちは! テリーです。リモートワーク楽しんでますか? 我が家はパソコンデスクの後ろに洗濯物が干してあり、テレカンのときに毎日とてもはずかしい思いをしています。そんな人に向けて、無料で手軽に背景ぼかしを入れるテクニックをご紹介します。

2019年春頃、カメラ画像の中から人や体の部位が映っている領域を分割(セグメンテーション)できるオープンソース機械学習モデル、BodyPixがGoogleからリリースされました。このライブラリを使うと、とても短いコードでリアルタイムに背景ぼかしの映像を作ることができます。

ぼかしなしとぼかしありの画像比較

サンプル

サンプルの使い方

まずは上記のサンプルをお試しください(カメラ付きのパソコンやスマートフォンをご使用ください)。「start」ボタンを押してください。カメラ使用許可の確認ダイアログが現れます。「許可」を押すと、左の四角にカメラの生映像が表示されます。数秒から20秒ほど待つと、右の四角に背景ぼかしの映像が再生されます。最初の1回目は5MBの機械学習モデルをダウンロードするため、待ち時間が長く感じます。

(注意) 遅いパソコンやスマートフォンで実行すると、コンピュータが固まったと心配になるほど猛烈に遅くなります。その場合は、ブラウザを強制終了してください。

動作確認: Chrome(Mac), Safari(Mac), FireFox(Mac), Safari(iPhone), Chrome(Android)
すべて2020年6月における最新バージョン

JavaScriptコード解説

CodePenにアクセスすると、上部右側の「JS」にソースコードが表示されます。コードの重要な箇所を説明していきます。

概要

行数 関数 機能
1〜16行目 setupCamera関数 カメラオープンとvideoタグへのアタッチ
18〜30行目 segmentBody関数 カメラ画像から人の領域検出、ボケをつけて描画のループ
32〜34行目 loading関数 ローディングアイコン表示・削除
36〜48行目 start関数 カメラオープン、BodyPix初期化、描画開始

詳細

setupCamera関数

2〜8行目:カメラのオープン処理(横:320ピクセル、縦:240ピクセル、オーディオなし)
10〜15行目:カメラ映像の描画準備が整うまで待機

1   async function setupCamera(videoElement) {
2     const stream = await navigator.mediaDevices.getUserMedia({
3       'video': {
4         width: 320,
5         height: 240
6       },
7       'audio': false,
8     });
9     videoElement.srcObject = stream;
10    return new Promise((resolve) => {
11      videoElement.onloadedmetadata = () => {
12        videoElement.play();
13        resolve();
14      };
15    });
16  }

segmentBody関数

20行目:領域検出処理と結果取得
24〜26行目:ボケ加工描画
27行目:再描画リクエスト
29行目:1度目の描画

18  function segmentBody(input, output, bodypixnet) {
19    async function renderFrame() {
20      const segmentation = await bodypixnet.segmentPerson(input);
21      const backgroundBlurAmount = 3;
22      const edgeBlurAmount = 3;
23      const flipHorizontal = true;
24      bodyPix.drawBokehEffect(
25        output, input, segmentation, backgroundBlurAmount,
26        edgeBlurAmount, flipHorizontal);
27      requestAnimationFrame(renderFrame);
28    }
29    renderFrame();
30  }

loading関数

33行目:ローディングアイコン表示・削除

32  function loading(onoff) {
33    document.getElementById('loadingicon').style.display = onoff ? 'inline' : 'none';
34  }

start関数

40行目:ボタンを2度押すとカメラ停止
44行目:BodyPixモデルのダウンロードと初期化
45行目:描画ループ開始

36  async function start() {
37    loading(true);
38    const input = document.getElementById('input');
39    if (input.srcObject) {
40      input.srcObject = null;
41    } else {
42      const output = document.getElementById('output');
43      await setupCamera(input);
44      const bodypixnet = await bodyPix.load();
45      segmentBody(input, output, bodypixnet);
46    }
47    loading(false);
48  }

まとめ

ご覧のように、たった50行のコードで背景ぼかしが実現できました。
BodyPixには他にも顔モザイク、ドット絵マスク、背景除去、など多数のエフェクトとオプション項目があります。精度をよくするために別の機械学習モデルを使用することもできます。BodyPix本家のドキュメントをご覧いただき、CodePenにアクセスして、このプログラムをベースに修正してみてください。

次回予告

せっかく背景ぼかしを入れられたのですから、この加工映像を使ってテレカンしたいですよね。次回はJavaScriptで加工した映像を配信するテクニックについてご紹介したいと思います。

参考

BodyPix本家:https://github.com/tensorflow/tfjs-models/tree/master/body-pix
CodePen:https://codepen.io/terry_a/pen/PoZmpaz