- ラズベリーパイで何かやりたいと思っている人
- python,機械学習で何かやりたいと思っている人
- とりあえず顔面追跡カメラ作りたい人
どうも,最近ラズベリーパイにハマっているけんゆー(@kenyu0501_)です.
今日は,インターネットにコロコロと転がっている(オープンにされている)記事たちを参考に,おいらも顔面追跡システムを構築してみました.
モーツァルト先輩にもご協力願いました.
Youtubeはこちらです.
(20秒ほどの動画ですのでご覧ください.)
いやー,インターネットは素晴らしいです.
こんな面白いシステムが半日で組めます.
オープンなインターネット時代に感激です!
そして車輪の再発明は避けたいので,誰かが公開している技は盗みまくります!
(あ,ちなみに,おいらのブログで公開しているものも全て使ってもらって構いませんよ!笑)
と言うことで,今日はこの顔追跡カメラの開発を出し惜しみなく書いていきます!
pythonコードの公開,このシステムの大枠の仕組み,参考にしたサイトの明記,使用した材料をそれぞれ説明していきます.
Pythonプログラムについて
Pythonコードで動いています.
いろいろインターネットをあちらこちらしましたが,このサイトを主に参考にしました.
(参考:Raspberry Pi3 とカメラモジュールで顔追跡カメラを作る)
ありがとうございます.
参考にして改良したコードです.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | # -*- coding: UTF-8 -*- import cv2 from picamera import PiCamera import io import numpy as np import os import time import pigpio pi = pigpio.pi() def move(x_move, y_move): pi.set_servo_pulsewidth(4, x_move) pi.set_servo_pulsewidth(17, y_move) #X,Yのサーボ可動範囲 X_MAX = 2500 X_MIN = 500 X_HOME = 1500 #水平方向 Y_MAX = 2500 Y_MIN = 1500 Y_HOME =2100 #垂直方向 #カメラの位置初期化? move(X_HOME, Y_HOME) #顔検出用学習用パス cascade_path = "/home/pi/opencv-3.1.0/data/haarcascades/haarcascade_frontalface_alt.xml" cascade = cv2.CascadeClassifier(cascade_path) stream = io.BytesIO() # camera=PiCamera() W = 500 H = 500 camera.resolution = (W, H) color = (255, 255, 255) #白色 #現在位置に初期位置を代入 now_degree_x, now_degree_y, move_degree_x, move_degree_y = X_HOME, Y_HOME, 0, 0 while(True): camera.capture(stream, format='jpeg') # data = np.fromstring(stream.getvalue(), dtype=np.uint8) # image = cv2.imdecode(data, 1) # frame = image facerect = cascade.detectMultiScale(frame, scaleFactor=1.2, minNeighbors=2, minSize=(10, 10)) if len(facerect) > 0: for rect in facerect: img_x = rect[0]+rect[2]/2 img_y = rect[1]+rect[3]/2 print(img_x, img_y) #顔とカメラ位置のズレを計算.(W,H)/2で250 move_degree_x = now_degree_x + (-img_x+250)*0.8 move_degree_y = now_degree_y + (img_y-250)*0.5 #モーターの可動範囲内の時のみカメラを動かす #if ((move_degree_x >= 500 and move_degree_x <= 2500) and (move_degree_y >= 500 and move_degree_y <= 2500)): if move_degree_x >= X_MIN: if move_degree_x <= X_MAX: if move_degree_y >= Y_MIN: if move_degree_y <= Y_MAX: #顔の方へカメラを動かす move(move_degree_x, move_degree_y) now_degree_x = move_degree_x now_degree_y = move_degree_y else: print("下は見えないよ~") else: print("もう!首が疲れる~") else: print("これ以上右に行かないで~") else: print("もう左はダメ~") #顔認証した中心点を円で描写 cv2.circle(frame, (int(img_x), int(img_y)), 10, color, -1) #顔認証した部分を長方形で囲む cv2.rectangle(frame, tuple(rect[0:2]),tuple(rect[0:2] + rect[2:4]), color, thickness=3) else: print("Where is your face?") cv2.imshow("Show FLAME Image", frame) k = cv2.waitKey(1) if k == ord('q'): break stream.seek(0) cv2.destroyAllWindows() |
コードが気になる方もいるかなと思い,先に記述しました.
次にコードと合わせて「システムの大枠の仕組み」を紹介していきます.
システムの大枠の仕組み
全体的なスライドを作りました.
プログラムは3つのパートに分かれています.
上からそれぞれ,
- ライブラリインポート
- パラメータや各種文字の定義と,初期化等
- 処理部分(whileから)
この上の3つです.
大事なところが少ししかないので,取り上げていきます.
2軸さーぼモータの取り付け!
今回は,サーボモータ(SG90)を二つ使いますが,GPIOに必要な部品はこれくらいです.
上の画像のように一つのサーボモータにつき,3本のコードが伸びていると思います.
それぞれ
- 黄色:GPIOの4番(X)と17番(Y)ピン
- 赤:5Vの電源が確保できるピンの位置
- 茶色:GNDが確保できるピンの位置
です.黄色のピンの位置はプログラム上で指定がありますが,電源とアースはどこでも構いません.
下のようにつないでくれたら大丈夫です.
プログラム上で,X軸とY軸の可動範囲を決める
この可動範囲は,実際にサーボモータを動かしながら経験的に定めてください!
そのほうが安全です,
なので,最終調整の段階で,X_MAX等は触ってもらって結構です.
あとは,プログラムをぺぺって貼り付けて,実物を用意したら動くと思います.
いちよう商品リンク貼っておきますが,こちらのカメラキットは寸法がちょっと粗めでした.
しかも極め付けは,土台ステージとサーボモータをリンクさせるコネクタ部品が入っていないこと!!笑
値段も安いので,そこは割り切って,コネクト部を加工して作りました
いちよう,カメラも貼っておきますが,Webカメラをお持ちの方は,それで良いかもしれません.
こちらです.
最後にちょっと注意点
注意点は,カメラの接続確認とGPIOピンが使用できる環境にしておいてください.
それぞれターミナルで,
- vcgencmd get_camera
- sudo pigpiod
と入力するだけです!
この記事の英語版を書きました
This article is recommended for such people! Someone wh…
ラズベリーパイで無限の可能性を!
ラズベリーパイがあればなんでもできます!
顔面追跡カメラもかなり簡単に作ることができました.
みなさんも是非どうですか!
他にもラズベリーパイを使った記事をあげておきます!
などなど!では