挨拶
みなさんこんにちは、ブログのスケジュール管理やイラストの勉強中のなおこです。
今回はPythonのOpenCVを用いて2次元キャラクター(アニメやイラストなど)の画像と実写画像を比較する方法をご紹介します。
どうやってやるのか一言で説明するとOpenCVに搭載されている カスケード分類器 という機能を使用します。

イラストと実写を分ける方法
カスケード分類器について調べているとすでに学習されたデータが配布されているようなのでそちらを使用していきたいと思います。
具体的にはlbpcascade_animeface とhaarcascade_frontalface_altを使用します。
haarcascade_frontalface_altはopencvの標準でインストールされているもので顔の検知をすることができます。
lbpcascade_animeface は25000枚のアニメキャラクターの顔画像を用いて作られており、キャラクターの顔検知ができます。
学習されたデータは下記で配布されています。
10年前にすでにイラストの画像認識を行うことができるとは驚きました。
ソースコードを書いてみる
python、opencvのモジュールを入れておいてください。導入が完了している状態で話をすすめます。
python自体はディストリビューションなどでも変わってくるので使っているものに合わせて
opencvの入れ方はfiftystorm36さんのqiitaがわかりやすいです。

HomeBrewでinstallしたOpenCVをpyenvから参照する
pythonでOpenCVを使う一番簡単な方法
python+OpenCVで顔認…
事前の学習されたxmlファイルのデータを元にプログラムをさくっとかきます。
やることは
- ディレクトリからpng、jpgデータをリストアップする
- リストアップした画像と学習されたデータで判定
ファイルの削除などの処理は書かずに判定を行う部分までをソースコードに書き出してみる。
import os | |
import cv2 | |
i_files = [] | |
searchpath = '.' | |
f = [os.path.join(searchpath, path) for path in os.listdir(searchpath)] | |
# png拡張子とjpg拡張子を検索、配列に追加 | |
for i in f: | |
if i.endswith('.png') or i.endswith('.jpg'): | |
i_files.append(i) | |
# pngとjpg拡張子の配列ループ | |
for im in i_files: | |
# 判定配列リセット | |
i_count = [] | |
# 画像をグレースケール | |
gray = cv2.cvtColor( | |
cv2.imread( | |
str(im), | |
cv2.IMREAD_COLOR | |
) | |
, cv2.COLOR_BGR2GRAY | |
) | |
# 学習データの読み込み | |
p = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml') | |
a = cv2.CascadeClassifier('lbpcascade_animeface.xml') | |
# 判定 | |
i_count.append(len(p.detectMultiScale(gray, 1.1, 3))) | |
i_count.append(len(a.detectMultiScale(gray, 1.1, 3))) | |
print(im) | |
if i_count[0] > i_count[1]: | |
print('実写') | |
elif i_count[1] > i_count[0]: | |
print('アニメ') | |
elif i_count[0] >= 1 and i_count[1] >= 1: | |
print('実写とアニメ') | |
elif i_count[0] == 0 and i_count[1] == 0: | |
print('不明') |
プログラムの流れを解説
- pythonの標準ライブラリのosとopencv(cv2)をインポート
- 画像用配列のリセットと検索するpathの変数を定義
- ディレクトリ内のファイルやディレクトリのpathをリストアップし一時的な配列に追加
- 一時的な配列をループ
- 最後の部分がpngまたはjpgかを判定
- pngとjpg拡張子のpathを画像用配列に追加
- 最後の部分がpngまたはjpgかを判定
- 画像用配列をループ
- 判定用の配列をリセット
- 画像を読み込みグレースケール化変数に代入
- 学習されたデータを読み込み
- 判定用の配列に判定結果を追加
- pathを表示
- 判定用の配列で判定
- 判定結果を表示
上記のプログラムと画像、学習されたデータの配置はこんな感じに行えば動くと思います。
- ./
- ー haarcascade_frontalface_alt.xml
- ー lbpcascade_animeface.xml
- ー imgs.py
- ー 画像データ
- ー 画像データ
- ー 画像データetc…
python imgs.pyなどで実行するとアニメか実写か判定した結果が表示されます。
よくドラマなどで2枚の画像比較するようにGUI表示したりしますがあれはドラマの演出

最後に
イラストACとphotoACの素材をそれぞれ100枚(200枚)用意してやってみたらイラスト自体はの50〜60%ぐらい判定できた感じですね。
認識した画像に実写の画像が数枚紛れ込むことがありましたが大量に紛れ込むということはなかったです。
アニメに近い絵柄であれば認識しやすいけど、細かく描き込まれている絵や顔が多少隠れている絵柄は認識しづらかったりするみたいです。
自分で学習データ作ってもっと認識できるもの作ってみたい。
なぜイラストと実写を分けようと思ったかというと
面白そうだから!
やっぱ面白いは大事だと思う!
The post Python イラストと実写を分ける画像処理 OpenCV first appeared on FascodeNetwork Blog.