割と簡単に顔画像を集める方法

  • 10
    いいね
  • 0
    コメント

背景

機械学習用の顔画像を集めている時に「このワザだけでも1本の記事として成り立つんじゃね?」と思ったのでご紹介。

特定の人の顔画像を集める

機械学習の初歩でやりがちなことのひとつに、特定の人であるかどうかを判定させるみたいなものがあります。
そのためには、教師データとしてその特定の人の画像をたくさん集めたくなります。
検索して出てくるサイトの多くではクローラーでかきあつめたりするものが多いようですが、以下の手順でも顔画像収集は可能です。
例として、秋元真夏さんの画像をたくさん集めたいものと仮定します。

  1. Webブラウザを開いて最大化
  2. googleの画像検索で「秋元真夏」と検索
  3. 画面をキャプチャして画像としてとっておく
  4. 表示されていなかった画像が表示されるようにスクロール
  5. それ以上検索結果が出てこなくなるまで3と4を繰り返す
  6. OpenCVを使ってちょちょいと書いたスクリプト(後述)を用いて3でとっておいた画像から顔部分だけ切り出す

任意の人の顔画像を集める

機会学習の初歩でやりがちなことのひとつに、特定の人であるかどうかを判定させるみたいなものがあり、
不正解の画像として正解の人以外の顔画像をたくさん集めたくなることがあります。
検索して出てくるサイトの多くではクローラーでかきあつめたりするものが多いようですが、以下の手順でも顔画像収集は可能です。

  1. Webブラウザを開いて最大化
  2. googleの画像検索で「集合写真」と検索
  3. たくさん人が写っている画像を気がすむまで適当に手動でダウンロード
  4. OpenCVを使ってちょちょいと書いたスクリプト(後述)を用いて3でとっておいた画像から顔部分だけ切り出す

画像から顔部分だけを切り出すスクリプト

cascade_path という変数で書いているパスは多分環境によって違うと思いますので、検索して見つけてください。
事前にOpenCVやpythonをインストールしておく必要があります。

import cv2
import glob
import sys
import os
import imghdr
import datetime
import time

def main(srcdir, destdir, cascade_path='/home/pi/opencv-3.1.0/data/haarcascades/haarcascade_frontalface_alt.xml'):

  winname = 'searching..'
  cv2.namedWindow(winname, cv2.WINDOW_AUTOSIZE)

  if not os.path.exists(destdir):
    os.mkdir(destdir)

  lastsaved = datetime.datetime.now()
  prefix = lastsaved.strftime('%Y%m%d-%H%M%S_')
  counter = 0
  cascade = cv2.CascadeClassifier(cascade_path)

  for filename in glob.glob(srcdir + "/*"):

    if os.path.isdir(filename):
      continue
    if imghdr.what(filename) == None:
      continue

    print("load " + filename)
    img = cv2.imread(filename)
    frect = cascade.detectMultiScale(img, minSize=(64, 64))
    pos = []
    if len(frect) > 0:
      for r in frect:
        x, y, w, h = r[0], r[1], r[2], r[3]
        face = img[y:y+h, x:x+w]
        if len(face) != 0:
          if w > 0 and h > 0:
            filename = destdir + "/" + prefix + str(counter) + ".jpg"
            cv2.imwrite(filename, face)
            print("save " + filename)
            counter += 1
            pos.append(r)
    for p in pos:
      cv2.rectangle(img, (p[0],p[1]),(p[0]+p[2],p[1]+p[3]),(0,0,255), 8)
    if len(pos) > 0:
      cv2.imshow(winname, img)
      cv2.waitKey(1)

  cv2.destroyWindow(winname)

if __name__ == '__main__':
  main(sys.argv[1], sys.argv[2])

これを例えばimg2face.pyという名前にしたとしたら、

python ./img2face.py ./imgs ./face

みたいにして動かします。./imgs配下に先ほど集めておいた画像ファイルを置いてから実行すれば、顔部分を切り出した画像が./face配下に出力されます。

おわりに

機械学習は事前準備が面倒ですね。皆様にも楽チンにする手法をどんどん公開していってほしいです。