深層学習でラブライブサンシャインのキャラクター顔認識をしてみた part3(未知のデータを認識させてみる)
はじめに
前回はモデルの作成から学習までしたので,今回は未知のデータの認識をやっていきたいと思います.未知のデータへの適用
深層学習ネットワークは適切に学習されれば,学習につかっていないデータを適用しても,高い識別率を得ることができます.そこで未知データに適用するためにプログラムを作成していきたいと思います.前回のTrainerクラスのtestメソッドとほぼ同じ形で処理をすることで未知データに適用することができます.●テストの流れ
- モデルと学習済パラメータを読み込む
- テスト用画像を読み込む
- カスケード分類器で顔を抽出
- モデルへテスト画像(顔)を入力
- 結果にsoftmax関数を通し,0~8のそれぞれの確率に変換
- 最も確率の高かった0~8のキャラクター名を対応表から抽出
- 結果を表示し,画像としても書き出す
ソースコード(test)
・test.pyimport 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%以上の確率で曜ちゃんに認識できました!キャラクターが少ないからかもしれませんが,精度はかなり高そうです.今回出力として,原画像に顔位置に四角で囲う処理をした画像を書き出す処理もしているので,以下のような画像も同時に得られます.