こんにちは、エンジニアの中西です。

少し前の話ですが攻殻機動隊の新しい映画が公開されましたね。
サイボーグや高度なAIが出てくるSFのお話なので、IT系のエンジニアは割と好きな方が多い気がします。

攻殻機動隊といえば原作に出てくる「人形使い」やTVシリーズのS.A.Cに出てくる「笑い男」と
いった「超特A級ハッカー」が登場します。

そんな「笑い男」の最大の特徴である「顔に描画される笑い男マーク」よろしく
今回は、画像中の顔を認識してエビス君の顔マークに変えていくプログラムを作成します。

以前に当社の筋肉エンジニアの山田が書いた記事の顔認識と画像処理を合わせて笑い男マークではなく、エビス君マークに変えてみましょう。

スクリプトは以下。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cv2
import glob
import os
from PIL import Image

# image/フォルダ内のimgで始まるファイルを一括で読み込む
filelist = glob.glob(‘./image/img*’)
filenum = len(filelist)

for i,image_path in enumerate(filelist):

# 画像を読み込む
img_name = os.path.basename(image_path).split(‘.’)[0]
print “processing: ” + img_name + ” :” + str(i+1) + “/” + str(filenum)
src_img = cv2.imread(image_path)
# 認識精度を高める為にグレースケールに変換した画像を使う。
src_gray = cv2.cvtColor(src_img, cv2.COLOR_BGR2GRAY)

# 顔検出用のファイルを読み込む。実行環境によって適宜変更してください。
cascade_name = “/usr/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml”
cascade = cv2.CascadeClassifier(cascade_name)
faces = cascade.detectMultiScale(src_gray, scaleFactor=1.3,minNeighbors=3,minSize=(30,30))

# OpenCVで画像の重ねあわせが大変なのでPIL(pillow)を利用する。
layer1 = Image.open(image_path)
# 顔をマスクする画像の読み込み。
layer2 = Image.open(‘./ebis.png’,’r’)

# 検出された顔の画像を切り出して保存する
for c, face_tuple in enumerate(faces):
       face_x = face_tuple[0]
       face_y = face_tuple[1]
       face_width = face_tuple[2]
     face_height = face_tuple[3]
       resize_img = layer2.resize((face_width, face_height))
       layer1.paste(resize_img, (face_x, face_y),resize_img)
layer1.save(‘./image/result_’+str(i)+’.png’)

まずは画像処理界のアイドルLenaさんでテスト。

元画像はこちら
lena_before

これに画像処理を行うと、エビス君に!

result_1

なんなく変わりましたね!

つづいて、エビスの営業やサポートのメンバーが多くいる、
東京オフィスの集合写真で試してみます。

東京オフィスのメンバーも…
img_002

エビス君に!
result_2

歴史上の偉人達も…
img_002 (2)

エビス君に。
result_2

と、認識漏れや誤認識もありましたが、このような形で顔を認識してその部分を別の画像に置き換える事ができました。

これを応用する事で、SNSにアップした画像に写りこんでいる周囲の無関係な人のプライバシーを守れるかもしれないですね。 これは既に、Googleではストリートビューで同じような事をしてますね。あと、プリクラで目が大きくなるのも同じようなやり方かもしれません。

動画も静止画像の連続なので同様の処理を行う事で、動画上でも顔を認識、及び置換が可能です。
もちろんコンピュータへの負荷は静止画像よりは高くなります。

最後に、認識漏れや誤認識になる原因についてですが、今回は顔の認識にOpenCVのカスケード型分類器というものを利用していますが、顔の傾きや表情などから標準の学習用データから生成された顔の特徴が条件を満たさない場合は、認識漏れとなり、壁の陰影や服のシワ等が条件を満たす場合には誤認識されます。

これは学習用データを修正する事で精度の改善が見込めますし、顔以外の特徴量を用いることで他の何かを検出させる事ができます。

顔を検出して任意の画像に置き換えることは、S.A.Cが放映された時に流行ったネタなのですが、
久しぶりに思い出したので記事にしてみました。
今回はOpenCVを利用する事で比較的簡単に実装できましたが、OpenCVは他にも様々な画像に対して処理が行えますので、ぜひ活用してみてください。


参考URL
OpenCVで学ぶ画像認識
OpenCVとVisual C++による画像処理と認識
python+OpenCVで顔認識をやってみる
OpenCV2.2 カスケード型分類器