読者です 読者をやめる 読者になる 読者になる

FaMirror Project

報告的なこと、技術的なこと

OpenCVで顔認識を行い、顔の部分だけトリミングして保存する【Python】

概要

OpenCVでは顔を簡単に認識することができます。

今回は画像から顔を認識した後に顔の部分だけトリミングを行い、その結果を保存します。

使用する言語はPythonをです。

顔認識を行う

以下のソースで顔認識を行い、顔が認識された座標をコンソールに表示します。

解析する画像は実行時に引数として指定してください。

# -*- coding:utf-8 -*-
import cv2
import sys
import os
import shutil

args = sys.argv
argc = len(args)

if(argc != 2):
	print '引数を指定して実行してください。'
	quit()

image_path = args[1]

cascade_path = "/usr/local/opt/opencv/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml"

#ファイル読み込み
image = cv2.imread(image_path)
if(image is None):
	print '画像を開けません。'
	quit()

#グレースケール変換
image_gray = cv2.cvtColor(image, cv2.cv.CV_BGR2GRAY)

#カスケード分類器の特徴量を取得する
cascade = cv2.CascadeClassifier(cascade_path)

#物体認識(顔認識)の実行
facerect = cascade.detectMultiScale(image_gray, scaleFactor=1.2, minNeighbors=2, minSize=(10, 10))

print "face rectangle"
print facerect

以下の画像で実行すると、コンソールに6人分の座標が表示がされます。
f:id:famirror:20151212162127j:plain

face rectangle
[[363 138  58  58]
 [435 196  54  54]
 [507 146  70  70]
 [295 171  57  57]
 [230 212  64  64]
 [126 141  74  74]]

ちゃんと6人とも認識されていることがわかります。

顔をトリミングして保存

次に、認識された顔の部分だけをトリミングして保存します。

先ほどのソースに以下のコードを追加してください。

#ディレクトリの作成
if len(facerect) > 0:
	path = os.path.splitext(image_path)
	dir_path = path[0] + '_face'
	if os.path.isdir(dir_path):
		shutil.rmtree(dir_path)
	os.mkdir(dir_path)

i = 0;
for rect in facerect:
	#顔だけ切り出して保存
	x = rect[0]
	y = rect[1]
	width = rect[2]
	height = rect[3]
	dst = image[y:y+height, x:x+width]
	new_image_path = dir_path + '/' + str(i) + path[1];
	cv2.imwrite(new_image_path, dst)
	i += 1

顔が一つ以上検出されれば、「元のファイル名_face」という名前のディレクトリが作成されます。

もともとその名前のフォルダがあれば一度全て削除してから再度ディレクトリを作り直すので注意してください。

その後、顔の数だけトリミングを行い、画像を保存しています。

ファイル名は0からの連番設定です。

先ほどの画像で実行すると、以下のような画像が得られます。
f:id:famirror:20151212162450j:plain:h60 f:id:famirror:20151212163015j:plain:h60 f:id:famirror:20151212162508j:plain:h60 f:id:famirror:20151212163208j:plain:h60 f:id:famirror:20151212163221j:plain:h60 f:id:famirror:20151212163232j:plain:h60 

顔の部分だけ白枠をつける

ついでですが、顔の部分に白枠をつけて画像を保存する作業も行います。

先ほどのソースにさらに以下の文を追加してください。

if len(facerect) > 0:
	color = (255, 255, 255) #白
	for rect in facerect:
		#検出した顔を囲む矩形の作成
		cv2.rectangle(image, tuple(rect[0:2]),tuple(rect[0:2] + rect[2:4]), color, thickness=2)

	#認識結果の保存
	new_image_path = dir_path + '/' +'all' + path[1]
	cv2.imwrite(new_image_path, image)

検出された顔の数だけ四角形を作成し、先ほど作ったディレクトリに「all」という名前で保存しています。

先ほどの画像で実行すると、以下のようになります。
f:id:famirror:20151212162348j:plain

コード

# -*- coding:utf-8 -*-
import cv2
import sys
import os
import shutil

args = sys.argv
argc = len(args)

if(argc != 2):
	print '引数を指定して実行してください。'
	quit()

image_path = args[1]

cascade_path = "/usr/local/opt/opencv/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml"

#ファイル読み込み
image = cv2.imread(image_path)
if(image is None):
	print '画像を開けません。'
	quit()

#グレースケール変換
image_gray = cv2.cvtColor(image, cv2.cv.CV_BGR2GRAY)

#カスケード分類器の特徴量を取得する
cascade = cv2.CascadeClassifier(cascade_path)

#物体認識(顔認識)の実行
facerect = cascade.detectMultiScale(image_gray, scaleFactor=1.2, minNeighbors=2, minSize=(10, 10))

print "face rectangle"
print facerect

#ディレクトリの作成
if len(facerect) > 0:
	path = os.path.splitext(image_path)
	dir_path = path[0] + '_face'
	if os.path.isdir(dir_path):
		shutil.rmtree(dir_path)
	os.mkdir(dir_path)

i = 0;
for rect in facerect:
	#顔だけ切り出して保存
	x = rect[0]
	y = rect[1]
	width = rect[2]
	height = rect[3]
	dst = image[y:y+height, x:x+width]
	new_image_path = dir_path + '/' + str(i) + path[1];
	cv2.imwrite(new_image_path, dst)
	i += 1

if len(facerect) > 0:
	color = (255, 255, 255) #白
	for rect in facerect:
		#検出した顔を囲む矩形の作成
		cv2.rectangle(image, tuple(rect[0:2]),tuple(rect[0:2] + rect[2:4]), color, thickness=2)

	#認識結果の保存
	new_image_path = dir_path + '/' +'all' + path[1]
	cv2.imwrite(new_image_path, image)