激安IPカメラ「TP-Link Tapo C100」と「Yolo v5」で人物識別できるスマート監視システムを構築する

この記事では、 お手軽監視カメラであるTP-Link Tapo C100 を使って撮影した映像から、yolo v5で人物等の識別をする方法を紹介します。

カメラに写った人物が誰か辺りまで識別できたら楽しそうですよね。

郵便や宅配便、新聞配達などが判別できれば、不在時に通知するとか訪問履歴を検索するとか、使い方によっては結構便利かもしれません。

今回はWindows10におけるyolo v5の導入からTapo C100との接続、自前のデータセットを使った学習、識別までを解説します。

使うカメラの準備

カメラ「 TP-Link Tapo C100 」について

amazonで買える「TP-Link Tapo C100」は3000円以下で手に入り、性能も高い良コスパなカメラです。

私はセール等によって2000円程度でいくつか購入し、玄関に設置しています。

クリックで拡大

Tapo C100は通常スマートフォンのアプリのみからカメラ映像を見られるようになっていますが、一部機能を有効化するとRTSPによってネットワークを介してカメラ映像を取得することができます。

RTSPは動画を配信するためのネットワークの規格で、HTTPの動画版みたいなものです。

カメラのRTSP配信機能を利用する

まず、カメラを買ったら専用のアプリ「TP-Link Tapo」をスマートフォン等にインストールし、マニュアルに沿ってカメラを設定します。

設定後、「カメラの設定」から「高度な設定」→「カメラのアカウント」へと進み、RTSPでアクセスできるユーザのアカウントを作成します。

Tapoのアプリ自体で作ったアカウントとは別物になります。

クリックで拡大

アカウント作成画面にて、適当なユーザ名とパスワードを設定し保存します。

RTSPを使って配信された映像にアクセスする際に、このユーザ名とパスワードが必要になります。

アカウトを作成すると、 同じネットワークからRTSPの配信へアクセスすることが出来るようになります。

RTSPのリンクは

rtsp://ユーザー名:パスワード@カメラのIPアドレス:554/stream1

です。

ユーザ名がroot、パスワードがadmin、カメラのIPが192.168.1.100の人は、「rtsp://root:admin@192.168.1.100:554/stream1」が目的のアドレスになります。

RTSPのリンクはよく見るHTTPのリンクに似ていますが、一般的なブラウザからこのリンクにアクセスすることはできません。

Youtube liveの配信などによく使われているOBS studioというソフトを使えば、このRTSPのリンクから映像を視聴できます。

OBS studioを開いて、「ソース」の+を選択

クリックして拡大

「メディアソース」を選ぶ

クリックで拡大

適当な名前をつけてOKをクリック

クリックで拡大

ローカルファイルのチェックを外すと出てくる「入力」の欄にRTSPのリンクを貼り付け

クリックして拡大

OKを押すとカメラ映像が表示されます。

映像は夜間だと赤外線カメラに切り替わる

YOLOv5の導入


カメラ映像をPCで取得することが出来るようになったので、これを識別するプログラムを構築します。

使うのは画像認識でおなじみのYOLOの5バージョンです。

YOLOv5のインストール

環境

  • windows10
  • anaconda 1.7.2
  • conda 4.8.4

anaconda環境を整えてあり、仮想環境で作業できるようになっていることを前提に作業します。

windowsの検索窓に「Anaconda Prompt」と入力してターミナルを起動

起動したら以下コマンドで仮想環境を作成

環境名はyolov5にしました。

conda create -n yolov5 python=3.6 

環境を起動

conda activate yolov5

yolov5をgitクローン

git入ってない人はgitインストールする

git clone https://github.com/ultralytics/yolov5
cd yolov5

pipで依存するパッケージをインストールする。

pip install -r requirements.txt

これで終了。

適当なwebカメラを繋いで以下のコマンドを実行すると、デフォルトの学習済みデータで識別ができます。

カメラが別のになる人はsourceの番号を変えてみてください。

python detect.py --source 0 --weights yolov5s.pt

weightsのオプションはデフォルトで付いてくる重みファイルで、全部で5つあるようです。

上から順に速度重視、下に行くほど正確性重視

  • yolov5s.pt
  • yolov5m.pt
  • yolov5l.pt
  • yolov5x.pt
  • yolov3-SPP.pt

カメラの映像を入力する

簡単にYOLOv5をセットアップしましたが、これにカメラの映像を入力する必要があります。

方法としては、

コマンドのsourceの入力引数にRTSPのリンクを貼り付けるだけ。これだけでストリーミングから識別まですべてやってくれます。

ここらへんは本当に便利で感動しますね!

python detect.py --source rtsp://root:admin@192.168.1.100:554/stream1 --weights yolov5s.pt

カメラ映像がしばらくすると真っ暗(ブラックアウト)してしまう人

私の環境では、上記の方法でカメラ映像から識別ができましたが、しばらくすると映像画面が真っ暗になり、何も表示されなくなってしまいました。

調べると、RTSPのカメラで似たような事になっている人がいるようで、結論としてはサーバ(カメラ)側の問題で配信が途切れていることが原因のようです。

https://github.com/ultralytics/yolov5/issues/4709

https://github.com/ultralytics/yolov5/issues/3721

そして、YOLO5Vでは一度セッションが切断されると、そのまま暗転してしまうようです。

そこで、少しコードをいじってセッションが切れたことを検知して待機し、再接続を試すように変更を加えてみました。

変更するのは、yolov5/blob/master/utils/datasets.pyの279行目、LoadStreamsクラスです。

まずは311行目を以下のように変更します。

self.threads[i] = Thread(target=self.update, args=([i, cap]), daemon=True)
self.threads[i] = Thread(target=self.update, args=([i, cap, s]), daemon=True)

その後、322行目からのupdate関数を以下のように変更します。

    def update(self, i, cap, s):
        # Read stream `i` frames in daemon thread
        n, f, read = 0, self.frames[i], 1  # frame number, frame array, inference every 'read' frame
        while cap.isOpened() and n < f:
            n += 1
            (grabbed, frame) = cap.read()

            if not grabbed:
                print("\033[31m"+"--------DISCONNECTED--------"+"\033[0m")
                print("\033[31m"+"reconnecting to"+str(s)+"\033[0m")
                cap.release()
                time.sleep(5)
                cap = cv2.VideoCapture(s)

            # _, self.imgs[index] = cap.read()
            cap.grab()
            if n % read == 0:
                success, im = cap.retrieve()
                self.imgs[i] = im if success else self.imgs[i] * 0
            time.sleep(1 / self.fps[i])  # wait time

接続が切れると5秒待って再接続をします。

雑な改変なので時間がかかりすぎた場合は終了してしまいますが、私の環境では今の所これで問題なく動作しています。

YOLOv5でグラボ使う環境を構築する

この先の学習の項目では機械学習を走らせるわけですが、GPUを使う場合とそうでない場合で速度が全然違います。そのため、 グラボが乗っている人は特に理由がなければ使うことをおすすめします。

しかし、デフォルトで構築されるYOLOv5の環境ではGPUを使えません。そのため、現状から少し環境を移行する必要があります。

このサイトを参考にしました。

https://blackarmor.blogspot.com/2021/06/windows10gpuyolov5.html

参考先ではminicondaを使っていますが、普通のcondaでも動作しました。

人物の学習

いよいよ予め用意されたデータセットではなく、学習を行ってオリジナルの環境での認識を行えるようにしていきます。

流れとしては、

学習に必要な教師画像を集める

画像をアノテーションしてデータセットを作成

学習!

となります。


画像を集める

認識したい対象のデータをとにかく沢山集めます。

枚数としては、一つの対象につき最低100枚ぐらいだと思います。

家族3人と郵便配達、宅配便を識別したければ5×100で500枚は最低必要です。

そして、その画像を可能な限り様々な角度で、偏り無く集めます。

認識はカメラで行うので、その教師素材もカメラで録画した画像から切り出すのが良いです。

事前に1週間程度のTapoで録画した映像を用意しておきます。

なかなか大変な作業になりますが、がんばります。

アノテーション

教師画像の素材に対して、画像のどの領域が認識対象なのかを学習エンジンに教えるため、画像とその検出エリア(検出の正解となる名前)をセットにしたデータを用意する必要があります。

その作業をアノテーションと呼ぶらしいです。

学習エンジンはそのデータをもとに学習を行い、設定した検出物を探してくれます。

VoTTのインストール

アノテーションにはそれ専用のソフトが有り、効果的にアノテーション作業を行うことができます。

アノテーションソフトにもいくつか種類があるようですが、今回はVoTTというものを利用しました。

https://github.com/Microsoft/VoTT/releases

公式のリポジトリの指示に従ってインストールします。

assetsから最新版のexeファイルを見つけてクリック。

今回はvott-2.2.0-win32.exeをダウンロードします。

立ち上げるとこんな画面が起動します。

クリックして拡大

プロジェクトをクリックし、現れた画面のソース接続という所を開いて、集めたカメラの動画が入っているフォルダを指定します。

クリックして拡大

動画や画像が読み込まれ、アノテーション作業の画面になります。

クリックして拡大

こんなかんじで検出対象を矩形で囲って、右上のTAGSを新規追加、選択して検出範囲にタグ付を行います。

クリックで拡大

データセットをYOLOv5の形式にする

VoTTの画面左の欄で「エクスポート」を選択すると、プロバイダーというところで VoTT JSONが選択できると思います。

以下の画像のように設定します。

クリックで拡大

タグ付けの画面に戻り、プロジェクトをエクスポートをクリックすると、エクスポートが開始されます。

しばらく待つとエクスポート完了の通知が出ます。

クリックで拡大

#### roboflowの使い方

VoTTではYOLOv5形式を直接出力することができないため、roboflowというオンラインの機械学習ツールセットを用いて変換しました。

オンラインなので、VoTTでエクスポートしたアノテーション素材を一度アップロードして、変換後のデータセットをダウンロードする必要があります。

roboflowの詳しい使い方は他の記事に譲ります。

手順としては、プロジェクトを「public」で作成、Upload画面にアノテーション素材のファイルを直接ドラッグアンドドロップします。

クリックで拡大

アノテーションされた画像群を、学習用、検証用などに分ける必要があるのですが、自動的にやってくれます。

特に問題がなければデフォルトのままで大丈夫だと思います。

クリックで拡大

アップロードが完了されると現れる画面にて、ひたすらcontinueを押していくと最後のGenerateが現れますので選択。

クリックで拡大

適当な名前でSave Name

クリックで拡大

完了すると「Export」のボタンが出てきます。ここで、プロジェクトがプライベートだとダンロードできません。

FormatでYOLO v5 Pytorchを選択してExport

クリックで拡大

ダウンロードします。

エクスポートしたファイルはこの様になっています。

クリックで拡大

オリジナルデータセットで学習させる

ダウンロードしたフォルダの中から、「train」と「valid」をコピーして、

「ユーザ\yolov5\data」内にペーストします。

次に、同じくroboflowからダウンロードしたフォルダ内にある「data.yaml」を開き、パスの記述を以下のようにペーストした場所の絶対パスに書き換えます。

以下のコマンドで学習を開始できます。

グラボ使う人

python train.py --data data/data.yaml --weights yolov5x.pt --device 0 --batch-size 4 --epochs 300

CPUだけの人

python train.py --data data/data.yaml --weights yolov5x.pt --batch-size 4 --epochs 300

–weightsのオプションで重みファイルを変更できます。

また、epochsは今回は300にしていますが、実際の学習結果をみて過学習など様々な要因から調整する必要があります。

多いほど時間がどんどん伸びます。

学習が始まるとこんな感じになります。

あとはただひたすらPCを冷やしながら待ちます。

私は最終的に、グラボ980Tiで10時間ぐらいかかりました。

学習が終わると、以下のようにResults saved to runs\expXXという出力が出ます。

この runs\expXX にいくと、学習して得られた重みファイルや、正答率などの学習分析が生成されています。

クリックで拡大

学習したオリジナル識別機でカメラ映像を識別させる

上で学習させた重みファイルをweightsに指定してやるだけです。

重みファイルはbest.ptという名前で出力されています。

python detect.py --source rtsp://root:admin@192.168.1.100:554/stream1 --weights C:\Users\~~~\yolov5\runs\train\expXX\weights\best.pt

カメラ映像が最初と違い、自分で苦労してアノテーションしたタグで認識されていれば成功です。

認識させたカメラ映像は、「yolov5\runs\detect\expXX」以下にmp4として保存されています。

handaru

handaru.net

handaru(はんだる)です。 工作が趣味です。

コメント

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です