インテージテクノスフィア技術ブログ

株式会社インテージテクノスフィアの社員達がシステム開発や仕事に関する技術情報を随時掲載いたします

インテージテクノスフィアっぽいとは?

こんにちはインテージテクノスフィアのアイダです。技術ブログ第1回目の投稿は当社AI・データビジネス本部のNさんです。

AI・データビジネス本部は当社の主力サービスであるAI事業の中心部署です。はてなブログ開始にあたり、Nさんが私に素敵なプレゼントをくださいました。その作成方法についての投稿です。

ではNさん宜しくお願い致します!

前フリ

皆さんは、日ごろお仕事で外部の人と会った時、こう感じたことは無いでしょうか?

「あ、この人ベンチャーっぽい」とか、「この人、大企業の人っぽいわー」とか。

そんな風に「○○社の人っぽい」といった印象を相手から感じること、ありますよね?あるって言ってくださいお願いします。

なんでも、7割以上の人が初対面での印象を「顔」で判断しているのだそうで、誰かと会った時に感じる「○○っぽさ」の多くは、顔に出ているものと思われます。

働いているうちにその会社の空気感というか、ふいんき(←なぜか変換できない のようなものが身体に馴染んでいって、じわじわと「その会社っぽさ」を感じさせる顔になっていく。そういうことが起きているのかもしれません。怖い。

社外の人と会った時に「○○社っぽい」感じを受ける、かつ、人は受ける印象を顔で判断することが多い、のであるならば、インテージテクノスフィアでも同じことが言えるはずです。 つまり、インテージテクノスフィア社員はそれぞれがインテージテクノスフィアっぽい顔をしている(はず)。

と、いう事は。

インテージテクノスフィア社員の顔を全員分混ぜたら、とてもインテージテクノスフィア社員っぽい顔ができるのでは?

面白そうなので検証してみたいと思います。

早速インテージテクノスフィア社員の顔を混ぜてみましょう。

インテージテクノスフィア社員顔を作ってみる

「平均顔」というものをご存知でしょうか?

要は人の顔写真を何重にも重ね合わせて作り出される顔の事で、重ね合わせた顔の「平均」をとった顔とも言えますね。

http://news.line.me/issue/oa-shujoprime/aea7a0809905 

リンク先(週刊女性PRIMEさん記事)の画像左側の女性が2000年代のドラマ主演女優の平均顔、右側の女性が2000年までのドラマ主演女優の平均顔だそうで、ふいんき(略 はかなり違いますね。

混ぜる素材によって平均顔に違いが出るので、インテージテクノスフィア社員の顔を混ぜた平均顔はインテージテクノスフィア社員っぽいふいんき(ry 顔になるのではないでしょうか。

顔写真を集める

平均顔作成に必要なのは顔写真(なるべく正面)ですが、これにピッタリのものが社員情報データベース。

画面に表示された社員情報データはお誂え向きに正面顔画像!

早速コピーしてみましょう!

f:id:intage-tech:20200108211122j:plain:w500

なん…だと…

セキュリティと利便性はトレードオフですし止むを得ません。ページからの直接コピーはできないので、画面のスクリーンショットから写真だけ切り出します。

が、全社員分これを繰り返すとかちょっと無理があるので、規模を大幅に縮小し「AI・データビジネス本部の男性社員顔」を作ることにします。

スモールスタート大事。18人分をせっせとコピーした結果が以下です。

f:id:intage-tech:20200127190034p:plain:w500

これを使って顔を重ねてみます。

顔画像を重ねて平均顔を作る

顔画像を重ねるといってもそのまま重ねれば良いというものではありません。 ズーム気味に写っている人がいたり、遠目に写っている人がいたり、目や鼻など、各パーツの位置や角度なんかも調整する必要があります。

画像処理系ライブラリOpenCVのチュートリアルサイト、LarnOpenCVにあった平均顔作成のチュートリアル https://www.learnopencv.com/average-face-opencv-c-python-tutorial/を参照したところ、平均顔の作成には以下の4ステップが必要との事。

 Step 1 : Facial Feature Detection (顔の特徴検出)

 Step 2 : Coordinate Transformation (座標の変換)

 Step 3 : Face Alignment (顔の位置合わせ)

 Step 4 : Face Averaging (顔の平均化)

…英語を必死に解読しましたが、分かったような分からんような(分かってない)。

ドロネー三角形分割(Delaunay Triangulation)…あー、はいはい、そういうことね、なるほどなるほど(分かってない)。

サンプルコードの実行

とても親切なことにチュートリアルページでサンプルコードがダウンロードできるようになっていたのでこれを試してみたいと思います。コードにデータも同梱されている親切設計。素敵。

そのまま動かせそうなので、zip展開後のディレクトリにある faceAverage.py をとりあえず実行してみます。習うより慣れろ。

上手くいけば大統領の平均顔が表示されるはずです。

Let's 平均顔!(合言葉)

f:id:intage-tech:20200128094151p:plain

なん…だと…(2回目)

調べてみると xrange はpython2.x系のみで使用可能で、3.x系では range に統合されているとの事。ソースを書き換えて、xrange→range にしてみましたが、今度は opencv のエラーが発生。こちらは今のopencvのバージョンでは既に廃止されたメソッドが使われていることによるものでした。動かす前に動作環境をちゃんと確認しろって事ですね。反省。

遅れましたが、今時点の環境情報は以下の通りとなります。

  • python : 3.6.5 (Anaconda 4.6.14)
  • opencv : 4.1.2

サンプルコードがpython2.x系で書かれている+それに合わせたopencvのバージョンになっているので、現環境でのコード実行は難しそう…

うーむ、困った。

こんなとき、どうするか。

解決するのはさほど難しくありません。そう、Anacondaならね(ステマ)

仮想環境をつくる

Anaconda では仮想環境をつくることができます。

python自体のバージョンや必要ライブラリのバージョンが異なる複数の環境を作ることができるので、こういった実験的な作業をするときにはとても便利ですね(ステマ)

サンプルコードを動かすため、python2.x系+opencv の仮想環境をつくってみましょう。

手順は以下の通り。

  1. Anaconda Prompt を起動
  2. conda create -n 環境名 python=2.7 でpython2.7の環境を作る
  3. conda activate 環境名 で環境を有効化
  4. conda install ライブラリ名 で必要なライブラリ(opencvとか)をインストール

4のインストールですが、python2.x系に対応した opencv がAnacondaの標準リポジトリにはなさそうだったので、-c オプションでチャネルを conda-forge に指定します。

コマンドは↓のような感じになります。

仮想環境構築コマンド例

(base) D:\test\FaceAverage\FaceAverage>conda create -n py27 python=2.7
Collecting package metadata (repodata.json): done
Solving environment: done
…
(略)
…
# To deactivate an active environment, use
#
#     $ conda deactivate
 
 
(base) D:\test\FaceAverage\FaceAverage>
(base) D:\test\FaceAverage\FaceAverage>conda activate py27
 
(py27) D:\test\FaceAverage\FaceAverage>conda install -c conda-forge opencv=2.4.13
Collecting package metadata (repodata.json): done
Solving environment: done
…
(略)
…
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
 
(py27) D:\test\FaceAverage\FaceAverage>

サンプルコードの実行(2回目)

環境が整ったところで再度サンプルコード faceAverage.py を動かしてみます。

Let's平均顔!(2回目)

f:id:intage-tech:20200128094553p:plain

キタ―――(゚∀゚)―――― !!

なんかもう終わってもいいような感じがしてきましたが、まだ道半ばです。 やっとサンプルコードが動かせたところ。先は長いですね。

顔の特徴点座標を抽出する

さて、サンプルコードに付いてきたデータの置き場所(presidentフォルダ)を見ると、写真と同じ名称のテキストファイルが入っています。 中には68行2列の数字の羅列。なんぞこれー。

f:id:intage-tech:20200128094714p:plain

チュートリアルによると、この数字はdlibというライブラリを使用して抽出できる、顔の68か所の特徴点の座標(68 facial landmarks using dlib)のようです。サンプルコードの中で画像と共にこの特徴点座標ファイルも読み込んでいるので、自分で用意した写真で平均顔を作るときには、この特徴点座標ファイルも用意する必要があるようです。 めんどくさい。早速用意しましょう。

まずはdlibとimutilsをインストールします。 先ほどのopencvと同様に、-c オプションで conda-forge を指定しました。 インストール時のコマンド例はこちら↓

コマンド例

(py27) D:\test\FaceAverage\FaceAverage>conda install -c conda-forge dlib
Collecting package metadata (repodata.json): done
Solving environment: done
…
(略)
…
 
 
(py27) D:\test\FaceAverage\FaceAverage>conda install -c conda-forge imutils
Collecting package metadata (repodata.json): done
Solving environment: done
…
(略)
…
 
(py27) D:\test\FaceAverage\FaceAverage>
(py27) D:\test\FaceAverage\FaceAverage>

あと、dlibでの特徴点座標の抽出にはデータセットが必要っぽいので、http://dlib.net/files/ から shape_predictor_68_face_landmarks.dat.bz2 をダウンロードして同じフォルダに展開して置いておきます。 dlibを使った顔の特徴点座標ファイルを作るサンプルコード (createFaceLandmark.py) は以下の通りです。

( https://www.pyimagesearch.com/2017/04/10/detect-eyes-nose-lips-jaw-dlib-opencv-python/ を主に参考にさせて頂きました。)

処理の流れとしては

  1. 検出器・特徴抽出器を用意
  2. 顔画像を読み込み(&色chをopencv用に変更)
  3. detector で顔領域を検出
  4. 検出した顔領域内で、顔の特徴点68か所を抽出
  5. 抽出した座標をファイル出力

といった感じになります。

顔の特徴点抽出(createFaceLandmark.py)

# -*- coding: utf-8 -*-
import cv2
import dlib
import glob
import numpy as np
import os
 
from imutils import face_utils
 
# 1.検出器・特徴抽出器を用意
detector = dlib.get_frontal_face_detector() # 顔の検出器
PREDICTOR_PATH = "shape_predictor_68_face_landmarks.dat" # 特徴量データファイル
predictor = dlib.shape_predictor(PREDICTOR_PATH) # 特徴抽出器
 
def create_face_landmark_file(dir_path):
    img_path_list = glob.glob(os.path.join(dir_path, "*.png"))
 
    for img_num, img_path in enumerate(img_path_list):
        print(img_num, img_path)
        landmark_txt = os.path.splitext(img_path)[0]+".txt"
 
        # 2.画像の読み込みと色ch変更
        img = cv2.imread(img_path)
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
 
        # 3.顔の検出
        faces = detector(img) 
        for rect in faces:
            shape = predictor(img, rect) # 4.検出した領域の中で特徴点抽出
            shape = face_utils.shape_to_np(shape) # 抽出座標をnumpy化
 
            np.savetxt(landmark_txt, shape, fmt="%.0i") # 5.抽出座標をファイル出力
 
if __name__ == '__main__' :
    create_face_landmark_file(".\\aid_face")

できたテキストファイルを開いてみると…

f:id:intage-tech:20200128095140p:plain

お、なんかいい感じ?それっぽいファイルが出来てる。

AID本部平均顔の作成

ようやくここまで来ました。集めてきた画像と、dlibで作成した特徴点座標ファイルを使って、AI・データビジネス本部男性社員の平均顔を作ってみましょう。

faceAverage.py の画像フォルダパスを少しいじって…(193行目辺りの path = 'president' を 'aid_face' に変える)

Let's 平均顔!(3回目)

f:id:intage-tech:20200128095413p:plain

キタ―――(゚∀゚)―( ゚∀)―(  ゚)―(  )―(  )―(゚  )―(∀゚ )―(゚∀゚)―――!!

…おおぅ…誰かに似てる気もするけど明確に誰とも言いきれない感じもある…

これがAI・データビジネス本部男性の平均顔かー。いやー、できたできた。ここまで長かった。ほんとに。

AI・データビジネス本部=AID本部男性社員の平均顔、は呼びづらいのでAID本部のAさん、略してアイダ(AID-A)さんと呼ぶことにしたいと思います。

やってみて

AI・データビジネス本部男性社員の平均顔、通称アイダさんの顔写真作成をやってみました。

いやー、楽しかった。

楽しかったんだけど、技術的要素をもう少しちゃんと理解してやればもっと色々と遊べたと思うので、そこは精進が必要ですね。python2.x系は2020年1月1日にEOL迎えたことですし、せめて3.x系で実行できるようにしたかった…

あと、全社員への拡張は作業量的に厳しかったので見送りましたが、機会があればやってみたいところです。社内のRPAツールとかでサクッと出来たりしないかなー。

各本部ごとの平均顔がどんなふいんき(ryになるのか、全てを混ぜたインテージテクノスフィア社員顔が一体どんな風になるのか…私、気になります!

以上。 ここまでお読みいただきありがとうございました。

おまけ:環境情報

今回のソース類のフォルダ階層は以下のような感じになります。

FaceAverage

├ aid_face ( 集めた顔画像フォルダ)

├ president ( サンプル画像フォルダ)

├ createFaceLandmark.py ( 顔の特徴点座標ファイル作成コード)

├ faceAverage.py ( 平均顔作成サンプルコード)

└ shape_predictor_68_face_landmarks.dat ( 顔の特徴点抽出用データセット)

各種バージョンは最終的に以下のようになりました。

  • python : 2.7.17
  • opencv : 2.4.13
  • numpy : 1.11.3
  • dlib : 19.0
  • imutils : 0.5.3

アイダ頑張ります。

ということで私アイダの名前と顔はNさんが作ってくださいました!実際にはAI・データビジネス本部男性社員顔ですが、許可を頂いたので私の顔ということになりました!今後顔を出す際にはこの顔写真を使いたいと思います。

投稿へのご質問などは、お問い合わせページ、およびはてなブックマークでのコメントなどで頂けるとありがたいです。引き続きインテージテクノスフィア技術ブログを宜しくお願い致します。