Edited at

2次元画像(アニメキャラ)顔識別をOpenCVで手軽にやってみた

More than 1 year has passed since last update.


この手のプログラムを作った経緯と作成方針

ここ最近、pythonで2次元画像を中心に画像収集していました。その時、顔認識が出来れば面白いと思い検索してみたら、こんな記事が出てきました。

OpenCVによるアニメ顔検出ならlbpcascade_animeface.xml

どうやら、2次元画像の顔検出はすでにあるみたいです。こちらのリンク先のgithubを見るとlbpcascade_animeface.xmlというファイルを読み込みOpenCVで顔検出しているようです。この方法は「Haar Cascades(カスケード型分類器)」という技術を使っていました。

Haar Cascadesを使った顔検出


ここでは検出を扱う.OpenCVは顔、目、鼻、笑顔など、学習済みの分類器を多数提供している。これらはXMLファイルとしてopencv/data/haarcascades/ディレクトリにある.


また、


OpenCVは学習機と検出器の両方を提供している.自分で(例えば車や植物を検出するための)分類器を作りたければ,OpenCVを用いて機械学習により作ることができる.詳しくは以下の資料を参照のこと: カスケード分類器の学習(英語版)


以上から、OpenCVで画像の学習(機械学習)ができるみたいなのでやってみることにしました。

さらに検索してみたところ、顔識別(キャラ判定)を行っている記事を発見しました。

はじめてのアニメ顔認識 with Chainer



  1. OpenCVとlbpcascade_animefaceを使って、アニメのフレームから顔を切り出し。

  2. そこから誤認識された画像をのぞいて、正解集合に入れる。

  3. 再びOpenCVを使って、顔が認識されなかったフレームを抽出。

  4. 3.の画像から、実際は顔が写っているものを探して、対象の顔を切り出し、正解集合に追加。

  5. 残りは顔が映っていないフレームから、ランダムにcropして、不正解集合に追加。

  6. それぞれの画像を90度、180度、270度回転させて、データを4倍に増やす。

  7. Networkの設計上、入力サイズをそろえる必要があったため、64x64に変換。


この手順通りにやれば顔識別ができると思いました。どうせならと思い自分の好きなキャラを学習させ、識別できるようにしたいと思います。しかし、この記事ではディープラーニングを使っているため、その部分だけをOpenCVに置き換えます(学習器の置き換え)。

20時間程度で完成した方もいるようです。追記:私は丸一日を使い完成しました。

アニメの動画から、画像収集してもいいのですが、せっかくなのでPixivpyを使い、Pixivの画像からSAOのレンを機械学習させてみます。


実行環境


  • Windows10

  • python3.6.1

  • opencv-python 3.4.1.15


実際にやってみる

作るにあたってこの記事を参考にしました。

OpenCVで物体検出器を作成する① ~基礎知識~

基本的にこの記事の手順通りに進めればできます。


はまりどころ


dllファイルが見つからない

dllファイルが見つからないが

openCVで人物特定の分類器を自作


cleatesamplesが見つからない!?......


これで解決できる。(なぜファイルが現在のOpenCVのバージョンに無いかは分かりませんでした...)


複数枚の正解画像から.vec(ベクター画像)を作成したい時

opencv_createsamples.exeを実行してベクター画像を作成する時、上記の参考記事では、正解画像(識別する対象の画像)が1つしかありませんでした。勿論、顔識別する時は明るさが違ったり、表情が変わったりするので1枚の正解画像だけでは判別できるか怪しいです(opencv_createsamples.exeで回転させたりして画像を増やしていますが、念のため正解画像を複数持つのがいいと思います)。例を挙げると

(×)猫の画像を正解画像に使い、動物を識別する。

(〇)猫、犬、ネズミ、サメ、などを正解画像に使い、動物を識別する。

これは、複数枚の正解画像から.vec(ベクター画像)を作成する必要性を意味しています。

opencv_createsamples -info ../positives.txt -vec ../vec/output.vec -num 30 -w 40 -h 40 -bgcolor 255 -maxidev 40 -maxxangle 0.8 -maxyangle 0.8 -maxzangle 0.5 -show

positives.txt

【OpenCV3】複数の正解画像を自分で集めて物体検出器を作る(Mac)

この記事を見て方法と記法を確認しました。注意する点としては、windowsではidentifyなどのコマンドが使えるImageMagickはインストールするとwindows標準のコマンドと名前が衝突するなどと不安な点があります。そのため私はpythonでpos/ディレクトリ以下の.jpgを調べ、Pillowでサイズを調べ、文字列を連結しpositives.txtに書き込みました。

import os

from PIL import Image

path='pos/'
files = os.listdir(path)
text=open(r'positives.txt','a')
for file in files:
im = Image.open(path+file)
w, h = im.size
s=str(path+file)+' 1 1 1 '+str(w)+' '+str(h)+'\n'

text.write(s)

汚いコードです。許してください。


.exe実行時にエラーが出る

opencv_createsamples.exeopencv_traincascade.exe実行時にエラーが出るときは、この記事を参照してください。

OpenCVで物体検出器を作成する⑧ ~エラー対処~


用いた画像

Pixivから、画像を取得

正解画像 30枚

不正解画像 60枚

これで機械学習しました。


学習


  1. Pixivから、正解画像と非正解画像を集める。

  2. lbpcascade_animeface.xmlで顔だけ切り取る。


  3. opencv_createsamples.exeで画像を増やす。


  4. opencv_traincascade.exeで学習。


結果

SAOのレンを機械学習させ、カスケード分類器(.xml)ができました。これを使い、2次元画像(アニメキャラ)顔識別をやってみます。※対象はPixivの画像


結果1

画像に何も加工しないで自作カスケード分類器(.xml)を実行

説明
正解数
確率

レンが映っている画像の識別(他の物体が識別されたら除外)
217枚中47枚
21.6%

レン以外の画像で顔をレン以外と識別(他の物体が識別されたものも含む)
220枚中202
91.8%


結果2

lbpcascade_animeface.xmlでアニメ顔検出を行い、トリミングし、自作カスケード分類器(.xml)を実行(ただしトリミングの時、余計に大きめでトリミングする。トリミングのせいでレンのカスケード分類器で認識できないことがあったため。)

説明
正解数
確率

レンが映っている画像の識別(レンが識別されていればよい)
220枚中84枚
38.1%

レン以外の画像で顔をレン以外と識別
220枚中212枚
95.4%

結果1を見た時萎えましたが、結果2ならば、学習枚数を増やせば精度が上がるのが見込めそう...かな?でも、結果2はトリミングしているので結構手間、実用的ではない。(普通は結果1のように識別したいはず)


おまけ

本来、アニメ画像を識別する時はアニメ画像から学習すべきですが、絵師さんの技量を信じて識別させてみましょう。

追記:顔を枠で囲った画像は「改ざん」により著作権法の違反の対象になるため、画像の引用ができませんでした。


まとめ

機械学習で顔識別するには顔をトリミングした画像が必要なので、自力で集めるのは困難です。潔くツールを使うべきです。さらに、トリミングしなければいけないのでひと手間かかります(顔検出プログラムが必要)。次は、ディープラーニングやりたいですね。


github

https://github.com/ehu-151/animeface