こんにちは、CCCマーケティング株式会社 データベースマーケティング研究所 技術開発ユニットの矢澤です。
私たちの部門では、Amazon Goのようなスマートストアを実現するための要素技術について研究し、プロトタイプの開発を進めています。今回は、その中でも画像処理の技術を使うことで、どのようなソリューションが可能になるかを紹介したいと思います。
はじめに
スマートストアでレコメンドや売り場の最適化を行う際には、商品を実際に購入したお客さんだけでなく、来店したけれど購入していないお客さん(潜在顧客)の情報が重要となります。
店舗にどんな人が来店しているのかが分かれば、それに合わせて店頭ディスプレイに表示する商品や店内で流すBGMを動的に変えたり、お店の客層に合わせて品揃えや棚割を考えたりすることができるようになります。 商品購入者の情報は、ポイントカードなどでID-POSデータとして収集できますが、非購入者の情報はそれには含まれないため、カメラなどの他の手段で取得する必要があります。
そこで今回は、店舗に防犯カメラが設置されていることを想定し、カメラ画像から来店者の性年代やファッションスタイルを判定する方法を紹介します。防犯カメラの画像を活用することで、特別な機器などを設置しなくても簡単に来店者の属性情報を収集し、マーケティングに活用することができるようになります。
全体構成
カメラ画像の取得から来店者の属性推定、推定結果の送信までの一連の流れは、以下のようになります。
店舗の入口や商品棚などに来店者が近づくと、周囲に設置された防犯カメラによって撮影が行われ、分析用のサーバーに画像が送られます。 分析サーバーでは、送信されたカメラ画像を元に、来店者の属性を推定します。 防犯カメラで顔を撮影可能な場合は、Azure Face APIというサービスによって、人物の性年代などを判定することができます。
防犯カメラの設置場所によっては、来店者の後ろ姿などしか撮影することができず、顔から属性を推定できない場合があります。 そのような場合は、あらかじめ学習しておいた画像分類モデルを利用して、服装からその人の性年代とファッションスタイルを判定します。
このとき、対象者以外の人物や背景が写り込んでいると予測精度が下がってしまうため、セマンティックセグメンテーションと呼ばれる技術を使って、対象人物の特定と背景のマスキングを行います。
無事に属性が判定されたら、Node-REDとMicrosoft Teamsに結果を送ることで、直近の来店者の情報や当日の統計情報などを可視化できるようになります。
以降では、具体的に各ステップで行なっていることの詳細を説明していきます。
防犯カメラでの画像撮影
まずは、防犯カメラで来店者の顔や服装を撮影し、サーバーに画像を送れるようにします。今回は、一般的な防犯カメラを購入し、社内のお菓子売り場に設置して実験を行いました。
購入したカメラは、Ctronics社の以下の商品です。
本カメラには動体検知機能が付いており、人などの物体の動きを検出して、自動で画像を撮影することができます。実際にカメラを設置して動体検知機能をオンにしてみたところ、人が来たときに画像が撮影されることを確認できました(たまに誤検知や検出漏れをすることもありますが・・・)。
このような機能が付いていない普通のカメラの場合でも、プログラム側で動体検知や人物検出を行うことで、来店者がいる場合のみ判定処理を行うことが可能です。
また、上記のカメラは有線と無線の両方のネットワークに対応していますが、今回は社内ネットワークを使用する都合上、LANケーブルを接続して有線でサーバーに画像を送信するようにしました。物理的な接続が完了したら、カメラ専用のブラウザアプリを使って、ネットワークアドレスやFTPなどの設定を行います。
ここで注意点として、画像を受信するサーバー側でも、FTP通信を有効化する必要があります。今回使用したサーバー(Linux CentOS 7)では、以下のコマンドでFTPサーバー用のプログラムをインストール、実行しました。
sudo yum install vsftpd
sudo vsftpd
FTPの通信方法は、アクティブモード(サーバーからクライアントに接続)とパッシブモード(クライアントからサーバーに接続)の2通りがありますが、今回は以下の利点からアクティブモードを選択しました。
- セキュリティ面:社内から社外への接続の方が安全
- ファイアウォール設定の手間:データコネクション用のポート番号が20, 21番に固定化されている
詳細な設定方法などは、使用するカメラやシステム環境によって異なるため、割愛させていただきます。
分析サーバーでの属性推定
防犯カメラの設定が完了したら、分析サーバー上でカメラ画像から属性を判定できるようにします。
今回は、2台のカメラで来店者の顔と服装をそれぞれ撮影するようにしました。送信された服装画像の例を以下に示します。
顔による性年代推定
カメラ画像に来店者の顔が写っている場合は、AzureのFace APIで属性を推定することができます。
Face APIは、Azure Cognitive Servicesの内の一つで、人の顔の認識に特化したサービスです。人物の画像から、顔の位置検出や属性判定、同一人物の識別、似た顔の検索、グループ化、感情認識などを行うことができます。
オンプレ版とクラウド版がありますが、今回はURLにアクセスするだけで簡単に判定を行うことができるクラウドAPIを試しました。処理速度がそこまで必要でない場合は、Freeインスタンスに登録することで30,000トランザクション/月 までは無料で使用することができます。
Face APIを使うには、Azureポータルでリソースを作成する必要があります。ポータル上でいくつかの項目を入力・選択すると、数分でリソース作成が完了し、アクセス用のキーが発行されるので、これを使用してAPIを呼び出せるようになります。
判定に成功すると、以下のようなJSONデータが返されます。
{
'faces': [{
'age': 28,
'gender': 'Male',
'faceRectangle': {
'left': 227,
'top': 284,
'width': 211,
'height': 211
}
}],
'requestId': 'dcf67d28-cf1a-4a72-b1f2-4877eca945d2',
'metadata': {'width': 683, 'height': 1024, 'format': 'Jpeg'}
}
データの内、facesが判定結果となっており、その中のgender, age, faceRectangleキーで性別、年代、顔の位置をそれぞれ取得できます。
画像内に複数の顔が含まれている場合、各人物の判定結果が配列として返ってきますが、今回は商品棚の前に立っているお客さんのみを対象としたかったため、最も顔のサイズが大きい判定結果を使用するようにしました。
また顔が1人も写ってない場合や、検出された顔のサイズが閾値より小さい場合は、属性判定処理をスキップするようにします。
上記のデータを、Node-REDやMicrosoft Teamsなどの外部サービスに送信することで、来店者の属性をより見やすい形で可視化することができます。具体的な送信方法については、後ほど説明します。
服装による性年代、ファッションスタイル推定
来店者の顔がカメラに写っていない場合も、学習済みの画像分類モデルを利用して、服装から性年代を判定することができます。
また、ファッションのスタイル(カジュアル、シンプルなど)を分類するモデルを同様に用意すれば、お客さんのファッションデータを収集することも可能です。ここでは、2台目の防犯カメラで撮影された顔の写っていない画像を使って、服装による属性推定に挑戦してみたいと思います。
画像分類モデルによる属性推定
服装を基にした性年代、ファッションスタイルの判定では、CNNと呼ばれるディープラーニングのモデルを使って画像を分類します。
CNNについては、一般的な画像データセット(ImageNet, CIFARなど)を使ってネットワークのパラメーターを学習したモデルが公開されており、データセットに含まれている物体(動物、乗り物など)であれば、自力で学習しなくてもそのまま予測を行うことができます。
しかし、服装から性年代やファッションスタイルを判定できる学習済みモデルは見当たらなかったため、今回はあらかじめ収集したファッション画像を使って、分類モデルを新たに学習します。
ただし自力で学習を行うといっても、CNNを一から学習すると精度や処理時間の面であまり良くないので、学習済みモデルの出力層以外は特徴抽出器としてそのまま使用し、いくつかの層を追加して最終的に予測クラス数分の出力が得られるようにした上で、追加した層の重みのみを学習するようにします。
このように学習済みモデルのパラメーターを初期値として、ネットワークの一部または全部の層を追加学習することをFine-Tuningといい、有用性が高いことが知られています。
今回は、TensorFlow Hubという学習済みモデルを読み込むためのツールを使って、Fine-Tuning用のプログラムを実装しました。服装から人物の属性を推定できるようにするため、性年代、スタイルごとのファッションコーディネート画像を使って、モデルを学習します。対象のファッションスタイルは、8クラスとしました。
学習画像の枚数を増やすため、Data Augmentationによってデータの水増しを行いました。また、今回使用したファッション画像はクラスによって枚数に偏りがあったため、不均衡データに対応した損失関数 を使用しました。 CNNの形状はInceptionResNetV2をベースとし、学習済みモデルの出力層の代わりに、3つの全結合層(ノード数は1000, 100, 8、活性化関数はReLU)を追加しました。これらの追加層を、Adam Optimizerで最大100エポック(Early Stoppingあり)学習し、最終的なパラメーターを分類モデルに使用しました。
画像の一部を検証用データとしてモデルの精度(Accuracy)を確認したところ、性年代判定とファッションスタイル判定でそれぞれ0.40, 0.25と、低めの値になりました。
ただし、今回は画像分類自体の精度はあまり重要でなく、防犯カメラによる属性推定のプロトタイプ作成が主目的であったため、このモデルをそのまま使用しました。分類精度を向上させたい場合は、学習画像の枚数を増やしたり、もう少し有用なデータを使ったりするなどの対応策が考えられます。
推定結果として、クラスごとの所属確率が得られます。このうち確率が最大となるクラスを取得することで、対象者の性年代やファッションを一意に決定することができます。
セマンティックセグメンテーションによる人物検出
上記の分類モデルに防犯カメラ画像を入力することで、来店者の属性を出力できますが、そのままでは性年代やファッションスタイルをうまく推定することができません。
なぜなら、画像に対象者以外の人物や背景などが写り込んでしまい、それらが予測時に悪影響を及ぼすためです。実際、今回お菓子売り場で撮影した画像では、床に緑色のマットが敷かれているため、来店者が緑色の服を着ていると誤認識されてしまう可能性があります。
そこで、セマンティックセグメンテーションと呼ばれる画像処理技術を用いて来店者の画像位置を特定し、それ以外の部分をマスキングすることで入力画像に余計な物体が含まれないようにします。
セマンティックセグメンテーションとは、画像のどこに何が写っているかを推定するもので、工場での異常検知や医療画像の診断、自動運転用のデータ作成などに活用されています。
物体の位置を矩形で抽出する一般的な物体検出技術と比較して、ピクセル単位でより細かく認識できるという利点があります。
今回はセマンティックセグメンテーションの中でも、MaskR-CNNという手法を使用します。
MaskR-CNNは、FasterR-CNNという物体検出技術を基にした手法で、セグメンテーション用のネットワーク構造や精度向上のための工夫が追加されています。
はじめに矩形単位での物体検出を行い、物体が見つかった領域のみピクセル単位でクラスを予測することで、効率的にセグメンテーションを行うことができます。
MaskR-CNNについても、CNNと同様に学習済みモデルが公開されています。推定用のプログラムは、Kerasで実装された以下のコードを活用させていただきました。
FPN, ResNet101というアーキテクチャに基づいたネットワークになっており、MS COCOデータセットで学習されています。MS COCOには人のアノテーションデータが含まれているため、Fine-Tuningを行う必要なく、学習済みモデルをそのまま人物の検出に使用することができます。
上記のモデルで画像中の人物位置を推定し、予測スコアや領域サイズが閾値以上となっている場合に人物として判定するようにしました。
人物以外のピクセルは、全て白色(RGB値:(255, 255, 255))にマスキングします。 またFace APIのときと同様に、画像中に人が一人も見つからなかった場合は、属性判定を行わないようにしました。
MaskR-CNNによるセグメンテーション結果の例を以下に示します。
推定スコアの閾値を0.999にしても高確率で来店者を検出することができ、領域もかなり細かく抽出できているため、MaskR-CNNの性能が相当良いことが分かりました。
このセグメンテーション後の画像を属性分類器に入力することで、より効果的に性年代やファッションスタイルを推定できるようになります。
実際に上記の画像を入力したところ、「エッジ」なファッションの「20代男性」と判定されました。
さらに、 ドメイン適応 と呼ばれる技術を活用することで、コーディネート画像で学習した画像分類モデルを防犯カメラ画像に適した形に変換することもできます。
ただし、そのためには防犯カメラで撮影した画像を大量に用意する必要があり、今回は検証期間の都合上、試すことができませんでした。データがある程度溜まったら、検証してみたいと思います。
推定結果の送信
最後に、Face APIやオリジナルの属性分類器による推定結果を外部のサービスに送信し、可視化する方法を説明します。
推定した結果をJSONファイルなどに追記していっても良いのですが、一々ファイルを開いて確認するのは面倒であり、また他のセンサの情報(商品在庫、気温など)やその日の来店者の内訳などをまとめて確認できた方が何かと便利です。
外部のサービスを活用すれば、数行のプログラムを書くだけで、そのような可視化を簡単に実現することができます。
Node-REDへのデータ送信
一つ目は、Node-REDへのデータ送信です。
Node-REDは、一言でいうとIoTのデバイスやAPI、サービスなどを相互接続するための開発ツールです。ダッシュボード上で、各デバイスから送られた情報を一覧表示できるようになっています。
Node-REDに判定結果を送信する方法として、あらかじめ作成したAPIに分析サーバーからHTTPリクエストを投げる形で、データを送ることができます。
実際のソースコードでは、Node-REDサーバーが稼働していない場合でもプログラムが停止しないように、エラー処理を行っています。
また実装上の注意点として、推定結果のデータ型に気をつける必要があります。TensorFlowのプログラムで画像の所属クラスを予測した場合、変数の型がnumpy.float32となり、そのままJSONデータに変換しようとするとエラーになってしまいます。
そのため、所属確率の値をPythonのfloat型にキャストしてから送るようにします。
Teamsへのデータ送信
二つ目は、Microsoft Teamsでの通知です。Teamsは、Microsoft Office365のチャットソフトで、bot形式でプログラムからメッセージを送ることもできます。
チャネルに対してIncoming Webhookのコネクタを作成し、Node-REDと同様にプログラムからデータをPOST送信します。
プログラムが完成したら、whileループなどで永続的に実行し、お客さんが来るたびに属性推定を行えるようにします。
試しに1日動かしてみたところ、その日の性年代ごとの来店者数がカウントされていることを確認できました。
おわりに
本章では、防犯カメラの画像から、お店に来た顧客の性年代やファッションスタイルを推定する方法を紹介しました。
リアルタイム性が必要な場合や、分析用のサーバーが用意できない、あるいは個人情報の観点からサーバーに画像を送ることが難しい場合などは、Jetsonやラズパイなどのモバイルデバイスにモデルをデプロイして、エッジ処理を行うことも考えられます。
ただしその場合は、本章で紹介した画像処理モデルをそのまま使用すると計算速度やメモリ不足の問題があるため、より軽量なネットワークを使うなどの工夫が必要となります。 また今回はカメラの静止画のみを使用しましたが、動画全体や音声などを活用することでより詳細な情報が収集できると思われるため、今後の課題として取り組んでいきたいです。
本記事は、2020年に行われた技術書典8に出展した本の内容の一部であり、CCC MARKETING TECH BLOGを、再編集して転載したものです。