ラズパイとOpenCVを使って、顔を検出したら写真を撮るようなコードをPythonで書いてみました。
usbカメラでなく、ラズパイのカメラを使っています。
ラズパイカメラだと写真撮影にはpicameraというライブラリを使う方法もありますがコードが少し複雑になります。
この記事では、picameraを使わずにシンプルにOpenCVで書いて行きます。
[toc]
コード
なぜかラズパイカメラだと反転するので、最初に上下反転する処理を入れています。
キャスケードファイルは、人の顔を認識するためのファイルを指定します。
以下のサイトからファイルをダウンロード。
https://github.com/opencv/opencv/tree/master/data/haarcascades
pythonのコードと同じディレクトリに置いて実行。
顔を検出したら、写真を保存して3秒待ちます。
import cv2 from datetime import datetime from time import sleep MIN_SIZE = (150, 150) cascade = cv2.CascadeClassifier("haarcascade_frontalface_alt.xml") camera = cv2.VideoCapture(0) try: while True: _, img = camera.read() # raspiのカメラだと反転しているので修正 img = cv2.flip(img, -1) igray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = cascade.detectMultiScale(igray, minSize=MIN_SIZE) if len(faces) == 0: continue for (x, y, w, h) in faces: color = (255, 0, 0) cv2.rectangle(img, (x, y), (x+w, y+h), color, thickness=8) t = datetime.now().strftime("%Y-%m-%d_%H_%M_%S") fname = "face" + t + ".jpg" cv2.imwrite(fname, img) print("detect face") sleep(3) except KeyboardInterrupt: print("key interrupt!!!")
以下のエラーが発生する場合はカスケードファイルがダウンロードしてあるか、ファイル名があっているか確認しましょう。
OpenCV Error: Assertion failed (!empty()) in detectMultiScale,
…
error: (-215) !empty() in function detectMultiScale
実行結果
撮影した画像はこんな感じ。

ipadに映った顔を認識してますね。
フレームを表示する
ファイル出力だと数が多くなるので、ディスプレイにフレームを表示するように改造してみたいと思います。
フレームを表示するときはSSHやVNCなどのリモート実行では表示されないので注意してください。
実行すると以下のようなエラーが出ます。
: cannot connect to X server
- 顔を検出しても、しなくてもフレームをディスプレイに表示する
- 「q」が押されたら終了
import cv2 from datetime import datetime from time import sleep MIN_SIZE = (150, 150) cascade = cv2.CascadeClassifier("haarcascade_frontalface_alt.xml") camera = cv2.VideoCapture(0) while True: # フレームがアクティブになった状態で「q」が押されたら終了。 if cv2.waitKey(1) & 0xFF == ord('q'): break _, img = camera.read() # raspiのカメラだと反転しているので修正 img = cv2.flip(img, -1) igray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = cascade.detectMultiScale(igray, minSize=MIN_SIZE) if len(faces) == 0: # 顔が検出されなかった時でもフレームを表示 cv2.imshow('frame', img) continue for (x, y, w, h) in faces: color = (255, 0, 0) cv2.rectangle(img, (x, y), (x+w, y+h), color, thickness=8) t = datetime.now().strftime("%Y-%m-%d_%H_%M_%S") fname = "face" + t + ".jpg" print("detect face") # 顔が検出されたら顔の周りに枠を表示してフレームを表示 cv2.imshow('frame', img) # ファイル出力したい場合は以下を使用、ファイル数が多くなりすぎないように3秒待つ # cv2.imwrite(fname, img) # sleep(3) # ビデオキャプチャを終了して、フレームを表示していたウィンドウを閉じる。 camera.release() cv2.destroyAllWindows()

こっちの方が直感的で分かりやすいと思います。
おわり。