2017年7月
            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          

Amazonウィジェット

  • miniPC
  • 最近買った本
  • Raspberry Pi
  • クアッドコプター
  • 書籍ランキング

AdSense

  • 広告
無料ブログはココログ

« 2016年2月 | トップページ | 2016年10月 »

2016年5月

2016年5月18日 (水)

Raspberry PiにWebカメラをつないで遊ぶ Pythonを使ったお手軽プログラミング

Pythonを一通り使えるようになったので、まとまった作品を作ってみました。
RaspberryPiの特徴は、やっぱりGPIOの使えるLinuxだということで、ボタンを押すとWebカメラの画像を撮影するビデオカメラを作ってみることにしました。

openCVのパッケージをインストールします。これはlinux上であればapt-getがあるので簡単にできます。

$ sudo apt-get install libopencv-dev
$ sudo apt-get install python-opencv

カメラの画像を動画として保存するにはこんな風にします。

import cv2

class CameraWriter():
  def __init__(self,filename):
    self.camera = cv2.VideoCapture(0)
    self.fps = 10
    self.size = (640,480)
    self.codec = cv2.cv.CV_FOURCC('I','4','2','0')
    self.writer = cv2.VideoWriter(filename, self.codec, self.fps, self.size, True)
    
  def process(self):
    for i in range(50):
      f,img = self.camera.read()
      self.writer.write(img)
  
if __name__ == '__main__':
  cw = CameraWriter("tameshi.avi")
  cw.process()

codecのところで形式を色々指定できるのですが、raspberry pi では"I420"という指定で動きました。撮影した画像はaviファイルで保存されます。FPSはカメラによって違うようですが、手持ちのカメラ「UCAM-C0113FBBK」ではこの数値がしっくりくるようでした。30FPSとかいくらでも入れられるのですが、PCで再生したときむちゃくちゃ早送りになります。

あとはcameraからreadして、imageをwriterで書き出す。ここが肝心になっています。このループの途中にGPIOの状態を読ませて、ボタンが押下されていなかったらループを出る。つまり撮影を終了するようにすれば簡単そうです。

  def process(self):
    for i in range(50):
      f,img = self.camera.read()
      self.writer.write(img)

次に、raspberry piのGPIOをいじってみましょう。GPIOはboardモードとBCMモードが選べるのですが、BCMモードにすると、ここに書いてあるようなGPIO何番という表記に沿った形になります。モードとピン配置の関係を間違えると迷宮入りするので、GPIOを使うときは必ずBCMモードで使っています。

import RPi.GPIO as GPIO
import time

GPIO.setmode( GPIO.BCM )
GPIO.setup(4, GPIO.IN, pull_up_down=GPIO.PUD_UP)

while 1 :
	if GPIO.input(4):
		print 'Input was High'
	else:
		print 'Input was Low'

上の例では内部プルアップを使っています。GPIO.setupの中でpull_up_downというやつです。これをつかうことで、外部にプルアップ抵抗をチマチマつける必要が無くなり簡素化できます。忘れたくない技です。

ちなみにこのソースを実行すると、GPIO4につないだボタンを押したときだけInput was Lowというメッセージになります。こういう基本動作をちょこちょこ書いて分野別に残しておくと、あとあと役に立ちます。

ここまでこればピンと来たひとは、ソースを書いているかもしれませんね。スレッドを使ってもいいし、シリアルで特定のコマンドを受けたときに撮影を開始させたり、TCP、UDPを活用してネットワークでやってみたり、なにをトリガにするかを考えるだけでも応用が広がります。とりあえずGPIOでやったときの、ボタンを押したときにLEDが点いて、撮影開始⇒ボタンを離すと撮影終了。という処理を書いてみました。カメラ画像書き出しループのところでGPIOを呼んで、条件によって終了させるだけです。

import cv2
import RPi.GPIO as GPIO

class CameraWriter():
  def __init__(self,filename):
    self.SW = 4
    self.LED = 17
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(self.SW, GPIO.IN, pull_up_down = GPIO.PUD_UP)
    GPIO.setup(self.LED, GPIO.OUT)

    self.camera = cv2.VideoCapture(0)
    self.fps = 10
    self.size = (640,480)
    self.codec = cv2.cv.CV_FOURCC('I','4','2','0')
    self.writer = cv2.VideoWriter(filename, self.codec, self.fps, self.size, True)
    
  def process(self):
    GPIO.output(self.LED,GPIO.LOW)
    while not GPIO.input(self.SW):
      GPIO.output(self.LED,GPIO.HIGH)
      f,img = self.camera.read()
      self.writer.write(img)
  
if __name__ == '__main__':
  cw = CameraWriter("tameshi.avi")
  cw.process()

このソースを土台にして、色々ためしてみてください。このソースではボタンを一回押して離すと、プロセスが終了します。また撮影したければもういちどpythonで起動しないといけなくなっています。これを、プロセスを終了するコマンドを送るまで何回でも撮影できるようにするとか、出力ファイル名にタイムスタンプをつけたり、画像の中になにか情報を書き込んだり。openCVなんで、顔認識とか色々できますよ。

« 2016年2月 | トップページ | 2016年10月 »