天井カメラで捉えた人物をコンピュータビジョンで解析した3年間のトライアンドエラーとこれから、というテーマでお話をしました。 #devio2021

配信では話さなかったお話を書いてみます。
2021.10.14

せーのでございます。

クラスメソッドオンラインイベントのDevelopersIO 2021 Decadeにて「天井カメラで捉えた人物をコンピュータビジョンで解析した3年間のトライアンドエラーとこれから」というテーマでお話をしました。

このブログでは感想とライブ配信では話していない部分について補足的に書いてみたいと思います。

動画

アーカイブがアップされるそうです。アップされ次第追加します。

資料

凡ミス

配信中も資料でもずーーーーっと「Jetson mini」と言っていましたが、「Jetson nano」、でした。NVIDIAの方、ごめんなさい。。。

配信で話さなかったこと

ベースモデルの変更

今のカフェのディープラーニングモデルの元になっている論文「Real-time 2D Multi-Person Pose Estimation on CPU:Lightweight OpenPose」にて、元々重たいOpenPoseモデルを軽くするための工夫をいくつかご紹介したのですが、大きな変更として「ベースモデルの変更」があります。

元々OpenPoseはVGG19というニューラルネットワークが使われていました。
これをこの論文ではMobileNetV1に変更していまして、そのままカフェのモデルもベースはMobielNetV1にしています。

このモデルはrefinementの回数を減らして、畳み込みの方法をDepthwise Seperatable Convolutionという形で分離している点が最大の特徴です。
モデルを軽くするにはパラメータの数を減らす事が一番で、このモデルでは畳み込みの方法を分離することでフィルタの数が減り、結果的にモデルが軽くなるわけです。

そしてモデルが軽くなる、という意味ではここ数年話題のVision Transformer、及びその物体検出方法として最近よく聞く「DETR」には注目しています。
Vision Transformerを使った骨格検知は「TransForm」などがあるものの、その精度はまだしっくりきてはいないです。とはいえ、すぐに追い抜け追い越せという状態になるかもしれないので、とりあえずやってみたいと思っています。ただTransformerは精度を上げるにはCNNよりも大量のデータが必要、と聴いていて、ちょっと悩んでいます。

OpenVINOで使う想定のモデルをJetsonに入れる

ベースのモデルの作り方を教えてくれたCubemosさんのお話をしましたが、そもそもCubemosさんのリリースしているCubemos SDKはOpenVINOで動かすことが前提になっています。でもJetsonのCPUはARMベースでIntelではありません。OpenVINOはIntelチップ向けに最適化されるのが特徴のひとつでもあるので、個人的にはIntelエッジを使いたいのですが、コストとパワーのバランス的に今はJetsonが推論に有利、と判断して使っています。

モデルはPytorchにて実装しており、ある程度の間をあけてチェックポイントを保存しています。その学習はAWSのSagemakerを使って一気に回しているので、そこでできたモデルをそのままSagemaker Neoを使ってJetson用に変換しています。

ただしSagemaker Neoを使って変換したモデルはDLR(Deep Learning Runtime)というライブラリを使って動かすことになるので、そこらへんに少しコツが必要です。
詳細はSINさん、山本さんにそれぞれ書かれていますので参考になさってください。

[Amazon SageMaker] イメージ分類のモデルをNeoで最適化して、Jetson Nano+OpenCV+Webカメラで使用してみました

【DLR】SageMaker Neoでコンパイルしたモデルを動かすときに使えるTips(起動高速化・処理高速化)

将来的にはJetsonを使い続けるなら管理の面からもGreengrassでラップした方が良いのではないかと思っています。これは近々ためしてみたいと思います。 またFPSを追求するために、現在最新のIntelチップ(VNNI搭載)とOpenVINOを使ってFP32(単精度浮動小数点演算)のモデルをINT8(8bit整数)に変換し、Intelチップ上で動かす実験を行っています。これがうまくいった場合、

  • INT8にしてIntelのNUC上で動かす
  • INT8にしてAWSのC5インスタンス上で動かす
  • NVIDIAの量子化トレーニングを行ってINT8で学習してJetsonにデプロイ

などが考えられます。 なのでまずはVNNIから試してみたいと考えています。

セグメンテーションはいらないんじゃないか問題

元々の「Real-time 2D Multi-Person Pose Estimation on CPU:Lightweight OpenPose」の実装では、COCOデータセットのアノテーションとしてkeypointの他に「セグメンテーション」が必要でした。当然それをベースにコードを書いているので、データセットは「keypoint」と「segmentations」のあるCOCO形式のデータセットを作っていました。

COCO Annotatorを使って骨格検知用のデータセットを作ってみる

ところが最近コードをよくよく読み返してみると

  • segmentationsは「マスク」を作成する時に使う
  • 「マスク」は学習に必要な人間以外の人間(後ろに映っている群衆など)が学習に悪影響を与えないようその体を隠すために使われる
  • マスクを使うかどうかCOCO形式ではフラグがある(iscrowd)

という事がわかりました。
カフェで学習用に作成している人は基本必要な人以外は画像上にいないので、常にiscrowdフラグはFalseになっています。

ということは、そもそもセグメンテーション自体がいらないのではないか、という疑問が出てきました。
試しにアノテーションとしてセグメンテーションの代わりにバウンディングボックス(人を矩形で囲むアノテーション方法)にして、該当するコードを変更してみたところ、ほぼ同じ精度が出ました。

同じアノテーションでも「セグメンテーションで囲う」のと「バウンディングボックスで囲う」のはかかる時間が段違いに違います。ということで、最近のアノテーションはkeypointとバウンディングボックス形式に変更になりました。

考えるきっかけを与えてくださったFastLabel様、ありがとうございます。

SORTとMulti person tracking modelの中身

ToFに代わる人物トラッキング方法として「SORT」という方法と「Multi person tracking model」という方法にチャレンジしています。

SORTはカルマンフィルタというトラッキング界隈では超有名なフィルタにより、近接するバウンディングボックスにIDを与えるアルゴリズムです。そう、純粋なアルゴリズムなので変更や改修が容易で、どこにでもすぐにデプロイできます。ですが曲線的な動きや物陰に隠れるなどの動きを追いかけることが苦手です。

一方Multi person tracking modelは特徴点を抽出する機械学習モデルを使用して、似た特徴の人をベクトルのユークリッド距離にて比較します。モデルの推論を使うのでそのモデルの良し悪しによって精度が決まってしまう一方、間違ったトラッキングの修正などができたりします。

これはそれぞれ良し悪しに見えるので、今後これらのハイブリッドであるDeepSortや、SORTで追跡をして、ロストした時にのみモデルを使うなど、これらを組み合わせた追跡方法を考えていきたいと思っています。

今こまっていること

Top-Viewの骨格検出モデルはだいぶ精度が上がってきたものの、「人物検出」と「特徴点抽出」のTop-Viewモデルはなかなか難しいです。ここらへんのコツを知ってるよ、もしくはいいTop-Viewのモデルがもうあるよ、という方はぜひTwitterなどでご連絡くださいませ。

ライブ登壇での感想

まがいなりにも「AI スペシャリスト」と名乗っている人間が「最初は全く知識がなかった」ということを対外的に発信するのはかなり恥ずかしかったですが、現状機械学習をやったことがない、もしくは始めたて、または上司から「我が社も機械学習やるぞー」と言われている方は結構多いのではないか、と思い、そんな人たちが実際に会社のプロダクトとしての機械学習モデルを作り、運用できるようになるための助けに少しでもなれば、という思いで話しました。

まとめ

ということで駆け足で発表を振り返ってみました。楽しんでいただけたら幸いに存じます。
機械学習やってるかた、ぜひこれからもご指導ご鞭撻のほどよろしくお願い致します。