石仏の顔検出

この記事は1年以上前に書かれました。
内容が古くなっている可能性がありますのでご注意下さい。


民間信仰により造立された石仏・石塔の一種である月待塔には、「廿三夜」などと文字のみが刻まれた文字塔と、如意輪観音や勢至菩薩などの像が彫られた刻像塔があります。刻像塔に彫られた顔を画像処理技術を用いて検出できるかどうか実験してみます。

月待塔の画像は、Twitterを利用したゲーム「月待ビンゴ」参加者のツイートに添付された画像を使用します。
GitHubで公開している月待塔オープンデータには、ツイートに添付された画像のURLが含まれているため、これを用いて画像を収集することができます。

プログラミング言語にはPython 3を使用し、画像処理にはオープンソースのライブラリ・OpenCVを利用します。Python環境の構築やOpenCV等のインストール方法についての説明は省きます。

作成したプログラムは以下の通りです。

import cv2
import glob
from scipy import ndimage

face = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml')
files = glob.glob("images/*.jpg")
for i, f in enumerate(files):
  img = cv2.imread(f)
  for deg in range(-30, 6, 3):
    img2 = ndimage.rotate(img, deg, reshape=False)
    gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
    faces = face.detectMultiScale(gray, minSize=(60, 60))
    if len(faces) > 0:
      for (x, y, w, h) in faces:
        cv2.rectangle(img2, (x, y), (x + w, y + h), (255, 0, 0), 2)
      img3 = cv2.resize(img2, None, fx = 0.5, fy = 0.5)
      cv2.imshow(str(deg) + " - " + f, img3)
cv2.waitKey(0)
cv2.destroyAllWindows()

はじめに、必要なライブラリをimportします。

import cv2
import glob
from scipy import ndimage

cv2は画像処理に、globはファイルの扱いに、scipyは画像の回転に使用します。
次に、カスケード分類器を作成します。

face = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml')

人間の顔検出に使用する分類器として、OpenCVでは haarcascade_frontalface_default.xml ほか数種類用意されていますが、今回実験した石仏の顔検出には、haarcascade_frontalface_alt2.xml が最も好成績でした。

files = glob.glob("images/*.jpg")
for i, f in enumerate(files):

でimagesフォルダ内の全ての.jpegファイルに対して顔検出を試みます。

img = cv2.imread(f)

でファイルから画像を読み込み、

for deg in range(-30, 6, 3):

時計回りに30度から、反時計回りに6度まで、3度刻みに画像を回転させ、顔検出を試みます。

img2 = ndimage.rotate(img, deg, reshape=False)
gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
faces = face.detectMultiScale(gray, minSize=(60, 60))

なぜ時計回りの回転角が大きいのかというと、月待塔に多く彫られている如意輪観音は首を傾げた姿のためです。

if len(faces) > 0:
  for (x, y, w, h) in faces:
    cv2.rectangle(img2, (x, y), (x + w, y + h), (255, 0, 0), 2)
  img3 = cv2.resize(img2, None, fx = 0.5, fy = 0.5)
  cv2.imshow(str(deg) + " - " + f, img3)

顔検出が成功した場合は、顔を検出した領域に青線で矩形を描き、画像の縦横の長さを0.5倍にしてウィンドウに表示します。ウィンドウのタイトルには回転角とファイル名を表示します。
全ての画像について処理が終了したら、

cv2.waitKey(0)
cv2.destroyAllWindows()

何かキーが押されるのを待ち、キーが押されたら全てのウィンドウを閉じて終了です。

実験に使用した98枚の画像のうち、(誤検出を含まず)正しく顔検出できたのは11枚でした。石仏は長年風雨にさらされており、目鼻立ちが不明瞭になってしまったためでしょうか、期待したほどの検出率ではありませんでした。
最後に、回転なしで顔検出した例と、回転することによって顔検出できた例の画像を1枚ずつ示します。

ちなみに、これらの月待塔の写真は私が撮影したものです。

OpenCVによる石仏の顔検出 12