search
LoginSignup
0

More than 1 year has passed since last update.

FreeBSD Advent Calendar 2020 Day 25

posted at

RaspberryPi 4 上の FreeBSD で USB接続のWebカメラ + OpenCV ネコの顔抽出を試す

RaspberryPi4 で Webカメラが動くようになった

RaspberryPi3/4 の aarch64環境では純正のカメラモジュールが動きませんが USB 接続のWebカメラはどうでしょうか?
実はRaspberryPi3/4 上のFreeBSDで USB接続のWebカメラが動かない(デバイスとして認識されるが、画像が取得できない)状態がしばらく続いていました。同じ aarch64の Pine64ではWebCamが動いていたのですが...。
ですが最近の RaspberryPi4 環境でやっとこさ Webカメラが動くようになったので、ついでにお約束の OpenCV の顔認識ができるかどうかやってみました。

RaspberryPi4 は 8G をこちらの記事で設定したやり方で設定したものです。

ためした Webカメラは大昔に買った https://www2.elecom.co.jp/multimedia/pc-camera/ucam-c0220fb/ ですが、UVC(USB Video Class)形式ならば動く可能性が高いと思います。

Webカメラ設定

Webカメラの設定は、RaspberryPi でもPC(amd64) も同じです。

  • cuse.ko のロード
  • webcamd の pkg インストール
  • Webカメラを使いたいユーザーを webcamd グループに追加
  • webcamd を起動

以上のことを、スクリプトにまとめました。pkg install webcamd した後、こちらにあるスクリプト

を実行して再起動すれば、Webカメラが使えるようになっていると思います。

OpenCV インストール

現時点(2020/12/25)ではaarch64 の pkg に opencv (graphics/opencv)と python3.7用 python パッケージ py37-opencv(graphics/py-opencv) が無いので、ports でビルドしてインストールします。graphics/py-opencvをmake install すれば、依存関係で graphics/opencv も入ります。



cd /usr/ports/graphics/py-opencv

make install

これでpython からカメラ画像が取得できるようになっているはずです。

camera.py
#!/usr/local/bin/python3.7

import cv2

cap = cv2.VideoCapture(0)

result, frame = cap.read()

cv2.imwrite('camera.jpg', frame)

上記スクリプトを実行して、camera.jpg カメラ画像が取得できていれば設定成功です。

ネコの顔抽出

OpenCV をインストールと、人間の顔やら目やら全身などいろんなものを抽出するためのカスケード分類機がインストールされます。
その中にネコの真正面顔抽出なんてのもあるので(/usr/local/share/OpenCV/haarcascades/haarcascade_frontalcatface.xml)ネコ好きとしてはちょっとこれを試してみようかということで、やってみました。

こちらの記事を参考にし、

カメラ撮影

ネコの顔を矩形で抽出

矩形描画

画像保存

のループを行うスクリプトを作成しました。
実行すると、猫画像を検出した場合に /tmp/cat.png が更新され続けます。

cat.py
#!/usr/local/bin/python3.7

import cv2
import time

cap = cv2.VideoCapture(0)

cascade_path = "/usr/local/share/OpenCV/haarcascades/haarcascade_frontalcatface.xml"
cascade = cv2.CascadeClassifier(cascade_path)
color = (255, 255, 255)

while True:
    ret, frame = cap.read()
    if ret != True:
        continue
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    rect = cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=2, minSize=(30, 30))
    if len(rect) > 0:
        for x, y, w, h in rect:
            cv2.rectangle(frame, (x, y), (x + w, y + h), color)
        cv2.imwrite('/tmp/cat.png', frame)
    time.sleep(1)

我が家のクロ氏の協力が得られなかったので、動物園で撮影したマヌルネコのアズさんの画像で試しています。PC画面をWebカメラで撮影して、RaspberryPi4 で撮影した画像をまた PC で表示させています。
動かしてみると、壁の変な模様などを認識してしまいがちで、下のようにきれいに認識はなかなかしてくれませn。

スクリーンショット_2020-12-26_00-49-23.png

カメラ画像が使えるようになるとできることが広がるので、GPIOなどと組み合わせて変なものが作れないかなぁ。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0