在從二次元畢業之前,我們經常都會看到"這個人物是誰?哪個番的?"之類的問題,在學習圖像識別的過程中,實現了一個動漫人物的識別的例子,直接使用現有的兩個成熟的工具OpenCV與 ImageAI通過人物頭像來進行動漫人物的識別,作爲一個入門的例子。而在實際情況下,動漫人物時有撞臉的情況發生,這個時候還需要通過服飾,甚至結合知識圖譜關聯圖像中出現的其他角色來進行更加精確的識別。下面直接上demo:
一、獲取圖像中的人物頭像:
這裏首先使用fate的一張圖像作爲例子,代碼如下:
1、引入必要的庫:
import cv2
import sys
import os.path
2、使用opencv進行動漫人物頭像的提取,這裏採用某宅界前輩提供的lbpcascade_animeface.xml:
cascade = cv2.CascadeClassifier('../lbpcascade_animeface.xml') #引入xml
image = cv2.imread('timg8.jpg', cv2.IMREAD_COLOR) #讀入一幅彩色圖片
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #色彩空間轉換
gray = cv2.equalizeHist(gray)#圖像直方圖均衡化
faces = cascade.detectMultiScale(gray,
# detector options
scaleFactor = 1.1,
minNeighbors = 5,
minSize = (24, 24))
3、展示人物頭像提取的結果,並把提取的頭像切割下來保存在faces文件中,爲後續的識別做準備:
i = 0
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
face = image[y: y+h, x:x+w, :]
face = cv2.resize(face,(96,96))
save_filename = '%s_%d.png' % (os.path.basename(filename).split('.')[0],i)
cv2.imwrite("faces/"+save_filename,face)
i = i + 1
cv2.imshow("AnimeFaceDetect", image)
cv2.waitKey(0)
cv2.imwrite("out2.png", image)
頭像識別的結果:
faces文件中保持的頭像:
二、使用ImageAI 進行模型的訓練,由於本機性能有限,這裏只做實例,對四個人物進行訓練,每個人物訓練集15張,測試集5張(實際使用中請使用高性能的機器進行,圖像的數量也建議在400-600張左右,圖像質量較好):
1、準備訓練集和測試集,這裏對四個角色進行訓練:
2、訓練代碼如下:
from imageai.Prediction.Custom import ModelTraining
model_trainer = ModelTraining()
model_trainer.setModelTypeAsResNet()
model_trainer.setDataDirectory("pg") #訓練的目錄
model_trainer.trainModel(num_objects=4, num_experiments=50, enhance_data=True, batch_size=5, show_network_summary=True)
使用imageai工具,代碼非常精簡。通過ResNet模型進行訓練,訓練對象爲4個,訓練50次,每批次訓練5張,生成副本並在控制檯打印訓練過程。
3、訓練結果:
訓練結果包括json和models。其中json表面了對象對象的索引值。models中是每次訓練的結果,其中ex-後面的是訓練的次數,0.450000是此次訓練在測試集上的精準度,可以看到訓練20次精準度是0.45(最大是1).
4、通過訓練的結果在識別提取的頭像:
from imageai.Prediction.Custom import CustomImagePrediction
import os
execution_path = os.getcwd()
prediction = CustomImagePrediction()
prediction.setModelTypeAsResNet() #設置ResNet模型
prediction.setModelPath(os.path.join(execution_path, "pg/models/model_ex-040_acc-0.800000.h5"))
prediction.setJsonPath(os.path.join(execution_path, "pg/json/model_class.json"))
prediction.loadModel(num_objects=4)
predictions, probabilities = prediction.predictImage(os.path.join(execution_path, "timg8_2.png"), result_count=1)
for eachPrediction, eachProbability in zip(predictions, probabilities):
print(eachPrediction + " : " + eachProbability)
圖像預測的代碼也比較簡潔,設置使用ResNet模型,採用的json和h5文件(訓練結果),要預測的圖像和預測的結果數量,最後打印出預測的結果:
最終預測是saber的概率是85%。
以上demo採用現有的庫,實現過程也比較簡單。但是在實際使用中還需要注意很多影響訓練和預測結果的問題,比如圖像的質量,訓練的次數等等。可以看到本實例採用的是model_ex-040_acc-0.800000.h5,也即是說在測試集上訓練的模型的準確率也只有80%(5張正確4張),效果不是很佳。同時,爲了提高提取的人物頭像的質量,還可以使用圖像超分辨率進行處理,提升圖像細節。