Python
画像処理
OpenCV
python3

python3+openCVでイラストと写真の識別

はじめ

 python3とopenCVを使ってjpg画像が"イラスト"なのか"写真"なのか識別してみました.思っていたよりも参考資料がなかったので,ほぼ自前でやりました.

環境

・ Python 3.6.4
・ Windows 10

 必要なモジュールは以下のとおりです
・opencv-python

 opencv-pythonはpipでインストールできます.

$ pip install opencv-python

識別の手順

  1. 画像ファイルを読み込みむ
  2. 読み込んだ画像(オリジナル画像)をグレイスケール化し以下の画像を得る.(エッジ検出はキャニー法です)
    1. グレイスケール化した画像からエッジ検出した画像(can_img)
    2. グレイスケール化した画像をガウシアンフィルタでぼかしてからエッジ検出した画像(gau_can_img)
    3. グレイスケール化した画像をメディアンフィルタでぼかしてからエッジ検出した画像(med_can_img)
  3. can_imgとgau_can_imgとの差,can_imgとmed_can_imgとの差を計算し,その差を足す.
    (イラストに比べて写真のほうがピントなどでぼけている部分があり,ぼかしを入れる前後で検出されるエッジの変化が大きいと予想したためこの差を識別に使用しました.また,イラストでは描かれているものの輪郭がはっきりしているものが多いと思ったりもしました)
  4. オリジナル画像から各画素のRGBを取得し,最も多く現れる色がどのくらい頻度で現れているのかを算出する.
    (イラストのほうが写真に比べて同じ色が含まれている量が多いと予想したためです)
  5. 3,4で得られた値からスコアを算出して,イラストか写真か判別する.

まとめると...

 「"ぼかしによるエッジ検出量の差"と"画像中で最も多く現れる色の出現頻度"をもとにスコアを算出し,そのスコアが一定以上ならイラスト,一定未満なら写真として識別する」
ということです.

スコアの算出

 スコアは以下の式で算出しています.SCOREが0.5より高ければイラスト,低ければ写真と識別されます.

SCORE = ((1 / diff_result) * 0.8 + (color_result / 100) * 0.2) * 0.625

・ diff_result: 手順3で得られた結果
・ color_result: 手順4で得られた結果

 diff_resultは画像をぼかしたときにエッジ検出量がどのくらい減ったかというものなので,この値が低いほどイラストとしてのスコアが高くなります.
 color_resultは画像中で最も多く現れる色の出現頻度なので,この値が高いほどイラストしてのスコアが高くなります.

 上のスコア算出の計算式は値を見ながら調整したものなので,最適ではないと思います.はい.

 画像データ

 画像データはpixivやフリーの写真素材サイトなどからとってきました.

ソースコード

 githubにおいてあります.
https://github.com/suzuryu/ImageIdentification.git

 画像サイズが大きい場合は,画像サイズを1/2に縮小しています.
識別はかなり大きな画像でなければ0~10秒程度で終わります.
(4032*3024より大きいものはわからないです.はい)

実行

ex) 実行例
 イラストは著作権的なのが面倒なのでイラストやから.

$ python identifiesImage.py exmaple.jpg
score : 0.476 -->picture

example.jpg

$ python identifiesImage.py exmaple2.jpg
score : 0.351 -->picture

IMG_0262.JPG

$ python identifiesImage.py exmaple3.jpg
score : 0.918 -->illust

example3.jpg

結果 意外と良い

score: 0.8581 画像枚数: 2630枚 正解枚数: 2557枚
写真判定: 0.795
イラスト判定: 0.82

 約2600件の画像で全体として識別率85%と結構いい感じに識別できました.写真をイラストとして識別しちゃうのが多かったです.
相性の悪いイラストや写真だと間違った識別をしやすくなると思います.
(写実的なイラスト,証明写真, 風景写真・イラスト etc..)