【画像処理】リアルタイムマスク処理をラズパイで (Python + Opencv + Raspberry pi)

ラズパイでリアルタイム画像処理

こんにちは.けい( @KeiMameshiba )です.

今回は,ラズベリーパイで「リアルタイムで色を抽出する方法」について,解説していきたいと思います.

具体的には,「OpenCVを使って,マスク処理を行う」ということです.

ライブラリの準備

ここの部分は前回の記事で解説していますので,OpenCVのインストールが済んでいない方は,ぜひ読んでみて下さい.

プログラム

ソースコード

今回使用するソースコードは以下のようになります.

import picamera
import picamera.array
import cv2
import numpy as np

with picamera.PiCamera() as camera:
    with picamera.array.PiRGBArray(camera) as stream:
        # カメラの解像度を320x240にセット
        camera.resolution = (320, 240)
        # カメラのフレームレートを15fpsにセット
        camera.framerate = 15
        # ホワイトバランスをfluorescent(蛍光灯)モードにセット
        camera.awb_mode = 'fluorescent'

        while True:
            # stream.arrayにBGRの順で映像データを格納
            camera.capture(stream, 'bgr', use_video_port=True)

            # 映像データをHSV形式に変換
            hsv = cv2.cvtColor(stream.array, cv2.COLOR_BGR2HSV)
            
            # 取り出す色を指定
            lower_green = np.array([40,50,50])
            upper_green = np.array([70,255,255])
            
            #マスク処理
            mask = cv2.inRange(hsv, lower_green, upper_green)
            
            res = cv2.bitwise_and(stream.array, stream.array, mask=mask)
            
            cv2.imshow("frame",stream.array)
            cv2.imshow("mask",mask)
            cv2.imshow("res",res)
            
            keycode = cv2.waitKey(1)
            if keycode == ord("s"):
                cv2.imwrite("**********.png", stream.array)
                cv2.imwrite("**********.png", mask)
                cv2.imwrite("**********.png", res)
                break
            elif keycode == ord("q"):
                break
            
            stream.seek(0)
            stream.truncate()
            
        cv2.destroyAllWindows()

実行結果

上のプログラムを実行すると,リアルタイムで緑色を抽出することができます.

結果を画像として保存できるようになっています.37~39行目のファイルを指定してください.キーボードで”q”を入力すると,その指定のファイルに保存できるようになっています.

私が試した結果が以下のようになりました.

指定する色(HSV)を変化させて,肌色を検出するプログラムにすると,次のような結果が得られます.

プログラム解説

初期設定

with picamera.PiCamera() as camera:
    with picamera.array.PiRGBArray(camera) as stream:
        # カメラの解像度を320x240にセット
        camera.resolution = (320, 240)
        # カメラのフレームレートを15fpsにセット
        camera.framerate = 15
        # ホワイトバランスをfluorescent(蛍光灯)モードにセット
        camera.awb_mode = 'fluorescent'

初めの2行は,それぞれインスタンスを生成しています.

残りの3行は,解像度や画像をキャプチャするフレームレート,ホワイトバランスをセットしています.

ホワイトバランスは以下から選ぶことができます.

  • 'off'
  • 'auto'
  • 'sunlight'
  • 'cloudy'
  • 'shade'
  • 'tungsten'
  • 'fluorescent'
  • 'incandescent'
  • 'flash'
  • 'horizon'

お使いの環境で選んでください.大抵は室内で行うと思うので,fluorescent = 蛍光灯で大丈夫だと思います.

画像データの変換

色を抽出するために,HSV空間へ変換を行います.BGR空間でも色を抽出することができますが,HSVの方が色指定がしやすいので変換します.

前回の記事では,画像データの配列を解説しました.そのときは,BGR空間の配列を画像データとしていました.

hsv = cv2.cvtColor(stream.array, cv2.COLOR_BGR2HSV)

この行でBGR→HSVへと画像データを変換しています.

マスク処理

mask = cv2.inRange(hsv, lower_green, upper_green)

この文で,指定した範囲内の色を白色にして,それ以外を黒色にして抽出することができます.

画像の値としては,黒色が0で,白色が255です.

cv2.bitwise_and(stream.array, stream.array, mask=mask)

bitwise_and関数で,元の画像から白色にした部分を取り出すことができます.

計算的には,stream.arrayはBGRの値を持っていて,maskは0か255の値を持っています.論理演算のアンド演算と同じように,maskとstream.arrayが両方値を持つところだけ,値が残ります.つまり,maskの白色の部分だけを元の画像から取り出すことができます.

まとめ

今回はラズベリーパイを用いた,リアルタイムマスク処理に挑戦しました.

昨今は自動運転ブームなので,もしかしたらこれと同じようなプログラムで動いているかもしれません.

ラズベリーパイを用いたプログラミングについては,他の記事でも紹介しているのでぜひ読んでみてください.

https://hellobreak.net/%e3%80%90raspberry-pi%e3%80%91/

おすすめの本

ラズベリーパイでちょっとAI寄りなプログラミングやってみたい!と思う方におすすめです.