SSD (Single Shot MultiBox Detector) による物体検出 - 加賀百万石ですが何か?

SSD (Single Shot MultiBox Detector) による物体検出

久しぶりに技術関連(緩め)の記事です。

毎度のことですが仕事でDeep Learning 関連のプロジェクトをやっていまして,分類やセグメンテーション(もどき),回帰の実装はやってみたことがあるのですが,物体検出系は知識としては知っているもののまだ実装(使ってみる)したことがないので,この機会にやってみました。まぁベンチャー企業に所属しているため,とにかく色々自分でもやってみないといけないというような背景もあって半ば強制的に勉強しないといけないという理由もあったりはしますが…。

業界的には今更感はかなりありますが,知識としては知っていてもデータを用意して学習・推論までちゃんとやってみる機会は意外と多くはないのではないかーと思います。

参考:過去記事

▼分類
【PyTorch】MNISTのサンプルを動かしてみた

▼セグメンテーション
【Keras+TensorFlow】Deep Learningで顔検出をしてみた
【Keras+TensorFlow】Deep Learningでテロップ位置を検出してみた

▼回帰
【海洋物理】Deep Learningで海面高度/水温から鉛直プロファイルを推定してみた

追記:SSD300とSSD512の比較

SSDは小さい物体に弱いと言われているため、入力画像の解像度を上げることでどの程度小さい物体を検出出来るようになるかの比較も行ったので、興味があれば併せて見てみてください。

【物体検出】SSD300とSSD512の比較

物体検出のアルゴリズム

物体検出系のアルゴリズムは色々あるのですが,比較的知られている(ある意味枯れている)アルゴリズムはざっくり以下のようなものがあるのは,これを見ている方ならご存知かと思います。

Faster R-CNNなどのTwo-Stage系
SSDYOLOv3などのSingle-Stage系

YOLO系についてはv3 (version 3) とあるように継続的に改善されているので,精度や処理速度については単純に比較はできませんが,物体検出系アルゴリズムの成長期に言われていたこととしては,

精度:Faster R-CNN > SSD > YOLO
処理速度:YOLO > SSD > Faster R-CNN

というように精度と処理速度は基本的にトレードオフの関係にあります。

なお,現在はこれらのアルゴリズム以外にも多くの手法が開発されていますので,もし興味がある方はググってみると面白いと思います。

今回使ったアルゴリズム

この中で今回どのアルゴリズムを使うかというと,タイトルの通りSSD (Single Shot MultiBox Detector) を使用することにします。

実務で使用する場合は,要件に応じて精度を優先するか処理速度を優先するかなどアルゴリズムを選定する基準は色々ありますが,今回は特定の目的にフォーカスを当てずに実装しようと思いますので汎用的(=器用貧乏)に使えそうなSSDにしました。

これは個人的な趣味でもありますが,Two-Stage系は何となくスマートじゃないというか,無駄に複雑になってしまっている気がするので,そういう個人的な興味という観点でもSingle-Stage系のアルゴリズムから選定しました。

なお,以後この記事では特に断りが無い限り,図は上記リンク先の論文から引用しています。

SSDのざっくりした説明

さーっと論文を読んだだけでもしかしたら間違いがあるかもしれませんので,もししっかりと理解したいという方は論文を読んで頂ければと思います。

まず,SSDのネットワーク構造はこんな感じになっています。

VGG16などのBase Networkにまず画像を通して,その後に追加した畳み込み層でスケールを変えていった特徴マップを作っていく構造になっています。

検出の仕組みについては,下図のように各特徴マップ上で,ピクセル単位でPriorやPrior Boxと呼ばれるBoxを事前に設定しておきます。

そして,それぞれのPrior Boxに対して物体位置のオフセットとクラス分類を行うことで物体を検出します。

各特徴マップのスケールが異なるため,出力層に近い特徴マップほど粗い(=縦横のピクセル数が少ない)マップになっており,相対的に大きな物体を捉える仕組みになっています。

検出してみた結果

実際にやってみるテーマをどうするか結構悩んだのですが,著作権云々とかの問題を極力避けるために,推論対象の画像は実際に自分が撮影した画像にしようということで,車や自転車など自動運転に関連するような物体検出タスクを想定してみることにしました。

一番重要なソースやその説明が記事的には本当は必要だと思いますが,SSDの実装は探せばいくらでも出てくるのでここでは割愛することにします。

※今回は趣味でやったこととはいえ,今後業務で使用する可能性もあるということで,あまり公開できないという背景もあります。

という訳でさっそく検出してみた結果になります。

今回は「とりあえず実装して動かしてみる」ということを目的としていたので,チューニングらしいチューニングは一切していませんし,各種ハイパーパラメータもバッチサイズ以外はデフォルトのパラメータを使用しました。

という感じで,パッとやってみるだけで上の画像のようにボチボチ検出できている感じの結果は得られました。たまたま撮影したときに通った自転車(黄枠)やVan(緑枠)もちゃんと検出できていますね。トラックなのかVanなのかは結構微妙な気はしますが,まぁ精度を求めることが目的ではないので,車(赤枠)と区別できているので良しとしましょう。

左奥に並んでいる中古車群がイマイチ車の境目がうまく取れていませんが,これは学習データの都合上仕方ない部分かなと思います。

まとめ

という訳で今回はSSDでの物体検出を勉強ついでに動かしてみました。

何となーく検出できている感が得られればいいかくらいのレベルで考えていたのですが,思ったよりもまともな結果が出てくれました。

このデータ以外にも仕事に関連してちょっと別の目的でもSSDを使用してみたのですが,そちらでも検出できている感じは出ていたので,とりあえずちゃんと動作しているんだろうなとは思います。

論文を見てみると分かりますが,SSDは物体検出のアルゴリズムの中ではもうかなり古い手法なので,今後はもう少し新しくて精度のいいアルゴリズムを実装してみようかなと思います。

スポンサーリンク