Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
15
Help us understand the problem. What is going on with this article?
@hidakanoko

Raspberry Pi CameraモジュールとOpenCVで人間の顔を認識する

More than 1 year has passed since last update.

環境

  • Raspberry Pi 3B (Raspbian 9.4) + Camera Module V2
  • OpenCV 3.4.3

OpenCVのインストール

インストールはチュートリアルのとおりでいけました。
https://docs.opencv.org/master/d7/d9f/tutorial_linux_install.html

NOTE: aptリポジトリにもpython-opencvがあるので、古いバージョンでもよければこちらを入れた方が簡単ですね。検出性能は...低いかもしれません。

pi@raspberrypi:~$ apt search python-opencv
ソート中... 完了
全文検索... 完了  
python-opencv/stable 2.4.9.1+dfsg1-2 armhf
  Python bindings for the computer vision library

必要パッケージのインストール

# apt-get install build-essential
# apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
# apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev

OpenCVのダウンロード

最新のソースはこちらから

# curl -OL https://github.com/opencv/opencv/archive/3.4.3.zip
# unzip 3.4.3.zip
# cd opencv-3.4.3/

ビルドとインストール

makeにはかなり時間がかかります。私の環境では一度端末がフリーズしてしまいました...

# # IN "opencv-3.4.3/" DIR
# mkdir build
# cd build
# cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local ..
# make
# make install

Pythonのモジュールは /usr/local/lib/PYTHON_VERSION/dist-packages/ にインストールされています。

pi@raspberrypi:~$ ls /usr/local/lib/{python2.7,python3.5}/dist-packages/
/usr/local/lib/python2.7/dist-packages/:
cv2.so

/usr/local/lib/python3.5/dist-packages/:
cv2.cpython-35m-arm-linux-gnueabihf.so

インストールの検証

$ python3 -c "import cv2; print(cv2.__version__)"
3.4.3

カメラの準備

接続とデバイスの有効化

カメラモジュールを接続したら、デバイスを有効化する必要があります。
カメラの接続方法とGUIからデバイスを有効化する方法は公式ページにステップバイステップ手順があります。
https://projects.raspberrypi.org/en/projects/getting-started-with-picamera

コマンドラインから行う場合は、カメラ接続後 raspi-config を起動して "5 Interfacing Options" ---> "P1 Camera" メニューでカメラデバイスを有効化します。設定変更後デバイスを再起動します。

$ sudo raspi-config

カメラのテスト

$ raspistill -v -o test.jpg

カメラで撮った画像から人間の顔を探す

公式の顔検出サンプルコードは下記URLにあります。下記コードは公式のサンプルコードを一部改変したものです。
https://docs.opencv.org/3.4.3/d7/d8b/tutorial_py_face_detection.html

Cameraモジュールで写真を撮る

Cameraモジュールを起動してカレントディレクトリに写真を保存します。
写真を撮る前に3カウントしています。

pic_file = './picamera_work.jpg'
if os.path.exists(pic_file):
    os.remove(pic_file)

camera = PiCamera()
for i in range(3, 0, -1):
    print(i)
    sleep(1)
camera.capture(pic_file)

camera.capture(output)はカメラで撮った写真をoutputで指定されたパスに保存します。ファイルパスの代わりにファイルオブジェクトを渡すこともできます。
保存する画像のフォーマットはファイル名から推測してくれます (例: *.jpg=>JPEGファイル)。format=FORMATで指定することもできます。
https://picamera.readthedocs.io/en/release-1.13/api_camera.html#picamera

OpenCVの学習済分類器をロードする

OpenCVでは学習済の分類器をいくつか提供しています。
分類器は/usr/local/share/OpenCV/haarcascades/にインストールされています。

分類器をロードするにはCascadeClassifierコンストラクタにパラメータとして渡すか、loadメソッドを別途呼び出します。
下記コードサンプルでは目と顔の分類器をそれぞれロードしています。

face_classifier = "/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml"
face_cascade = cv2.CascadeClassifier(face_classifier)
eye_classifier = "/usr/local/share/OpenCV/haarcascades/haarcascade_eye.xml"
eye_cascade = cv2.CascadeClassifier(eye_classifier)

顔を検出する

detectMultiScaleで顔を検出します。
http://opencv.jp/opencv-2.1/cpp/object_detection.html#cv-cascadeclassifier-detectmultiscale
detectMultiScaleは与えられた画像を縮小しながら何度も検出を試みます。パラメーターscaleFactorには画像の縮小量を設定します。
最終的に検出される物体は少なくともminNeighborsで指定された分だけ近傍矩形を含む必要があります。minNeighborsに小さな値を指定すると検出できる割合は増えますが、誤検出も増えます。

pic = cv2.imread(pic_file)
pic_gray = cv2.cvtColor(pic, cv2.COLOR_BGR2GRAY)

faces = face_cascade.detectMultiScale(
    pic_gray,
    scaleFactor=1.1,
    minNeighbors=5,
    minSize=(30, 30))

scaleFactorの働きはこちらのQAが理解の助けになりました。
http://answers.opencv.org/question/10654/how-does-the-parameter-scalefactor-in-detectmultiscale-affect-face-detection/

検出したオブジェクトを表示する

検出した顔のエリアを線で囲っています。さらにそのエリア内で目を検出して、見つかった場合はそのエリアも線で囲います。

for (x, y, w, h) in faces:
    cv2.rectangle(pic, (x, y), (x + w, y + h), (255, 0, 0), 2)
    roi_gray = pic_gray[y:y+h, x:x+w]
    roi_color = pic[y:y+h, x:x+w]
    eyes = eye_cascade.detectMultiScale(roi_gray)
    for (ex, ey, ew, eh) in eyes:
        cv2.rectangle(roi_color, (ex,ey), (ex+ew,ey+eh), (0,255,0), 2)

cv2.imshow("Raspberry pi camera detects {0} faces".format(len(faces)), pic)
cv2.waitKey(0)
cv2.destroyAllWindows()

コード全体

from picamera import PiCamera
from time import sleep
import cv2
import os
import sys

pic_file = './picamera_work.jpg'

if os.path.exists(pic_file):
    os.remove(pic_file)

camera = PiCamera()
for i in range(3, 0, -1):
    print(i)
    sleep(1)
camera.capture(pic_file)

face_classifier = "/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml"
face_cascade = cv2.CascadeClassifier(face_classifier)
eye_classifier = "/usr/local/share/OpenCV/haarcascades/haarcascade_eye.xml"
eye_cascade = cv2.CascadeClassifier(eye_classifier)

pic = cv2.imread(pic_file)
pic_gray = cv2.cvtColor(pic, cv2.COLOR_BGR2GRAY)

faces = face_cascade.detectMultiScale(
    pic_gray,
    scaleFactor=1.1,
    minNeighbors=5,
    minSize=(30, 30))

for (x, y, w, h) in faces:
    cv2.rectangle(pic, (x, y), (x + w, y + h), (255, 0, 0), 2)
    roi_gray = pic_gray[y:y+h, x:x+w]
    roi_color = pic[y:y+h, x:x+w]
    eyes = eye_cascade.detectMultiScale(roi_gray)
    for (ex, ey, ew, eh) in eyes:
        cv2.rectangle(roi_color, (ex,ey), (ex+ew,ey+eh), (0,255,0), 2)

cv2.imshow("Raspberry pi camera detects {0} faces".format(len(faces)), pic)
cv2.waitKey(0)
cv2.destroyAllWindows()

おまけ

imwriteを使って切り出した顔を画像として保存することもできます。

count = 0;
for (x, y, w, h) in faces:
        count += 1
        cv2.rectangle(pic, (x, y), (x + w, y + h), (255, 0, 0), 2)
        roi_gray = pic_gray[y:y+h, x:x+w]
        roi_color = pic[y:y+h, x:x+w]
        cv2.imwrite("face_{0}.jpg".format(count), roi_color)
        ...
15
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
codmon
保育園・幼稚園向け業務支援システム「コドモン」の開発・運営を手がける会社です。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
15
Help us understand the problem. What is going on with this article?