ビジネスパーソン・ガジェット置場 empty lot for business

営業や仕事、それに伴う生活を便利に楽にするツール、ガジェットを作ります。既にあるツールも自分用にカスタマイズ。

openCV: 画像から顔部分を切り出す

ディープラーニングで顔分類を行うために画像から顔部分を切り出すためのコードです。

openCVのカスケード分類器を使用して切り出す

前回のCustomSearchAPIの使用方法と同様に下記のサイトさんを参照させていただいています。

機械学習で乃木坂46を顏分類してみた | Aidemy | 10秒で始めるAIプログラミング学習サービスAidemy[アイデミー]

 

実装は、CustomSearch APIで取得した画像ではなく、自分で集めた画像(Iveのメンバー)を使いました。また、カスケード分類器「haarcascade_frontalface_alt.xml」は、だいぶ前に自分のPCに落としていたのでそれを使いました。

 

一度下記のようなエラーが出たのですが、ストップしてしまった画像を見つけ画像を小さくしたら問題なく処理できました。

 

OpenCV(4.5.3) /private/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/pip-req-build-xxsyexfp/opencv/modules/imgproc/src/resize.cpp:4051: error: (-215:Assertion failed) !ssize.empty() in function 'resize'

 

コード

 

集めた画像はData3というフォルダに入れていたのでそこからファイルをglobで全取得して処理をしています。

import numpy as np
import cv2
import matplotlib.pyplot as plt
from PIL import Image
import glob
import os
import shutil

# フォルダごとに取り出す用にフォルダの名前をまとめる
d_name = ['イソ', 'ウォニョン', 'ガウル', 'ユジン', 'リズ', 'レイ']

# フォルダごとにファイルを読み込み顔部分を抽出してface_imageに格納していく
for name in d_name:
    files = glob.glob(f'data3/train/{name}/*')
    out_dir = f'face_image/train/{name}'
    # 各ファイルを読み込み顔部分を検出
    for i in range(len(files)):
        image = cv2.imread(files[i])
        image_gs = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
        face_list = cascade.detectMultiScale(image_gs, scaleFactor=1.1, minNeighbors=2, minSize=(64, 64))
        
        # 顔部分が抽出できたならサイズを変更しface_imageに格納
        if len(face_list) > 0:
            for rect in face_list:
                x, y, width, height = rect
                image = image[rect[1]:rect[1]+rect[3], rect[0]:rect[0]+rect[2]]
                if image.shape[0] < 64:
                    continue
                image = cv2.resize(image, (128, 128))
                fileName = os.path.join(out_dir, files[i].split('/')[-1])
                cv2.imwrite(fileName, image)
        else:
            continue

上記のエラーが出たのは下部の「image = cv2.resize(image, (128, 128))」このコードです。その下3行をtryで囲ってエラーが出た場合該当の画像をprintする形で対処しました。

 

こちらの処理で6人のメンバーそれぞれ80枚ずつ合計480枚集めていた画像が324枚まで減ってしまいましたが、水増し(別途ブログ作成)で2000枚程度にし学習器に入れる予定です。

 

こちらの処理では、切り取った画像をあらかじめ作成していた「face_image」というフォルダの「train」フォルダの「各メンバー名のフォルダ」にファイル名を変えずに格納していくようにしています。