LoginSignup
3
4

More than 1 year has passed since last update.

Raspiに接続したUSBカメラの画像をFlaskで飛ばしてWin10PCのOpenCVで再生する

Last updated at Posted at 2021-10-21

Raspi4のOS作成方法

最新の方法は、ラズパイ公式サイトの「OSインストールページ」の「Raspberry Pi Imager」を使う方法です。

参考HP
https://taku-info.com/raspi-osreinstall/
https://www.indoorcorgielec.com/resources/raspberry-pi/raspberry-pi-os%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab/

pythonのバージョンを3.7.3に変える

参考HP
https://www.ingenious.jp/articles/howto/raspberry-pi-howto/python-3-change/

インストール直後の初期設定では、デフォルトで使用されるPythonは、Python2系になっています。
デフォルトで使用するPythonをPython3系に変更する方法について記載されてます。

Raspi側のプログラム

参考HP
https://github.com/EbenKouao/pi-camera-stream-flask
https://qiita.com/Gyutan/items/1f81afacc7cac0b07526
https://qiita.com/naoppy/items/74bdfa8216c7223f584b

ライブラリーのインストール

sudo apt-get update 
sudo apt-get upgrade

sudo apt-get install libatlas-base-dev
sudo apt-get install libjasper-dev
sudo apt-get install libqtgui4 
sudo apt-get install libqt4-test
sudo apt-get install libhdf5-dev

sudo pip3 install flask
sudo pip3 install numpy
sudo pip3 install imutils

参考HPでは下記コマンドでopenCVをインストールしているがRaspi4ではインストールに失敗する

sudo pip3 install opencv-contrib-python
sudo pip3 install opencv-python

そこで、他の方法でopenCVをインストールする
参考HP
https://qiita.com/naoppy/items/8a2178383859178e6d7e

pip3 install opencv-contrib-python==4.1.0.25

USBカメラを認識させるためのライブラリーをインストールする

USBカメラ認識について書かれてます
https://qiita.com/iwatake2222/items/d6645880c5bb91ce8a85

カメラ制御にはVideo4Linux2(V4L2)というAPIを使用します
V4L2を使用するためには、事前にコマンドでモジュールを組込んでおく必要があります。
これを実行するとカメラがビデオデバイスとして認識されます(/dev/video0)

sudo modprobe bcm2835-v4l2

lsusbコマンドでのカメラ確認

$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 046d:c534 Logitech, Inc. Unifying Receiver
Bus 001 Device 003: ID 046d:0825 Logitech, Inc. HD Pro Webcam C920
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

3行目にC920が認識されている

デバイスファイルの確認

$ ls /dev/video*
/dev/video0  /dev/video10  /dev/video12  /dev/video14 /dev/video16
/dev/video1  /dev/video11  /dev/video13  /dev/video15  /dev/video18

Raspi4では、1つのwebカメラに対して2つデバイスファイル(video0とvideo1)が作られる仕様になっている。

USBカメラの詳細を調べるツールu4l-utilsをインストールする

sudo apt-get install v4l-utils

v4l-utilsを使ってUSBカメラを調べる
https://leico.github.io/TechnicalNote/Linux/webcam-usage

$ v4l2-ctl --list-devices
bcm2835-codec-decode (platform:bcm2835-codec):
        /dev/video10
        /dev/video11
        /dev/video12
        /dev/video18

bcm2835-isp (platform:bcm2835-isp):
        /dev/video13
        /dev/video14
        /dev/video15
        /dev/video16

HD Pro webcam C920 (usb-0000:01:00.0-1.2):
        /dev/video0
        /dev/video1

プログラム

参考プログラムをgithubにあげたのでここから落としてください

git clone https://github.com/fuji244tys/streamer

USBカメラの動画をopenCVで取得する

camera.py

import cv2

class VideoCamera(object):
    def __init__(self):
        self.video = cv2.VideoCapture(-1)

        # (-1)はRaspiにつながったカメラを探します

    def __del__(self):
        self.video.release()

    def get_frame(self):
        success, image = self.video.read()
        ret, jpeg = cv2.imencode('.jpg', image)
        return jpeg.tobytes()

        # read()は、二つの値を返すので、success, imageの2つ変数で受けています。
        # OpencVはデフォルトでは raw imagesなので JPEGに変換
        # ファイルに保存する場合はimwriteを使用、メモリ上に格納したい時はimencodeを使用
        # cv2.imencode() は numpy.ndarray() を返すので .tobytes() で bytes 型に変換

Flaskでビデオストリーミング

main.py

from flask import Flask, render_template, Response
from camera import VideoCamera

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

def gen(camera):
    while True:
        frame = camera.get_frame()
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')

@app.route('/video_feed')
def video_feed():
    return Response(gen(VideoCamera()),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

プログラムの実行方法

pi@raspberrypi:~ $ cd streamer
pi@raspberrypi:~/streamer $
pi@raspberrypi:~/streamer $ python3 main.py

Win10PC側のプログラム

RaspiのIPアドレスを調べる方法

参考HP
https://edu.isc.chubu.ac.jp/naga/mri/mri7.html

Flaskのプログラムは別のPCからのアクセスを許可しているので、Flask を実行しているRaspiのIPアドレスがわかれば、同じネットワークに 接続している他のPCからアクセスできる。
IP アドレスは次のコマンドで確認できる。
無線 LAN ルータに接続 している場合は、一般的に割り当てられるアドレスは 192.168.???.??? になる。

pi@raspi4A:~/pi-camera-stream-flask $ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether dc:a6:32:bf:84:5a brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether dc:a6:32:bf:84:5b brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.14/24 brd 192.168.0.255 scope global dynamic noprefixroute wlan0
       valid_lft 79846sec preferred_lft 69046sec
    inet6 fe80::b61d:48f9:cb17:2b3d/64 scope link 
       valid_lft forever preferred_lft forever

無線LANで繋がってるRaspiのIPアドレスは 192.168.0.14 となる

画像受信プログラム

RaspiのIPアドレスを設定すると画像を受信できた。
たまに画像を取れないことが発生したので、取れないときに再起動させるようにしたら連続して動画表示できるようになった。

stream.py
#-------------------------------------------------------------------------------
# Name:         streaming.py
# Purpose:      Win10_PC recieve video from Raspi4 using openCV
#               video streamer be maked by Flask run on Raspi4+USBcamera
#
# Author:       fujioka
#
# Created:     2021/10/20
# Copyright:   (c) T.F. 2021
#-------------------------------------------------------------------------------
import cv2
import time

url = "http://192.168.0.14:5000/video_feed"

#================================================
# func
#================================================
def stream():
    try:
        print('start:' + time.strftime('%Y/%m/%d %H:%M:%S'))
        video = cv2.VideoCapture(url)
        t2=0
        while(video.isOpened()):
            t1 = time.time()
            ret, frame = video.read()
            #------------------------------------------------------------------
            if ret is False:
                print('read error:' + time.strftime('%Y/%m/%d %H:%M:%S'))
                video.release()
                cv2.destroyAllWindows()
                time.sleep(1) #second
                stream()
                break
            #------------------------------------------------------------------
            #cv2.rectangle(frame, pt1, pt2, color, thickness=1
            #                   , lineType=cv2.LINE_8, shift=0)
            cv2.rectangle(frame , (0, 2), (140, 30), (255, 255, 0), -1)
            cv2.putText(frame   , '{:>5.1f} ms'.format((t1 - t2)*1000)
                                , (10, 25)
                                , cv2.FONT_HERSHEY_SIMPLEX
                                , 0.8
                                , (0, 0, 255)
                                , thickness=2)

            cv2.imshow('frame', frame)
            t2 = t1

            #------------------------------------------------------------------
            key = cv2.waitKey(1)
            if key == 27:
                video.release()
                cv2.destroyAllWindows()
                break

    except KeyboardInterrupt:
        pass

    finally:
        video.release()
        cv2.destroyAllWindows()


#================================================
# main
#================================================
stream()

動画表示画面
stream2.jpg

物体検出

RaspiにつないだUSBカメラからの画像をWin10PCで受信できるようになった。次はこの画像に物体検出を行う。

参考HP
Pytorchで物体検出Yolov5を動作させる
https://qiita.com/fujioka244kogacity/items/e5acf8d9bb728e7d1bcc

ここのdetect.pyの--source 指定を0からurlに変えると良い

(yolo5) C:\Users\fujio>cd yolov5
(yolo5) C:\Users\fujio\yolov5>python detect.py --source 0 --weight best.pt
(yolo5) C:\Users\fujio>cd yolov5
(yolo5) C:\Users\fujio\yolov5>python detect.py --source "http://192.168.0.14:5000/video_feed"  --weight best.pt

stream3.jpg

3
4
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
3
4