9
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[メモ](らずぱい)Pan-Tilt HATとカメラで、顔追跡(Face Tracking)

Last updated at Posted at 2017-02-21

概要

pi@raspberrypi:~ $ python
Python 2.7.9 (default, Sep 17 2016, 20:26:04)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.

from pantilthat import *
angle_pan = 15 # 角度:-90 - +90
angle_tilt = -30 # 角度:-90 - +90
pan(angle_pan)
tilt(angle_tilt)
quit()
pi@raspberrypi:~ $


## 環境
- Raspberry Pi 2 / 3
- Camera Module V2.1 (V1.3でも動作した)
- Raspbian: `2017-01-11-raspbian-jessie.img` (OpenCVで、ウィンドウにカメラ画像を表示させるので、Liteじゃないよ)

## 手順
1. Pan-Tiltキットの組み立て [Assembling Pan-Tilt HAT](https://learn.pimoroni.com/tutorial/sandyj/assembling-pan-tilt-hat)
https://learn.pimoroni.com/tutorial/sandyj/assembling-pan-tilt-hat <br>写真を見ながらやればできるかと。
    - Pan-TiltモジュールをHATの基板に固定
        - 黒いナイロンねじは、長めなので、きってしまうのもいいね(It's a good idea to trim the protruding end of the nylon bolt with a pair of scissors or tin snips,~)らしい
    - サーボモータの線をうらのコネクタに挿す (GND=茶, 5V=赤, PWM-黄)
        - Pan(クビを横に振る)をチャンネル1 (SERVO1)
        - Tilt(クビを縦に振る)をチャネル2 (SERVO2)
    - カメラ固定台組み立て 
        - V1.3用とV2.1用で、表に出る側の切り込みが違うんだと思う。
        - 白いねじは長めにできてるので、切ってもいいね(Again, it's a good idea to trim off the excess nylon bolt with a pair of scissors or tin snips.)、らしい
    - カメラ固定台をPan-Tiltモジュールにつける
        - カメラのケーブルは上にでるよ
    - Neopixel stick ... 購入してないので、スキップ。
    - カメラのケーブルをらずぱいに挿す。
        - ラズパイの差込口の上にある部品(茶色?とか黒とか?)をちょいと持ち上げる1mmくらい。力を入れすぎると、壊れるよ
        - カメラケーブルを差し込んで
        - 持ち上げたのを、押し込む、と固定される。 
    - らずぱい40ピンにHATを挿す。

2. 起動システムの準備(いつもの)
    - Raspbianをやいて
    - `sudo apt-get update && sudo apt-get upgrade -y` #パッケージ更新

3. Pan-Tilt 関係のパッケージをインストール
`curl -sS https://get.pimoroni.com/pantilthat | bash`
で何か聞かれたら、`y [Enter]`

4. カメラモジュールの有効化<br>`sudo raspi-config nonint do_camera 0 # 0:Enable/1:Disable`


5. `sudo reboot` # 再起動
6. PanTiltモジュールの動作確認
    - ターミナルを開いて、
    - `python[Enter]` で、python起動
    - 以下、コピペ
 
		```py
		from pantilthat import *
		angle_pan  = 15   # 角度:-90 - +90
		angle_tilt = -30  # 角度:-90 - +90
		pan(angle_pan)
		tilt(angle_tilt)
		quit()
		```
    - 動く? 数字を変えると、向きがかわる angle_pan=0 / angle_tilt = 0で正面向く感じ?



### フェイストラッキングのデモプログラム
https://github.com/pimoroni/PanTiltFacetracker


1. 必要なパッケージ導入<br>`sudo apt-get install python-smbus python-opencv opencv-data`
2. git clone 

    ```bash
git clone https://github.com/pimoroni/PanTiltFacetracker
cd PanTiltFacetracker
  1. 実行
    ./facetracker_lbp.py
    • ウィンドウが開いて、カメラの画像が映る
    • 顔 を検出すると、それがセンターにくるように、Pan-Tiltモジュールが動く.

その他

  • ログ

     pi@raspberrypi:~ $ curl -sS https://get.pimoroni.com/pantilthat | bash
    
     This script will install everything needed to use
     Pan-Tilt HAT
    
     Always be careful when running scripts and commands
     copied from the internet. Ensure they are from a
     trusted source.
    
     If you want to see what this script does before
     running it, you should run:
     \curl -sS https://get.pimoroni.com/pantilthat
    
     Note: Pan-Tilt HAT requires I2C communication
    
     Do you wish to continue? [y/N] y
    
     Checking environment...
     Updating apt indexes...
     .........
     Reading package lists...
     .........
    
     Checking hardware requirements...
    
     I2C must be enabled for Pan-Tilt HAT to work
     I2C is now enabled
    
     Checking packages required by I2C interface...
    
     Pan-Tilt HAT comes with examples and documentation that you may wish to install.
     Performing a full install will ensure those resources are installed,
     along with all required dependencies. It may however take a while!
    
     Do you wish to perform a full install? [y/N] y
     Checking install requirements...
    
     Checking for dependencies...
    
     Installing python-pantilthat...
     install ok installed
    
     Installing python3-pantilthat...
     install ok installed
    
    
     Checking for additional software...
    
     python-picamera is already installed
     python3-picamera is already installed
    
     Downloading examples and documentation...
     Resources for your Pan-Tilt HAT were copied to
     /home/pi/Pimoroni/pantilthat
    
     All done!
    
     Enjoy your Pan-Tilt HAT!
    
     pi@raspberrypi:~ $ sudo reboot
    
  • なんか、色がおかしい?
    赤いのを映すと青になる、青いのが赤になる..RGB並びの設定がおかしい?
    OpenCVから、v4l2の設定ができない? CV_CAP_PROP_FORMAT ??
    直し方が分からないので、PythonのPiCameraを使用するように変更。

    • sudo apt-get install python-picamera

    • picameraを使用するようにごにょごにょしたコード。

       #!/usr/bin/env python
       ## http://qiita.com/mt08/items/97d89a09e5129e10f88c
      
       from picamera.array import PiRGBArray
       from picamera import PiCamera
       import cv2, sys, time, os
       from pantilthat import *
      
       # Frame Size. Smaller is faster, but less accurate.
       # Wide and short is better, since moving your head
       # vertically is kinda hard!
       FRAME_W = 192
       FRAME_H = 112
      
       # Default Pan/Tilt for the camera in degrees.
       # Camera range is from -90 to 90
       cam_pan = 90
       cam_tilt = 60
      
       # Set up the CascadeClassifier for face tracking
       #cascPath = 'haarcascade_frontalface_default.xml' # sys.argv[1]
       cascPath = '/usr/share/opencv/lbpcascades/lbpcascade_frontalface.xml'
       faceCascade = cv2.CascadeClassifier(cascPath)
      
       # Set up the capture with our frame size
       camera = PiCamera()
       camera.resolution = (FRAME_W, FRAME_H)
       camera.framerate = 32
       rawCapture = PiRGBArray(camera, size=(FRAME_W, FRAME_H))
       time.sleep(0.1)
      
       # Turn the camera to the default position
       pan(cam_pan-90)
       tilt(cam_tilt-90)
       light_mode(WS2812)
      
       def lights(r,g,b,w):
       	for x in range(18):
       		set_pixel_rgbw(x,r if x in [3,4] else 0,g if x in [3,4] else 0,b,w if x in [0,1,6,7] else 0)
       	show()
      
       lights(0,0,0,50)
      
      
       for image in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
      
       	frame = image.array
      
       	# This line lets you mount the camera the "right" way up, with neopixels above
       	frame = cv2.flip(frame, -1)
       	
       	# Convert to greyscale for detection
       	gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
       	gray = cv2.equalizeHist( gray )
      
       	# Do face detection
       	faces = faceCascade.detectMultiScale(gray, 1.1, 3, 0, (10, 10))
          
       	# Slower method 
       	'''faces = faceCascade.detectMultiScale(
       		gray,
       		scaleFactor=1.1,
       		minNeighbors=4,
       		minSize=(20, 20),
       		flags=cv2.cv.CV_HAAR_SCALE_IMAGE | cv2.cv.CV_HAAR_FIND_BIGGEST_OBJECT | cv2.cv.CV_HAAR_DO_ROUGH_SEARCH
       	)'''
       	
       	lights(50 if len(faces) == 0 else 0, 50 if len(faces) > 0 else 0,0,50)
      
       	for (x, y, w, h) in faces:
       		# Draw a green rectangle around the face
       		cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
      
       		# Track first face
       		
       		# Get the center of the face
       		x = x + (w/2)
       		y = y + (h/2)
      
       		# Correct relative to center of image
       		turn_x  = float(x - (FRAME_W/2))
       		turn_y  = float(y - (FRAME_H/2))
      
       		# Convert to percentage offset
       		turn_x  /= float(FRAME_W/2)
       		turn_y  /= float(FRAME_H/2)
      
       		# Scale offset to degrees
       		turn_x   *= 2.5 # VFOV
       		turn_y   *= 2.5 # HFOV
       		cam_pan  += -turn_x
       		cam_tilt += turn_y
      
       		print(cam_pan-90, cam_tilt-90)
      
       		# Clamp Pan/Tilt to 0 to 180 degrees
       		cam_pan = max(0,min(180,cam_pan))
       		cam_tilt = max(0,min(180,cam_tilt))
      
       		# Update the servos
       		pan(int(cam_pan-90))
       		tilt(int(cam_tilt-90))
      
       		break
      
       	frame = cv2.resize(frame, (540,300))
       	frame = cv2.flip(frame, 1)
          
       	# Display the image, with rectangle
       	# on the Pi desktop 
       	cv2.imshow('Video', frame)
       	key = cv2.waitKey(1) & 0xFF
      
       	# clear the stream in preparation for the next frame
       	rawCapture.truncate(0)
      
       	# if the `q` key was pressed, break from the loop
       	if key == ord("q"):
       		break
       	
       # When everything is done, release the capture
       cv2.destroyAllWindows()
      




## TODO
- スクショとか、動作動画とか、載せる?
- 笑い男マーク対応?
- 複数顔検出して、一番大きいやつを追跡とか?




9
12
0

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
  3. You can use dark theme
What you can do with signing up
9
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?