はじめに
- 最終的なWebアプリケーションに至る作業なので、資料を公開することにしました。
- なので、基本的な話のみになります。
- ソース一式は ここ です。
- 参考
ライブラリのインストール
-
Ubuntu
なら$ apt install python3-opencv
でインストールする場合もあると思います。 - また、最終的なWebアプリケーションの環境は、
Heroku
を想定しています。 - Heroku の場合は、Ubuntu を利用できますが、
python3-opencv
は、うまく動作しません。 - 下記の
pip
でopencv-python
なら、最新バージョン、マルチコアの利用など、良い事が多いです。
$ pip install opencv-python
設定ファイル config.py
- ダウンロードした画像ファイルのフォルダ、顔認識した画像ファイルのフォルダを指定しています。
- 顔認識に利用する
Haar Cascades
xml
ファイルの場所を指定します。 -
CLASSES
を利用して、該当フォルダの画像を順次処理します。
$ cat config.py
CLASSES = [
'安倍乙',
'石原さとみ',
'大原優乃',
'小芝風花',
'川口春奈',
'森七菜',
'浜辺美波',
'清原果耶',
'福原遥',
'黒島結菜'
]
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DATA_PATH = os.path.join(BASE_PATH, 'data')
LINK_PATH = os.path.join(DATA_PATH, 'link')
DOWNLOAD_PATH = os.path.join(DATA_PATH, 'download')
FACE_PATH = os.path.join(DATA_PATH, 'face')
HAARCASCADE_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'haarcascade_frontalface_default.xml')
haarcascade_frontalface_default.xml
- 以下から
xml
ファイルダウンロードします。
$ wget https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml
顔認識プログラム save_face_image.py
ダウンロード画像の一覧の取得、Haar Cascade の読み込み等
-
query
には、CLASSES
が順次与えられます。 - ダウンロード画像のパスの確認、顔画像のパスの作成をします。
- Haar Cascade を読み込みます。
-
glob
でダウンロード画像の*.jpeg
を検索し、一覧化します。
def detect(query):
"""画像の読み込み、顔画像の検出、顔画像の保存."""
download_path = os.path.join(DOWNLOAD_PATH, query)
if not os.path.isdir(download_path):
print('no download path: {}'.format(download_path))
return
os.makedirs(os.path.join(FACE_PATH, query), exist_ok=True)
face_cascade = cv2.CascadeClassifier(HAARCASCADE_PATH)
download_list = glob.glob(os.path.join(download_path, '*.jpeg'))
download_list.sort()
顔認識
- ダウンロード画像を順次処理します。
- 画像はカラーからグレースケールに変換し、Haar Cascade で顔認識を実施します。
-
scaleFactor
は、画像から顔認識をする時に、画像を異なるサイズに変更し、複数回顔認識をするための値です。 -
scaleFactor
が小さいと、顔以外を検知したり、時間がかかったりします。逆に、大きい値だと、検知出来なかったりします。 - 初期値は、
1.1
ですが、誤検知と非検知を鑑み、1.2
にしています。 -
minNeighbors
は、上記のscaleFactor
に関連があります。 -
scaleFactor
は、画像の同じ箇所を複数回確認し、検知することになります。何回検知した時、顔認識したことにするかをminNeighbors
で指定しています。この値が大きいと、複数回検知しないと、顔認識したと見なされないので、見落としが発生します。 - 今回は、
3
にしました。この値は、デフォルト値です。忘れない様に、あえて指定しています。 - この値の調整は、状況に応じて調整が必要なので、難しいですね。。。
for download in download_list:
img = cv2.imread(download)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=3)
if len(faces) < 1:
print('query: {}, download: {}, face num: 0'.format(query, os.path.basename(download)))
continue
顔画像の保存
- 顔画像の位置元に、画像を取り出し、顔画像のフォルダに保存します。
- ファイル名は、ダウンロード画像を元にしています。
- 例えば、ダウンロード画像が
0001.jpeg
なら 顔画像は0001-0001.jpeg
になります。 - 複数人の顔画像が認識されるので、
0001-0002.jpeg
0001-0003.jpeg
と言う感じで保存しています。
for num, (x, y, w, h) in enumerate(faces, start=1):
face = img[y:y+h, x:x+w]
filename = os.path.join(FACE_PATH, query, os.path.basename(download).split('.')[0] + '-{:04d}.jpeg'.format(num))
cv2.imwrite(filename, face)
print('query: {}, download: {}, filename: {}'.format(query, os.path.basename(download), os.path.basename(filename)))
顔画像の例
- 以下の様な感じです。誤検知がありますね。この後が辛い。。。
おわりに
- 顔認識を実施しました。
- 次回は、顔認識の簡易管理アプリと誤検知の削除をする予定です。