MSBOOKS

プログラミングとか深層学習とか日常の出来事とか

深層学習でラブライブサンシャインのキャラクター顔認識をしてみた part3(未知のデータを認識させてみる)

はじめに

前回はモデルの作成から学習までしたので,今回は未知のデータの認識をやっていきたいと思います.

未知のデータへの適用

深層学習ネットワークは適切に学習されれば,学習につかっていないデータを適用しても高い識別率を得ることができます.そこで未知データに適用するためにプログラムを作成していきたいと思います.前回のTrainerクラスのtestメソッドとほぼ同じ形で処理をすることで未知データに適用することができます.
●テストの流れ

  • モデル学習済パラメータを読み込む
  • テスト用画像を読み込む
  • カスケード分類器で顔を抽出
  • モデルへテスト画像(顔)を入力
  • 結果にsoftmax関数を通し,0~8のそれぞれの確率に変換
  • 最も確率の高かった0~8のキャラクター名を対応表から抽出
  • 結果を表示し,画像としても書き出す

ソースコード(test)

・test.py

import csv
import numpy as np
import cv2
import sys

import torch
import torch.nn as nn
import torch.nn.functional as F
from Model import VGG

cascade = cv2.CascadeClassifier('lbpcascade_animeface.xml')
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

chara_list = [] #キャラクター対応表
with open('file.csv','r') as f:
    reader = csv.reader(f)
    for r in reader:
        chara_list.append(r)

#モデルとデータの準備
model = VGG(9).to(device)
param = torch.load("output/model.pth")
model.load_state_dict(param)
model.eval()
FILE_NAME = input("file name : ") #標準入力からファイル名を要求
image = cv2.imread(FILE_NAME, 1)
if image is None:
    print('File Name Error!')
    sys.exit(1)

#顔を抽出
height, width = image.shape[:2]
cascade = cv2.CascadeClassifier('lbpcascade_animeface.xml')
faces = cascade.detectMultiScale(image,
        scaleFactor = 1.1,
        minNeighbors = 4,
        minSize= (24, 24))
if len(faces) > 0:
    (x,y,w,h) = faces[0]
    if(x<0 or y+h>height or x<0 or x+w>width):
        image_face = image
    else:
        image_face = image[y:y+h,x:x+w]
        cv2.rectangle(image,(x,y),(x+w,y+h),(255,255,255),2)
else:
    image_face = image 

image_face = cv2.resize(image_face, (64, 64))
image_face = image_face.transpose(2,0,1)
image_face = torch.Tensor(image_face.reshape(1,3,64,64))
image_face = image_face.to(device)
#モデルへ適用
output = model(image_face)
par, pred = torch.max(F.softmax(output.data, dim=1), 1)
score, chara = float(par), pred
chara_name=''
for cl in chara_list:
    num, name = cl
    num = int(num)
    if chara == num:
        chara_name = name

#結果を標準出力
print('')
print('===========RESULT===========')
print('FILE NAME   : '+FILE_NAME)
print('Character   : '+chara_name)
print('Recognition : '+str(round(score*100, 2))+'%')
print('============================')
print('')

#結果を画像出力
cv2.putText(image, chara_name, (x-5, y+10), 
    cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0, 0, 0))
cv2.putText(image, '('+str(round(score*100, 2))+'%)', (x-5, y+30), 
    cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0, 0, 0))
cv2.imwrite('result.png',image)

今回テスト用画像として以下の曜ちゃんの画像を用意しました.これは学習画像には含まれていません

適用結果は…

なんと80%以上の確率で曜ちゃんに認識できました!キャラクターが少ないからかもしれませんが,精度はかなり高そうです.今回出力として,原画像に顔位置に四角で囲う処理をした画像を書き出す処理もしているので,以下のような画像も同時に得られます.

おわりに

今回3回に渡ってラブライブサンシャインのキャラクター顔認識に取り組んでみました.その結果,アニメキャラクターの顔を抽出するカスケード分類器VGGネットワークを使用することで高い精度で認識できることがわかりました.他にも色々認識させてみたいな~.