
OpenCVを使った顔抽出
こんにちは。
AI coordinatorの清水秀樹です。
前回の記事で、OpenCVを使った顔認識を紹介しました。
今回は大量の画像から顔の部分だけをトリミングして保存する方法を紹介します。
機械学習用画像の準備としても使えると思いますので、ぜひ参考にしてみてください。
テスト環境
macOS Sierra
Anaconda3-4.2.0-MacOSX-x86_64
python 3.5.2
opencv3 3.1.0
まずは1枚でチャレンジ
import cv2
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
%matplotlib inline
#入力ファイルのパスを指定
in_jpg = "./photo/1.jpg"
out_jpg = "./photo_out/1.jpg"
#入力画像の表示
plt.show(plt.imshow(np.asarray(Image.open(in_jpg))))
# 画像の読み込み
image_gs = cv2.imread(in_jpg)
# グレースケールに変換
#image_gs = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 顔認識用特徴量ファイルを読み込む --- (カスケードファイルのパスを指定)
cascade = cv2.CascadeClassifier("./haarcascades/haarcascade_frontalface_alt.xml")
# 顔認識の実行
face_list = cascade.detectMultiScale(image_gs,scaleFactor=1.1,minNeighbors=1,minSize=(100,100))
#顔が1つ以上検出された時
if len(face_list) > 0:
for rect in face_list:
image_gs = image_gs[rect[1]:rect[1]+rect[3],rect[0]:rect[0]+rect[2]]
#顔が検出されなかった時
else:
print("no face")
cv2.imwrite(out_jpg, image_gs)
#出力画像の表示
plt.show(plt.imshow(np.asarray(Image.open(out_jpg))))
in_jpgには抽出元となる画像を保存したパスをしてください。
上記パスにインプットとなる画像を保存してから処理を実行すると、out_jpgにトリミングした顔画像を出力するようにしています。
出力結果は以下の通り。

しっかりと顔部分だけをトリミングすることに成功しました。
今回も新垣結衣さんの写真を使いました。
それではこのソースコードを大量の画像でも動くようにカスタマイズしていきたいと思います。
大量の画像からの顔抽出
ソースコードが雑なのはご容赦ください。
import cv2
import matplotlib.pyplot as plt
import numpy as np
import sys, os
from PIL import Image
%matplotlib inline
#入力ファイルのパスを指定
in_jpg = "./photo/"
out_jpg = "./photo_out/"
#リストで結果を返す関数
def get_file(dir_path):
filenames = os.listdir(dir_path)
return filenames
pic = get_file(in_jpg)
for i in pic:
# 画像の読み込み
image_gs = cv2.imread(in_jpg + i)
# 顔認識用特徴量ファイルを読み込む --- (カスケードファイルのパスを指定)
cascade = cv2.CascadeClassifier("./haarcascades/haarcascade_frontalface_alt.xml")
# 顔認識の実行
face_list = cascade.detectMultiScale(image_gs,scaleFactor=1.1,minNeighbors=1,minSize=(1,1))
# 顔だけ切り出して保存
no = 1;
for rect in face_list:
x = rect[0]
y = rect[1]
width = rect[2]
height = rect[3]
dst = image_gs[y:y + height, x:x + width]
save_path = out_jpg + '/' + 'out_(' + str(i) +')' + str(no) + '.jpg'
#認識結果の保存
a = cv2.imwrite(save_path, dst)
plt.show(plt.imshow(np.asarray(Image.open(save_path))))
print(no)
no += 1
画像の枚数分だけfor文で動かすようにしています。
minSize=(1,1)としていますので、顔でない部分の抽出がされる可能性が高くなりますが、そこは割り切りましょう。
以下出力されてきた画像の一部です。









しっかりと顔部分のトリミングができました。
一方で、顔でない部分もいくつか抽出されてきました。




この辺りの画像は人力で削除するしかないですね。
OpenCVを上手く使えば、色々な画像編集が一瞬で出来そうですね。
特に人の顔の学習モデルを作成したい場合には重宝しそうです。
簡単に出来ますので、ぜひ試してみてください。
それではまた。
コメントはまだありません。