Fusic Tech Blog

Fusion of Society, IT and Culture

リアルタイムで顔にモザイクをかける
2019/12/03

リアルタイムで顔にモザイクをかける

Fusic Advent Calendar 2019 3日目の記事です。
昨日の記事は、 seike460 による Lambda With RDS Provided Serverless Framework でした。
上から順に実行していくと、PHPを AWS Lambda 上で実行しつつRDSにアクセスできるようになるようです。

さて、本日はFusic 機械学習記事 #2 で行った"リアルタイムで顔にモザイクをかけたい"をどのように実現したかを書いていこうと思います。

環境

手元のMacBook Pro で実行しました。

  • MacBook Pro (13-inch, 2017)
  • 3.3 GHz Intel Core i5
  • 16 GB 2133 MHz LPDDR3
  • Intel Iris Plus Graphics 650 1536 MB

また、pyenvを使って、Python 3.7.4 をインストールしています。

顔認識

顔認識には、以前Twitter で話題になった、
https://github.com/Linzaer/Ultra-Light-Fast-Generic-Face-Detector-1MB
のレポジトリを使わせていただきました。

vision/ssd/mb_tiny_fd.py ファイルから、 create_mb_tiny_fdcreate_mb_tiny_fd_predictorをimportし、
vision/ssd/config/fd_config.py ファイルから define_img_size をインポートします。

そして、

# モデルの準備 
model_path = "models/pretrained/version-slim-640.pth"
define_img_size(640)
test_device = 'cpu'
label_path = "./models/voc-model-labels.txt"
class_names = [name.strip() for name in open(label_path).readlines()]
net = create_mb_tiny_fd(len(class_names), is_test=True, device=test_device)
predictor = create_mb_tiny_fd_predictor(net, candidate_size=1500, device=test_device)
net.load(model_path)

# モザイクをかける処理
def _mosaic(src, ratio=0.05):
    small = cv2.resize(src, None, fx=ratio, fy=ratio, interpolation=cv2.INTER_NEAREST)
    return cv2.resize(small, src.shape[:2][::-1], interpolation=cv2.INTER_NEAREST)

# 画像の読み出し
nparr = np.fromstring(frame, np.uint8)
img_np = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
image = img_np
height, width, _ = img_np.shape
boxes, labels, probs = predictor.predict(image, 1500 / 2, 0.7)

# 検出した顔にモザイクを掛ける
for i in range(boxes.size(0)):
    box = boxes[i, :]
    xmin, ymin, xmax, ymax = box
    xmin, xmax, ymin, ymax = int(xmin), int(xmax), int(ymin), int(ymax)
    tmp = image[ymin:ymax, xmin:xmax]
    image[ymin:ymax, xmin:xmax] = _mosaic(tmp)
frame = cv2.imencode('.jpg', image)[1].tostring()

というふうに書くと、検出した顔にモザイクを書けてくれます。
最後の行で frame = cv2.imencode('.jpg', image)[1].tostring() としているのは、
後述する動画ストリーミングのための処理です。

動画のストリーミング

https://github.com/miguelgrinberg/flask-video-streaming こちらのレポジトリを使用させていただきました。
数点修正を行っております。

app.py を、MacBook Proの内蔵カメラを使うように修正

これは実は予め準備されています。 すなわち、

from camera import Camera

を、

from camera_opencv import Camera

に変更してあげれば完了です。

def gen(camera): の中身を修正

こちらは、上述したモザイクを掛ける処理を書いてあげれば完了です。
ポイントは、 # モデルの準備 の箇所を gen メソッドの外に書くこと。
これを gen メソッド内に書いちゃうと、毎回モデルのロードが実行されるのでとても遅いです。
(実際それをやっていた。)

ここまで修正し、実行します。
すると、 http://localhost:5000 でモザイクが掛かった画像が出力されると思います。
めでたしめでたし。

まとめ

今回は、新たな学習を行わず、ストリーミングされている動画にモザイクを書ける方法を書いていきました。
これを応用すれば、笑い男を表示させたりすることもできるはずです。
また、今回はオープンソースになっているレポジトリを参照させていただきました。
もちろんこのまま本番環境で使用することはできませんが(速度とか複数接続とかの問題がある)、
爆速で開発を行うことができました。
参考にさせていただいたレポジトリの開発者の皆様、大変ありがとうございました。

今回はMac内蔵カメラから映像を撮りモザイクを書けましたが、
一般的にはネットワーク越しでカメラから画像を取得することになると思います。
その場合は、https://qiita.com/tkyko13/items/1871d906736ac88a1f35 等を参考に処理を修正する必要があります。

明日のFusic Advent Calendar 2019は!?

明日は、NaoyaMiyagawaによる、Amazon Athenaも交えたオブジェクトレベルのログ記録&監視方法 です。
どのような内容になるのか自分も知らないので、とても楽しみです。
たぶん、あっと驚くような記事が上がってくると思うので今からとても楽しみにしています。

hamano

hamano

I'm a software engineer in Fukuoka, Japan. Recently, I am developing machine learning models using TensorFlow, and also developing Web services by using PHP.