はじめに
セーフィーで画像認識エンジニアをしている橋本です。本記事では、先日発売されたエッジAIカメラSafieOneで利用可能なサービス「Store People Detection Pack」で開発した画像認識システムとアルゴリズムについて紹介したいと思います。
「Store People Detection Pack」とは、小売業界の課題を解決するために作られた人物検出AIを使ったサービスです。別記事でも解説されていますので、是非合わせてご覧ください。
本サービスを利用することで、Webマーケティングでは当たり前に可視化できているコンバージョンにつながる顧客の行動を、リアルな店舗の映像から明らかでき、小売業界での映像データの利活用が進むのではないかと期待しています。
Webサイトでは、どのようにページを遷移して商品を探し最終的な購入に至ったのかを把握できるため、「クリック率(逆に離脱率)がどのくらいなのか」といった情報から分析を行い、最適化が行いやすくなっています。一方で、リアルの店舗では、レジの売り上げ(POS)データで最終結果は分かるものの、購入に至るまでの経緯はブラックボックスになっています。
例えば、「今日は『かつ丼弁当』を食べよう」と思い立ってスーパーマーケットのお弁当コーナーに行き購入に至った目的買いのお客様と、店舗で様々なお弁当を検討して「かつ丼弁当」を購入したお客様の違いをPOSデータから見分けることはできません。本サービスを使えば「かつ丼弁当」の前で立ち止まった人数を可視化でき、さらに録画映像を振り返って要因分析を行うことができます。
システムの概要
本サービスの技術的な特徴はエッジAIを使った画像認識を行っていることです。エッジAIというのは画像をアップロードしてサーバー上で推論するのではなく、カメラ毎に搭載されたプロセッサで推論するAIのことを指しています。一般的に、エッジデバイスにはAIアクセラレータが搭載されており、ニューラルネットワークを効率的に計算することができます。SafieOneの場合はQualcomm製のDSPが搭載されており、SNPE(Snapdragon Neural Processing Engine)SDKを使ってネットワークの実行部分を実装しています。
本サービスがエッジAIを採用している理由としては、
- 低コストなリアルタイム処理が得意
- デバイスごとに異なる賢さのAIをインストールできる(個別AI)
の2点が挙げられます。
リアルタイム処理については、カメラの映像をデバイス内で直接処理できるのでアップロードが不要でレイテンシが少なく、専用アクセラレータを用いるためサーバー上の汎用ハードウェア(CPU、GPU)と比べてコストパフォーマンスに優れています。
また、個別AIについては、まだお見せできないのですが、特定のユーザ・業種に対して専用のAIを簡単に作成してカメラ毎に異なる賢さを搭載できるように開発を進めています。サーバー推論の場合はある程度のユーザ数で推論モデルと計算資源を共有することになるため、低コストな個別対応が難しいといった課題があるのですが、当社は自社でエッジAIカメラを販売しているため対応が行いやすくなっています。
システム全体の構成は上記のようになっています。SafieOneにはオプションを付けることで様々なアプリ(AI-App)がインストールできるようになっています。PeopleDetectionはエッジAIの本体でニューラルネットを使った画像認識を行うアプリです。SafieEdgeAppFrameworkはSafieOneにインストールされるアプリのライフサイクル管理や、カメラ画像をアプリに送信する役割を持っています。SafieClientはカメラハードウェアの制御、映像や検出結果(イベント)をサーバに送信するのが主な役割です。SafieEdgeAppFrameworkやSafieClientについては、別記事で解説されていますので是非合わせてご覧ください。
本サービスではエッジ側で画像認識結果をある程度集計して、ユーザが興味を持つ有益な事象(イベント)だけをサーバーに送って保存する仕組みになっています。ユーザーがSafieViewerを操作して検出結果の時系列グラフを見たいといったリクエストを送った場合には、サーバーに保存されているイベントを使って描画するという処理の流れになります。
エッジAI本体のPeopleDetectionは上のようなパイプラインで処理を行っています。物体検出(Object Detection)、追跡(Tracking)、イベント発行(Event Publishment)については次節以降で詳細を説明します。
物体検出
画像認識とは画像に含まれる意味や構造を抽出して、テーブルデータとして利活用できる状態にするプロセスのことを言います。画像認識のタスクはいろいろありますが、本サービスでは物体検出を利用しています。物体検出とは、オブジェクトのカテゴリと位置と大きさを検出するタスクのことを言います。物体検出(object detection)は受け取った画像から、検出結果(raw detections)を計算して、次の追跡(tracking)処理に渡します。
SafieEdgeAppFrameworkにはビデオフレーム購読用のインターフェースが定められており、これをアプリ開発者が実装すると、当該メソッドが1 sec / 10 fps = 100ms間隔でcall backされて、アプリがカメラから画像を取得できる仕組みになっています。推論間隔が空いてしまう場合に、人物の動きが大きくなってトラッキングが不安定になるため、パイプライン全体のレイテンシの平均値と標準偏差を計測して、100msに収まるようにネットワークの選定とチューニングを行っています。
当社では、MobileNetV2-SSD、Yolov5、YoloXなどのアルゴリズム調査とチューニングを行い最も性能の良いネットワークと学習結果を採用しています。物体検出のアルゴリズムの進歩は早く、最近はPicoDet、Yolov7など新しいネットワークが登場していますので随時アップデートをしていきたいと考えています(のでエンジニアを鋭意募集しております!)。
学習時の工夫
画像認識の学習では、推論環境と学習時で画像の分布を合わせることが重要です。当社のカメラ(左)は天井に設置することが多く俯角が大きいことや、水平114° 垂直60°の広角レンズを使っているため、人物の見え方がCOCOのような汎用的なデータセット(右)とはかなり異なってきます。そこで、COCOをベースとしながら、当社のドメインに合わせた画像を約21,000枚追加したほか、画像回転のデータ拡張を強めにかけることで、パースによる人物の傾きに対応するようにしています。
量子化の工夫
エッジ実装では高速な演算と引き換えに、量子化誤差によって推論精度が低下することがあります。CPUでは32ビット浮動小数、GPUでhalf precisionを使った場合は16ビット浮動小数が利用できるため、丸め誤差を気にする必要はありませんが、SafieOneのDSPで8ビット固定小数を利用した場合、256 段階の表現しかできないため考慮が必要になります。量子化誤差を少なくするためのポイントは、
- 各レイヤーの出力の値域を絞る
- 出力の分散ごとにtensorを分ける
ことです。
上の図はYolox-nanoの1・2番目の畳み込みレイヤーをnetronで可視化したものです。デフォルトのactivationはSiLU(左)となっていますが、上界がない(unboundedな)ため大きな値が出力される可能性があります。そうした場合に8bitで量子化するとステップ幅が大きすぎるためおおきな丸め誤差が発生し細かな諧調が失われる可能性があります。そこで、学習時にReLU6(右)など適当な閾値でクリップするようなactivationを使って値域を限定することで、学習時の性能(mAP)は下がりますが、8ビット変換時の量子化誤差を低減できました。
また、フレームワークに依存しますがchannel単位の量子化に対応していない場合(tensor単位の量子化しか対応していない場合)は注意が必要です。畳み込みの出力するtensorの分散がchannel毎に異なっていた場合、分散の大きなchannelにつられて量子化幅が決定され、分散の小さなchannelの情報が消えてしまいます。これを解決するには、分布が似ているチャネルごとにconvolutionの出力を分ける必要があります。
Yolox-nanoに416×416の画像を入力した場合に、一番大きな特徴量マップ(52×52)には、4チャネル(x, y, w, h)を出力する回帰用のヘッダ(左)、objectness(0~1)を出力する分類用のヘッダ(真ん中)、11クラスのスコア(0~1)を出力する分類用のヘッダ(右)が接続されています。回帰用のヘッダは値域が限定されないため、分類用のヘッダと同じtensorに纏めないほうが良いとされています。このネットワークでは、畳み込みは異なる経路で行っているため問題ないのですが、その後で1つのtensorにconcatする部分に注意する必要があります。1つのtensorにすることで量子化が再度行われ、丸め誤差が発生してしまうため、concatの前の出力をCPUの32ビット浮動小数点を使って計算することで精度の悪化を防ぐことができました。
物体検出では一般的に最終レイヤーで回帰と分類を行い、その後、デコード処理としてAddやMultiply、出力をまとめる目的でConcatenateが使われることが多いです。このような変換処理の度にtensor全体で再度量子化が行われ、丸め誤差が繰り返し発生してしまうため、後処理の量子化実行には注意しておくと良いと思います。
トラッキング
トラッキング処理は物体検出の結果(raw detections)を受け取って、人物IDのついた追跡結果(tracklets)を出力します。主な機能として、
- 同一人物に同じIDを割り当てる
- 検出漏れがあった場合に位置を推定して補間を行う
を持っています。PeopleDetectionでは、軽量かつ性能も良いためSORTアルゴリズムを使っています。処理の流れは以下の通りです。
- カルマンフィルタを使って前フレームのtracklet(人物の位置と速度)から現フレームのtrackletを推定する
- 推定したtrackletとraw detectionをハンガリアン法で二部マッチングする
イベント発行と送信
イベント発行(Event Publishment)処理では、追跡処理で出力したtrackletsを受け取り、ユーザが興味を持つ有益な事象が発生した場合に、イベントとしてサーバに送信します。サーバーに送付するイベントは以下の3種類を定義しています。
- 設定した領域が滞留人数と時間の条件をみたした時に送信される PeopleDetectionEvent
- 設定した領域から人物が退出した時に送信される AreaLeaveEvent
- 設定した線分を人物が交差した時に送信される LineCrossEvent
上記のイベントがそれぞれ、
- 立ち入り検知
- 立ち入りカウント
- 通過人数カウント
のサービスに利用されます。
PeopleDetectionEventは「設定した領域で、N人以上、M秒以上の滞留が発生した場合」にサーバーに送信されるイベントです。人物毎に滞留時間を計算することで、一時的にエリアに入った通行人を除くことができます。サンプル動画では3人以上10秒以上の条件を設定していますが、3人がエリアに入っただけでは条件をみたさず、最後に入った人物の滞留時間 t ≥ 10のときに条件が成立したと判定しているのが分かると思います。
このイベントが発生した時には、ユーザに通知を送る、Viewerのタイムラインにフラグとサムネイルを表示するといった処理が行われます。例えば、レジ待ち行列が長くなったタイミングで通知を送ってレジ応援を呼ぶといったオペレーションや、映像の振り返りを効率化するといった活用方法を想定しています。
AreaLeaveEventは「設定した領域から人物が退出したとき」にサーバーに送信されるイベントで、イベントが発生した時刻のタイムスタンプと、人物がその領域に滞在した秒数を含んでいます。このデータをサーバで集計することで時間帯ごとにエリアに滞在していた人数を計算して、時系列グラフを表示できるようになっています。さらに、「N人以上、M秒以上」のクエリで絞り込むことで立ち止まりの人数だけを可視化することもできるため、通行人と立ち止まりの比率を使ったファネル分析といったご活用をしていただいています。
LineCrossEventは「設定した線分を人物が交差したとき」にサーバーに送信されるイベントで、イベントが発生した時刻のタイムスタンプと、線分を交差した方向を含んでいます。サンプル動画ではOut方向に2人、In方向に1人をカウントしています。
線分の前後でうろつく人物を過大にカウントするのを防止するため、線分を跨いだら同一人物に対して一定のクールダウン期間を設けるなど、フィールドテストで得られた知見から細かな改良を行ってきました。このデータもサーバーで集計されて時間帯ごとの入退場人数を計算して、時系列グラフを表示するのに使われます。店舗入り口や通路に設置して人流の解析に使用するなど、様々な用途でご活用をいただいています。
まとめ
本記事では、SafieOneで利用可能なサービス「Store People Detection Pack」で開発した画像認識システムやアルゴリズムについて紹介しました。当社のクラウドには、15万台以上のカメラが常時接続されており、画像認識サービスを開発するのに恵まれた環境だと思います。本記事で紹介したサービスの他にも、多様な映像サービスの考案と開発を進めていますので、是非エントリーしてみてください。