顔の傾き(Roll)で顔検出を検証してみた
概要
前回、顔の傾き無しの画像で4つの顔検出アルゴリズムで検出をしてみたが、10°刻みでどこまで検出可能かトライしてみた
- Haar 特徴量+Cascade 識別器
- Dlib(HOG特徴量+SVM識別器)
- CNN(mmod_human_face_detector.dat.bz2)
- MTCNN(Multi-task Cascaded Convolutional Neural Networks for Face Detection)
コメント
- 今回カメラは使用せず、画像ファイルを直接読み出して検証しています
- ソースコード は一度に4つのアルゴリズムを動作させて、矩型の輪郭を描画をしています。正しい描画ができているかちょっと不安
- 顔検出できていないライブラリは輪郭描画なし
- 画像回転は「scipy.ndimage」モジュールのrotate()を利用しています
環境条件
- MacBook Pro
- CPU:2.4 GHz クアッドコアIntel Core i5
- メモリ:8 GB 2133 MHz LPDDR3
- MacOS Catalina(10.15.7)
- Python 3.7.6
- Opencv 4.1.2
- VS code1.50
結果
アルゴリズム | 顔検出最大角度(Roll) |
---|---|
Haar+Cascade | ±10° |
Dlib | ±50° |
CNN | ±90° |
MTCNN | ±90° |
カメラを使用して顔検出することを考えると、Dlibの最大50°という結果であり、アルゴリズムとして普通に使えそう。Harr+Cascadeはちょっとした傾きで顔検出ができないため難しい。CNN、MTCNNは文句なしの結果。あとはCPUのパフォーマンス次第で判断になりそうです。
Picth(ピッチ:顔の左右の向き)とYaw(ヨー:顔の上下の向き)も検証したいとことですが、簡単な画像データをrotate(回転)するだけでは検証できないので、 今度は顔の角度を判定するようなプログラムをサンプルソースを元にトライしてみたい。
イメージ画像
ソースコード
#!/usr/bin/env python # -*- coding: utf-8 -*- import dlib import cv2 import time import copy from mtcnn import MTCNN from scipy import ndimage # CNN cnn_fn= "./mmod_human_face_detector.dat" cnn_face_detector = dlib.cnn_face_detection_model_v1(cnn_fn) # Dlib detector = dlib.get_frontal_face_detector() # HaarCascade cascade_fn = "./haarcascade_frontalface_alt.xml" cascade = cv2.CascadeClassifier(cascade_fn) # MTCNN mtcnn_detector = MTCNN() # 顔検出するオリジナル画像を読み出し frame = cv2.imread("./face_image.jpg") # 画像をコピー face_frame = copy.deepcopy(frame) # 画像のグレースケールと平滑化 gray_image = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) gray_image = cv2.equalizeHist(gray_image) # BGRからRGBに変換 rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 顔の角度を変えるためのループ for cnt in range(0,10): # 角度を10度刻みにする angle = cnt*10 # イメージ画像を回転する (CNN,Dlib用) frame_rotate = ndimage.rotate(frame,angle) # イメージ画像を回転する (HaarCascade顔検出用) gray_image_rotate = ndimage.rotate(gray_image,angle) # イメージ画像を回転する (MTCNN顔検出用) rgb_image_rotate = ndimage.rotate(rgb_image,angle) # CNN顔検出 cnn_dets = cnn_face_detector(frame_rotate, 1) # Dlib顔検出 dlib_dets = detector(frame_rotate, 1) # HaarCascade顔検出 haar_dets = cascade.detectMultiScale(gray_image_rotate, scaleFactor=1.3, minNeighbors=3, minSize=(30, 30), flags=cv2.CASCADE_SCALE_IMAGE) # MTCNN顔検出 mtcnn_dets = mtcnn_detector.detect_faces(rgb_image_rotate) # CNNの顔検出箇所の矩型描画ループ for cnn_face in cnn_dets: cv2.putText(frame_rotate, "CNN", (int(cnn_face.rect.left()), int(cnn_face.rect.top())-4), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0),1, cv2.LINE_AA) # 顔箇所を四角で描画 cv2.rectangle(frame_rotate, (cnn_face.rect.left(),cnn_face.rect.top()), (cnn_face.rect.right(),cnn_face.rect.bottom()), (255,255,0), 2) # Dlibの顔検出箇所の矩型描画ループ for k, d in enumerate(dlib_dets): cv2.putText(frame_rotate, "Dlib", (int(d.left()), int(d.top())-4), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0),1, cv2.LINE_AA) # 顔箇所を四角で描画 cv2.rectangle(frame_rotate, (int(d.left()), int(d.top())),(int(d.right()), int(d.bottom())), (0, 255, 0), 2) # OpenCVの顔検出箇所の矩型描画ループ for(x,y,w,h) in haar_dets: cv2.putText(frame_rotate, "Haar", (x,y-4),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1, cv2.LINE_AA) # 顔箇所を四角で描画 cv2.rectangle(frame_rotate, (x,y), (x+w,y+h), (0,0,255), 2) # MTCNNの顔検出箇所の矩型描画ループ for face in mtcnn_dets: # 座標と高幅を取得 box_x, box_y, box_w, box_h = face['box'] cv2.putText(frame_rotate, "MTCNN", (box_x,box_y-4),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 1, cv2.LINE_AA) # 顔箇所を四角で描画 cv2.rectangle(frame_rotate, (box_x,box_y), (box_x+box_w,box_y+box_h), (0,255,255), 2) # ファイルに保存 cv2.imwrite("./facedetect_angle_" + str(angle)+".png",frame_rotate) print("\n Exit Program") cv2.destroyAllWindows()