PythonによるOpenCVで顔検出と抽出
Pythonの画像処理パッケージ「OpenCV」を利用して、人の画像から、顔を検出し、抽出していきます。
JupyterNotebookで、順番通りに実行することをおすすめします。
追加:顔画像の抽出を追加しました。
手順
以下の手順で、解説していきます。
- 画像を用意する
- 顔検出器を作る
- 実行する
画像を用意する
今回は、乃木坂46の生田絵梨花さんの画像を使い、顔検出を行います。
Pythonで、画像のあるURLからダウンロードします。
urllib.requestを使います。
以下のコードを実行すると、画像をダウンロードし、”test.jpg”で保存されます。
ソースコード
import urllib.request as req url = "http://imgcc.naver.jp/kaze/mission/USER/20180519/35/3012705/157/500x718xedab7ba7e203cd7576d12004.jpg" req.urlretrieve(url, "test.jpg")
使用画像
顔検出器を作る
元画像を表示させる
まずはじめに、先程ダウンロードした画像を表示させます。
ダウンロードした画像、つまり元画像をorigin_imgとします。
そして、顔検出用に元画像をimgにコピーしておきます。
顔検出で、cv2.rectangle()で顔部分を赤線で囲む処理をします。
代入で、画像を複製するだけだと、複製元の画像まで上書きされてしまいます。
未処理の画像を維持するために、copy()を用いて、コピーします。
origin_img = cv2.imread("test.jpg") img = origin_img.copy()
ソースコード
import cv2 import matplotlib.pyplot as plt %matplotlib inline origin_img = cv2.imread("test.jpg") img = origin_img.copy() #plt.axis("off") plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.show()
カスケードファイルを用意する
以下のリンクから、haarcascade_frontalface_alt.xmlをダウンロードし、プログラムファイルと同じディレクトリに移動させましょう。
カスケードファイル
カスケードファイルを利用して、検出器
ソースコード
#カスケードファイルを指定して、検出器を作成 cascade_file = "haarcascade_frontalface_alt.xml" cascade = cv2.CascadeClassifier(cascade_file) img_face = img #画像の読み込んでグレースケール img_gray = cv2.cvtColor(img_face, cv2.COLOR_RGB2GRAY) #顔認識 face_list = cascade.detectMultiScale(img_gray, minSize = (150, 150)) #結果 if len(face_list) == 0: print("失敗") quit() for (x,y,w,h) in face_list: print("顔の座標 = ", x, y, w, h) red = (0, 0, 255) cv2.rectangle(img_face, (x,y), (x+w, y+h), red, thickness=20) #出力 plt.imshow(cv2.cvtColor(img_face, cv2.COLOR_BGR2RGB)) plt.show()
出力と保存
以上の手順で、以下の顔検出の画像が表示されたと思います。
いくちゃん可愛いですよね。。。
それは置いといて、最後にこの画像を保存します。
ソースコード
cv2.imwrite("out.jpg", img)
追加:顔画像の抽出
顔検出を実行した時、同時にxy座標も算出しました。
その座標の情報を使って切り取り、つまり顔画像の抽出を行います。
ソースコード
#切り取り img_face_ex = origin_img[y:y+h, x:x+w] plt.imshow(cv2.cvtColor(img_face_ex, cv2.COLOR_BGR2RGB)) plt.show() #保存 cv2.imwrite("out_face.jpg", img_face_ex)
抽出した画像
注意
顔検出で、cv2.rectangle()で顔部分を赤線で囲む処理をします。
代入で、画像を複製するだけだと、複製元の画像まで全て、上書きされてしまいます。
未処理の画像を維持するために、copy()を用いて、コピーしておくことが必要です。
おわり
追加:横顔は苦手
カスケード(顔パーツのデータ)は、正面の顔検出用です。
なので、横顔の顔検出が苦手です。