Kerasでアニメ 「けいおん!」を画像認識させてみた
を基に画像分類を試していたのですが、エラーは出ず、顔が検出されてはいたのですが、下記画像のように画像上にスコアが表示されませんでした。
私が実際に検出した画像には全て何も表示されませんでした。
何もエラーが出てこないので、コードをどこを調整すればいいのか分かりません。
機械学習とPythonに強い方、どなたかご存知の方がいたらお願いします。
result.py
1import os 2import keras 3import cv2 4import matplotlib.pyplot as plt 5from keras.models import load_model 6import numpy as np 7import glob 8 9#ディレクトリを作成 10if not os.path.exists("result"): 11 os.mkdir("result") 12dirname = "./result/" 13#modelの読み込み 14model = load_model("bochi_model.h5") 15#適用する画像があるディレクトリを開く 16img_path_list = glob.glob("./img_bochi/*") 17num = 0 18for img_path in img_path_list: 19 print(img_path) 20 img = cv2.imread(img_path, 1) 21 name,ext = os.path.splitext(img_path) 22 num += 1 23 file_name = dirname + "pic" + str(num) + str(ext) 24 img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 25 cascade_path = "./lbpcascade_animeface.xml" 26 cascade = cv2.CascadeClassifier(cascade_path) 27 #顔認識を実行 28 faces=cascade.detectMultiScale(img_gray, scaleFactor=1.2, minNeighbors=1, minSize=(68,68)) 29 Labels=['hitori', 'kita', 'nizika', 'ryo'] 30 31 Threshold = 0.95 32 #顔が検出されたとき 33 if len(faces) > 0: 34 for fp in faces: 35 # 学習したモデルでスコアを計算する 36 img_face = img[fp[1]:fp[1]+fp[3], fp[0]:fp[0]+fp[2]] 37 img_face = cv2.resize(img_face, (64, 64)) 38 score = model.predict(np.expand_dims(img_face, axis=0)) 39 # 最も高いスコアを書き込む 40 score_argmax = np.argmax(np.array(score[0])) 41 #閾値以下で表示させない 42 if score[0][score_argmax] < Threshold: 43 continue 44 #文字サイズの調整 45 fs_rate= 0.008 46 text = "{0} {1:.1f}% ".format(Labels[score_argmax], score[0][score_argmax]*100) 47 #文字を書く座標の調整 48 text_rate = 0.22 49 #ラベルを色で分ける 50 #cv2なのでBGR 51 if Labels[score_argmax] == "kita": 52 cv2.rectangle(img, tuple(fp[0:2]), tuple(fp[0:2]+fp[2:4]), (0, 0, 255), thickness=3) 53 cv2.putText(img, text, (fp[0],fp[1]+fp[3]+int(fp[3]*text_rate)),cv2.FONT_HERSHEY_DUPLEX,(fp[3])*fs_rate, (0,0,255), 2) 54 if Labels[score_argmax] == "hitori": 55 cv2.rectangle(img, tuple(fp[0:2]), tuple(fp[0:2]+fp[2:4]), (152, 145, 234), thickness=3) 56 cv2.putText(img, text, (fp[0],fp[1]+fp[3]+int(fp[3]*text_rate)), cv2.FONT_HERSHEY_DUPLEX, (fp[3])*fs_rate, (152, 145, 234), 2) 57 if Labels[score_argmax] == "nizika": 58 cv2.rectangle(img, tuple(fp[0:2]), tuple(fp[0:2]+fp[2:4]), (0,255,255), thickness=3) 59 cv2.putText(img, text, (fp[0],fp[1]+fp[3]+int(fp[3]*text_rate)), cv2.FONT_HERSHEY_DUPLEX, (fp[3])*fs_rate, (0,255,255), 2) 60 if Labels[score_argmax] == "ryo": 61 cv2.rectangle(img, tuple(fp[0:2]), tuple(fp[0:2]+fp[2:4]),(255,0,0), thickness=3) 62 cv2.putText(img, text, (fp[0],fp[1]+fp[3]+int(fp[3]*text_rate)), cv2.FONT_HERSHEY_DUPLEX, (fp[3])*fs_rate, (255,0,0), 2) 63 plt.figure(figsize=(8, 6),dpi=200) 64 plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) 65 plt.show() 66 cv2.imwrite(file_name, img) 67 # 顔が検出されなかったとき 68 else: 69 print("no face")
「faces=cascade.detectMultiScale(...」のすぐ下に(インデントを合わせて)下記を追加して実行したら、何て表示されますでしょうか?
print(len(faces))
> # 顔が検出されなかったとき
else:
print("no face")
「no face」とは表示されてないのですよね?
「score_argmax = np.argmax(np.array(score[0]))」のすぐ下に(インデントを合わせて)下記を追加して実行したら、何て表示されますでしょうか?
print(score[0][score_argmax])
「Threshold = 0.95」の「0.95」を、もっと小さな数値(0.1とか)に変えても、画像上にスコアは表示されませんでしょうか?
jbpb0さん、回答ありがとうございます。
Thresholdを下げたらスコアが表示されました。
しかし、no face と思った以上に検出されない画像が多かったのですが、これは学習モデルが少ないのか、画質が低いせいなのか、改善する方法はありますでしょうか?
> no face と思った以上に検出されない画像が多かった
http://workpiles.com/2015/04/opencv-detectmultiscale-scalefactor/
http://workpiles.com/2015/04/opencv-detectmultiscale-minneighbors/
とかを参考にして、「faces=cascade.detectMultiScale(...」のパラメータを調整してみるとか
(検出されやすくすると、誤検出も増えますが)
「faces=cascade.detectMultiScale(...」のパラメータの「minSize=(68,68)」は、
https://qiita.com/Taka_input/items/04a23bd8e9101788e583
に「物体がとり得る最小サイズ。これよりも小さい物体は無視される。」とあるので、質問者さんが使ってる画像内の顔のサイズに対して適切か、も確認してください
ただし、「lbpcascade_animeface.xml」を作った時の学習データと乖離してるものは、検出されにくいと思います
(そういうものが検出されるようにパラメータを調整したら、誤検出がすごく増えると思います)
https://teratail.com/questions/ususk6an7z50uy
のコメントも、放置しないで回答してください
あなたの回答
tips
プレビュー