teemaxの日記

理工チックなあれこれ

Raspberry pi からのストリーム動画をPythonで処理

Raspberry pi からの動画ストリーム

前回 netcat というソフトウェアを使って、Raspberry pi カメラで撮った動画を PC へストリームする方法を書きました。


Rasberry pi で 動画ストリーム - teemaxの日記

しかしここで、上記事のように動画を PC にストリームするだけではなく、ついでに何かしらの"処理"も施したい、なんて思いました(例えばストリーム動画から顔検出したり)。
そこで今回はストリームした動画を Python コードに取り込んで処理できるようにするところまで書きたいと思います。

Pythonに取り込むには

netcat で送られてくるストリーム動画を PC 側の Python に取り込むためには ffmpeg というプレイヤーを使います。
ffmpeg には -image2pipe というパイプ出力用のオプションがあり、これが役に立ちます。なのでffmpeg が入っていない場合には homebrew 等でインストールしておきます。
brew install ffmpeg

またパイプ出力されたデータの変換に numpy という Pythonの数値計算用のライブラリも使われています。
numpy のインストールは pip で。
pip install numpy

今回、 Python からの動画表示には OpenCV を使っています。
OpenCV というのは画像処理・画像解析用の代表的ライブラリで、様々な画像変換・特徴抽出等を行えます。
OpenCV をインストールする場合はこちら。
brew install opencv

基本的なストリーム動画処理の流れとしては以下を繰り返します

  1. netcat で受け取ったストリームを ffmpeg で変換しパイプ出力
  2. パイプ出力から1フレームずつストリーム画像取得
  3. OpenCV で1フレームずつ表示(このとき自分の行いたい画像処理を施す)

コード

次のようなコードを書いて実行します。
関数とかにはしていないのですがそのうちするかもしれません。

import cv2
import subprocess as sp
import numpy as np

if __name__=='__main__':
    cmd1 = ["nc", "-l", "5001"]
    pipe1 = sp.Popen(cmd1 ,stdin = sp.PIPE, stdout = sp.PIPE)
    cmd2 = ["ffmpeg", "-i", "-", "-loglevel", "quiet", "-an", "-r", "10", "-pix_fmt", "bgr24", "-f", "image2pipe", "-vcodec", "rawvideo", "-"]
    pipe2 = sp.Popen(cmd2, stdin = pipe1.stdout, stdout = sp.PIPE)
    pipe1.stdout.close()

    while True:
        row_img = pipe2.stdout.read(500*500*3) ## img size is now 500x500 and RGB
        img = np.fromstring(row_img, dtype='uint8').reshape((500,500,3)) ## replace row_img's width and height (ex. 300x400 -> 400x300)
        ## Insert your code here if you would like to process image
        
        cv2.imshow("Raspi_Cam", img) ## show stream image

    cv2.destroyAllWindows()

使い方

このコードを

python test.py

で実行した後、raspberry_pi側で

raspivid -w 500 -h 500 -b 2000000 -fps 10 -t 999999 -o - | nc [PCのIP] 5001

というコマンドを実行します。
上コマンド中のオプション( -w -h -b -fps )はいろいろ変えて大丈夫です。

注意点

コードに関して注意点をいくつか挙げると、

  • row_img = pipe2.stdout.read(500*500*3)500*500*3というところには上コマンドで指定したwidth*height*3の値を入れてください。
  • img = np.fromstring(row_img, dtype='uint8').reshape((500,500,3))reshape((500,500,3))にはreshape((height, width, 3))となるように値をセットしてください。
  • cv2.imshow("Raspi_Cam", img)の手前で img に対して OpenCV 等で画像処理を行えば処理された画像が表示されます。

参考文献

  1. http://petrkout.com/electronics/low-latency-0-4-s-video-streaming-from-raspberry-pi-mjpeg-streamer-opencv/
  2. http://zulko.github.io/blog/2013/09/27/read-and-write-video-frames-in-python-using-ffmpeg/

 
 
 

みんなのRaspberry Pi入門 [対応言語:Python]

みんなのRaspberry Pi入門 [対応言語:Python]

クリッパー エコ ティーバッグ ラズベリーリーフティー 20P

クリッパー エコ ティーバッグ ラズベリーリーフティー 20P

スポンサーリンク