OpenCVとTensorFlowを使って里洋平判別器を作る

# はじめに

## 私と里洋平

私と里洋平がはじめて出会っていたはずであろうタイミングは2008年度ヤフー株式会社の新卒研修である。
なぜ、「はずであろう」という言い回しなのかというと当時のヤフー株式会社の新卒採用は250名を超えており、
研修で同チームになるか、配属先の部署が同じでないと面識もないということがザラであった。

入社当時、私はプログラミングの初心者であり、「ポインタって食えるの?」程度だったのに対し、
里は自ら選抜クラス入りを申し出、研修を乗り越えたという話である。
そして配属先も異なっていたため、みごとすれ違いとなってしまったわけである。

その後、私の所属していた部署に後輩として入ってきた@doradora09氏から、
「里が主催となり、TokyoRという勉強会を開催しているので良かったら参加してみないか」と誘われ
たまにではあるがTokyoRで顔を出すようになり、そこでもすれ違いを繰り返していた。

2015年、私は転職などを経て、更にリストラを食らってニート状態であった。
気まぐれで@doradora09氏に連絡を取ってみたところ、
「里が副社長をしているDatumStudioに入ったのでよければ話を聞きに来ないか」ということになった。
DatumStudioのセミナーには過去に参加しており、面白そうな会社だなと思っていた。

話だけのはずが飲み会となり、副社長である里と縁ができたのである。
そして余談ではあるがその場で電卓を叩かれ、入社が決まり現在に至るのである。


## 里洋平とは

里洋平とは言わずと知れた日本を代表するデータサイエンティストの1人であり、
同時にDatumStudio株式会社の副社長でもある。
我々は里洋平を目指すべきである。


## 里洋平検出器の作成

そしてデータサイエンティストであるならば里洋平の特徴量を抽出し把握する必要がある。
その特徴量に近づくよう努力をする必要があるのではないだろうか。

というわけで今回はネットやDatumStudioの内部で収集した画像から里洋平を里洋平たらしめているものを抽出し、
里洋平検出器を作成することにした。

# 本題

## 利用技術と処理の流れ

画像の加工についてはOpenCVを利用し、
特徴量の抽出には深層学習のライブラリであるtensorflowを用います。
言語についてはこれらを包括的に扱えるpython3を選択しました。

処理の流れについては以下のとおりです。

1. 画像収集(人力)
2. 画像加工(OpenCVを使ってグレースケール化、顔識別、顔部分の切り取り、64*64の画像に変換)
3. 画像を里洋平とそれ以外に分類
4. tensorflowを使った学習器の作成
5. 評価

## 環境

AWSでよしななインスタンスを借り、OSはAmazon Linuxとします。

python3で開発を行うにあたってanaconda3を利用して仮想環境を導入しました。

```
conda create -n yohei python=3.5 numpy scipy pandas jupyter scikit-learn matplotlib
source activate yohei
conda install tensorflow
conda install -c menpo opencv3=3.1.0
```

Amazon LinuxをではOpenCVが動かないという問題に当たったため、以下を参考にしました。
http://amazarashi.me/archives/855

## 画像収集

インターネットやDatumStudioで正面からの里洋平画像を募集しました。

<img width="490" alt="advent_2016_03.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/90126/1f1dd5ae-e5fb-0987-9a08-84f980a81f91.png">


## 画像加工

画像加工についてはOpenCVを利用しました。
以下のコードを実行するだけで可能です。

```
import cv2, matplotlib
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import display, Image
import os

def face_detector(img_path, i):
    # 画像読み込み
    img = cv2.imread(img_path)
    
    # グレースケール化
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 顔検出
    img_face = faceCascade.detectMultiScale(img_gray, 1.1, 3)

    # 顔検出できていれば以下の処理へ
    if len(img_face) > 0:
        for rect in img_face:
            x = rect[0]
            y = rect[1]
            width = rect[2]
            height = rect[3]
            # 切り抜き
            dst = img_gray[y:y+height, x:x+width]
            # 64*64にリサイズ
            dst_resized = cv2.resize(dst,(64, 64))
            new_image_path = '出力先ディレクトリ' + str(i) + '.png'
            cv2.imwrite(new_image_path, dst_resized)
            i += 1
        
    return(i)

i = 0

for img_file in file_list:
    full_path_name = '画像置き場'+ img_file
    i = face_detector(full_path_name, i)
```

このようにグレースケール化され64*64に切り取られた顔画像ができます。

<img width="484" alt="advent_2016_01.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/90126/487b91c7-3b22-86f6-16c9-4e5c07be2db3.png">


## 画像を里洋平とそれ以外に分類

人力で画像を里洋平とそれ以外に分類します。
また以下のような正誤判定のラベルをつけたcsvファイルを用意します。
(1だと里洋平、0だとそれ以外)

```
img_0.png 1
img_1.png 0
img_9.png 0
︙
```


## tensorflowを使った学習器の作成

以下を参考にして学習器を作成します。

TensorFlowでアニメゆるゆりの制作会社を識別する
http://kivantium.hateblo.jp/entry/2015/11/18/233834

ここからは後日追記します。
もう少しお待ちを。