LoginSignup
6
8

More than 5 years have passed since last update.

Python+OpenCVで顔検出(回転不変)

Posted at

Python+OpenCVで顔検出(回転不変)

画像を回転させながら顔検出
一番いい角度の調整等は行っていない
必要なら以下を参考に

Heroku + OpenCVで簡易顔検出API

Face Detection using Haar Cascades

入力画像ではなく、フィルタのほうを回転させて自動で検出してほしい……

はまりポイント

画像処理に慣れている人なら当たり前なのかもしれないが、ほとんどやったことがないので結構はまった

画像の高さや幅を取得・指定するときに順番が違うことがある

  • shape…高さ(rows)、幅(columns)
  • インデックスでスライス…[高さ下限(y) : 高さ上限(y+h), 幅下限(x) : 幅上限(x+w)]
  • OpenCVの座標指定(中心点とか)…(横(x), 縦(y))

ディスプレイの座標系はy軸が下方向なのに角度は反時計回りなので、普通のy軸が上方向の座標系に変換すると時計回りに回っている

コード

face_rotate_detect.py
# -*- coding: utf-8 -*-

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import cv2, os, sys, imghdr, shutil, math
import numpy as np

CWD = os.getcwd()
DIR_ORIGIN = CWD + '/images/'
DIR_DESTINATION = CWD + '/faces/'

classifier = cv2.CascadeClassifier('{python_dir}/{classifier_dir}/haarcascade_frontalface_alt2.xml'.format(
    python_dir = os.path.split(sys.executable)[0],
    classifier_dir = '../share/OpenCV/haarcascades',
))

def getFaces(path_full):
    results = []
    image = cv2.imread(path_full)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    rows, cols, colors = image.shape
    center = tuple(np.array([cols, rows]))
    # get rotations
    for angle in range(-90, 91, 5):
        radian = np.deg2rad(angle)
        output_height = int(np.absolute(cols * np.sin(radian)) + np.absolute(rows * np.cos(radian)))
        output_width = int(np.absolute(cols * np.cos(radian)) + np.absolute(rows * np.sin(radian)))
        output_size = tuple(np.array([output_width, output_height]))
        # rotate
        Matrix = cv2.getRotationMatrix2D(center, degree, 1.0)
        # translate
        Matrix[0, 2] += (output_width - width) * 0.5
        Matrix[1, 2] += (output_height - height) * 0.5
        # warp affine
        rotated = cv2.warpAffine(gray, Matrix, output_size, flags = cv2.INTER_LINEAR)
        # detect faces
        faces = classifier.detectMultiScale(rotated)
        if len(faces):
            rotated_color = cv2.warpAffine(image, Matrix, output_size, flags = cv2.INTER_LINEAR)
            for x, y, w, h in faces:
                results.append(rotated_color[y : y + h, x : x + w])
    return results

def saveFaces(faces):
    global count

    for face in faces:
        cv2.imwrite(
            '{dir_destination}{count}.jpg'.format(dir_destination = DIR_DESTINATION, count = count),
            face,
            [cv2.IMWRITE_JPEG_QUALITY, 100]
        )
        count += 1

count = 1
for path, subdirs, files in os.walk(DIR_ORIGIN):
    for name in files:
        path_full = os.path.join(path, name)
        if imghdr.what(path_full) in ['jpeg']:
            saveFaces(getFaces(path_full))
            print(path_full)
6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8