🕵🏻‍♂️

たった1枚の画像で物体検出モデルを学習できるOne-Shot Object Detection

2021/12/22に公開

ワンショット物体検出とは

ワンショット物体検出とシングルショット物体検出

Turi Createに「One-Shot Object Detection」というタスクがある。

有名な物体検出モデルであるYOLOやSSDは「シングルショット」物体検出と呼ばれるが、Turi CreateではYOLOベースの「Object Detection」タスクも用意されており、明確に 「シングルショット」と「ワンショット」は別物 のようだ。

たった1枚の画像で学習可能

じゃあワンショットってなんだろう?と解説を読んでみると、

One-Shot object detection (OSOD) is the task of detecting an object from as little as one example per category. Unlike the Object Detector which requires many varied examples of objects in the real world, the One-Shot Object Detector requires a very small (sometimes even just one) canonical example of the object.

(DeepL翻訳)ワンショット物体検出(OSOD)とは、1カテゴリあたり1例でも少ない物体から検出するタスクである。実世界に存在する多くの多様な例を必要とする物体検出とは異なり、ワンショット物体検出では、非常に小さな(時にはたった1つの)正規の例を必要とします。

なんと、たった1枚の画像で検出対象を学習できてしまうというものらしい。

画像1

とはいえどんなものでもOKというわけではなく、道路標識やロゴ、トランプ等の 二次元の物体に適しているらしい。

The One-shot Object Detector is best suited for two-dimensional objects that have some regularity in the wild. Examples include road signs, logos, playing cards, and clapperboards. The One-Shot Object Detector is not suitable for three-dimensional objects like faces, animals, and cars -- such objects are better suited for the classical Object Detector.

(DeepL翻訳)ワンショット・オブジェクト検出器は、自然界に存在するある程度の規則性を持った二次元のオブジェクトに最適です。例えば、道路標識、ロゴ、トランプ、拍子木などです。顔や動物、車などの3次元のオブジェクトには適していませんので、そのようなオブジェクトは古典的なオブジェクト検出器に適しています。

二次元の物体に適しているのがなぜかというのは、後述の学習手順を自分でやってみるとよくわかる。モデルの学習で本当に1枚の画像しか用いていないわけではなく、1枚の画像をいろいろな背景画像に合成 し、学習データを大量に生成する方式のようだ。さまざまな角度から見た場合の情報が必要ない二次元のオブジェクトが検出対象だからこそ成立する。

この制約があっても活きるユースケースは大いにあると思う。過去にロゴひとつを認識させるのに苦労した経験のある自分にとっては超画期的だ。

本記事では、Turi Createでこの One-Shot Object Detectionタスクで物体検出モデルを学習・テストし、Core MLモデル [1] を作成するまでの手順 を紹介する。 [2]

学習

画像データの読み込み

学習用の画像(1枚)を読み込んでいる

import turicreate as tc

starter_images = tc.SFrame({'image':[tc.Image('stop_sign_starter.png')],
                  'label':['stop_sign']})

学習

なんと以下の1行だけ。

model = tc.one_shot_object_detector.create(starter_images, 'label')

実行すると次のようにログ出力された。

Downloading https://docs-assets.developer.apple.com/turicreate/data/one_shot_backgrounds.sarray.tar
Download completed: /var/folders/1d/1nblw12s25bbn1n1d98fm8q00000gn/T/data_cache/one_shot_backgrounds.sarray.tar
Augmenting input images using 951 background images.
+------------------+--------------+------------------+
| Images Augmented | Elapsed Time | Percent Complete |
+------------------+--------------+------------------+
| 100              | 16.99s       | 10.5%            |
| 200              | 21.74s       | 21%              |
| 300              | 28.97s       | 31.5%            |
| 400              | 35.22s       | 42%              |
| 500              | 40.82s       | 52.5%            |
| 600              | 45.69s       | 63%              |
| 700              | 50.85s       | 73.5%            |
| 800              | 56.68s       | 84%              |
| 900              | 1m 3s        | 94.5%            |
+------------------+--------------+------------------+
Using 'image' as feature column
Using 'annotation' as annotations column
Downloading https://docs-assets.developer.apple.com/turicreate/models/darknet.params
Download completed: /var/folders/1d/1nblw12s25bbn1n1d98fm8q00000gn/T/model_cache/darknet.params
Downloading https://docs-assets.developer.apple.com/turicreate/models/darknet.mlmodel
Download completed: /var/folders/1d/1nblw12s25bbn1n1d98fm8q00000gn/T/model_cache/darknet.mlmodel
Using GPU to create model (AMD Radeon Pro 5500M)
Setting 'batch_size' to 32
Setting 'max_iterations' to 5000
+--------------+--------------+--------------+
| Iteration    | Loss         | Elapsed Time |
+--------------+--------------+--------------+
| 1            | 3.26101      | 3.14s        |
| 2            | 3.29851      | 3.47s        |
| 3            | 3.26779      | 3.80s        |
| 4            | 3.24934      | 4.13s        |
| 5            | 3.20112      | 4.52s        |
| 6            | 3.09855      | 4.87s        |
| 11           | 3.09168      | 6.55s        |
| 21           | 3.18174      | 9.90s        |
| 31           | 2.90547      | 14.35s       |

...

| 4991         | 0.243801     | 31m 49s      |
| 5000         | 0.2236       | 31m 54s      |
+--------------+--------------+--------------+

ログの最初の方に

Augmenting input images using 951 background images.

とあることから、このワンショット物体検出というのは1枚の画像をいろんな背景つきの画像にaugumentationして学習する方式っぽい。なるほど。

それと

Using GPU to create model (AMD Radeon Pro 5500M)

とあることから、ちゃんとGPUが使われていることが確認できる。

また、公式サンプルのコメントによると、この処理にはCPUで数時間、GPUで1時間ほどかかるとあったが、

This step will take a few hours on CPU and about an hour on GPU

上のログから分かる通り、MBP 16インチ(当時の最高スペック)では30分程度で完了した。

テスト

テスト用画像の読み込み

テスト用画像を読み込む。test_imagesというSFrameオブジェクトが生成される。

# Load test images
test_images = tc.SFrame({'image':[tc.Image('stop_sign_test1.jpg'), 
                                 tc.Image('stop_sign_test2.jpg')]})

予測を実行

  • 作成した物体検出モデルを使って予測を実行し、結果をtest_imagesの'predictions'カラムに格納
# Save predictions on the test set
test_images['predictions'] = model.predict(test_images)
  • bounding boxを描画して'annotated_predictions'カラムに格納
# Draw prediction bounding boxes on the test images
test_images['annotated_predictions'] = \
   tc.one_shot_object_detector.util.draw_bounding_boxes(test_images['image'],
       test_images['predictions'])
  • test_imagesを可視化
test_images.explore()

画像2

annotated_predictionsカラムを見ると、1枚の画像だけで学習させた道路標識がテストデータ内でしっかり検出できていることがわかる。

Core MLモデルとして保存

# Save the model for later use in TuriCreate
model.save('stop-sign.model')

# Export for use in Core ML
model.export_coreml('MyCustomOneShotDetector.mlmodel')

出力したモデルをXcodeでプレビュー

画像3

生成後のモデルだけ見ると、入出力仕様は従来の物体検出モデルと同じ。Descriptionが違うぐらい。

Turi Createの基礎

こちらの記事をご参照ください。

Turi Createのメモ 2021年版|shu223|note

脚注
  1. Core MLモデルなので、当然iOS, macOS, watchOSで利用可能。 ↩︎

  2. 本記事は2020年3月に書いたこちらの記事をベースに加筆修正したものです。内容が一部古い場合があります。 ↩︎

Discussion