Meta(旧 Facebook)が2022年1月に発表した新しい物体検出器であるDetic(Detecting Twenty-thousand Classes using Image-level Supervision)を試していきます。

今回は公式のチュートリアルに沿って実装方法を紹介します。

Google colabを使用して簡単に物体検出のモデルを実装することができますので、ぜひ最後までご覧ください。

今回の内容

Deticの概要

Deticの導入

・チュートリアルのテスト

Deticとは

Detic(Detecting Twenty-thousand Classes using Image-level Supervision)とはMeta(旧 Facebook)が発表した新しい物体検出器です。

画像分類データセットを使った物体検出器のトレーニングを可能とする事で、物体検出の検出分類数(vocabulary)を大幅に拡張しました。

これにより、物体検出時にアンカーボックスを用いる必要がなく、画像分類のデータセットで物体検出のトレーニングが可能となりました。

Deticの特徴

アノテーション済みのマスク画像データを提供し物体検出の学習に用いるデータセットは、画像中の検出対象物の座標を与える必要があります。

このため画像分類に比べると、物体検出のデータセット作成の方が手間がかかります。
Deticでは画像分類のデータセットで物体検出のトレーニングが可能となったため、大量のデータセット(ImageNet)から大量の物体を学習しています。

これにより、従来の手法よりも2万種類以上にも及ぶ多くの物体を検出することが可能となります。
またCLIPを使用して、任意のクラス名に対して物体検出も実現しています。

Deticの導入

早速Deticを使用していきましょう。

以下、Google colab環境で進めていきます。

まずはGPUを使用できるように設定をします。

「ランタイムのタイプを変更」→「ハードウェアアクセラレータ」をGPUに変更

今回紹介するコードは以下のボタンからコピーして使用していただくことも可能です。

Open In Colab

from google.colab import drive
drive.mount('/content/drive')
%cd ./drive/MyDrive
import torch
TORCH_VERSION = ".".join(torch.__version__.split(".")[:2])
CUDA_VERSION = torch.__version__.split("+")[-1]
print("torch: ", TORCH_VERSION, "; cuda: ", CUDA_VERSION)

detectron2をインストールします。

!pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/$CUDA_VERSION/torch$TORCH_VERSION/index.html

公式よりcloneしてきます。

!git clone https://github.com/facebookresearch/Detic.git --recurse-submodules
%cd Detic
!pip install -r requirements.txt

以上で導入が完了しました。

実際にテストしてみる

ここからは実際にサンプル画像を用いてテストをしてみます。

import detectron2
from detectron2.utils.logger import setup_logger
setup_logger()

import sys
import numpy as np
import os, json, cv2, random
from google.colab.patches import cv2_imshow

from detectron2 import model_zoo
from detectron2.engine import DefaultPredictor
from detectron2.config import get_cfg
from detectron2.utils.visualizer import Visualizer
from detectron2.data import MetadataCatalog, DatasetCatalog


sys.path.insert(0, 'third_party/CenterNet2/projects/CenterNet2/')
from centernet.config import add_centernet_config
from detic.config import add_detic_config
from detic.modeling.utils import reset_cls_test

学習済モデルをロードします。

cfg = get_cfg()
add_centernet_config(cfg)
add_detic_config(cfg)
cfg.merge_from_file("configs/Detic_LCOCOI21k_CLIP_SwinB_896b32_4x_ft4x_max-size.yaml")
cfg.MODEL.WEIGHTS = 'https://dl.fbaipublicfiles.com/detic/Detic_LCOCOI21k_CLIP_SwinB_896b32_4x_ft4x_max-size.pth'
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5  # set threshold for this model
cfg.MODEL.ROI_BOX_HEAD.ZEROSHOT_WEIGHT_PATH = 'rand'
cfg.MODEL.ROI_HEADS.ONE_CLASS_PER_PROPOSAL = True # For better visualization purpose. Set to False for all classes.
predictor = DefaultPredictor(cfg)

まずはvocabularyをロードし、検出できる対象を全て検出してみましょう。

BUILDIN_CLASSIFIER = {
    'lvis': 'datasets/metadata/lvis_v1_clip_a+cname.npy',
    'objects365': 'datasets/metadata/o365_clip_a+cnamefix.npy',
    'openimages': 'datasets/metadata/oid_clip_a+cname.npy',
    'coco': 'datasets/metadata/coco_clip_a+cname.npy',
}

BUILDIN_METADATA_PATH = {
    'lvis': 'lvis_v1_val',
    'objects365': 'objects365_v2_val',
    'openimages': 'oid_val_expanded',
    'coco': 'coco_2017_val',
}

vocabulary = 'lvis' # change to 'lvis', 'objects365', 'openimages', or 'coco'
metadata = MetadataCatalog.get(BUILDIN_METADATA_PATH[vocabulary])
classifier = BUILDIN_CLASSIFIER[vocabulary]
num_classes = len(metadata.thing_classes)
reset_cls_test(predictor.model, classifier, num_classes)

テストする画像を用意します。

ここではチュートリアルに従ってテスト画像を準備します。

!wget https://web.eecs.umich.edu/~fouhey/fun/desk/desk.jpg
im = cv2.imread("./desk.jpg")
cv2_imshow(im)

実際にテスト画像を見てみましょう。

desk.jpg

この画像に対してテストをしてみます。

outputs = predictor(im)
v = Visualizer(im[:, :, ::-1], metadata)
out = v.draw_instance_predictions(outputs["instances"].to("cpu"))
cv2_imshow(out.get_image()[:, :, ::-1])

結果が表示されました。画像の中にある多くの物体が検出できていますね。

検出対象を指定する

多くの物体を検出できることができる反面、検出対象を限定したいケースもあるかと思います。

ここでは、検出対象を指定してテストしてみます。

from detic.modeling.text.text_encoder import build_text_encoder
def get_clip_embeddings(vocabulary, prompt='a '):
    text_encoder = build_text_encoder(pretrain=True)
    text_encoder.eval()
    texts = [prompt + x for x in vocabulary]
    emb = text_encoder(texts).detach().permute(1, 0).contiguous().cpu()
    return emb

vocabulary = 'custom'
metadata = MetadataCatalog.get("__unused")
metadata.thing_classes = ['headphone', 'webcam', 'paper', 'coffee'] # Change here to try your own vocabularies!
classifier = get_clip_embeddings(metadata.thing_classes)
num_classes = len(metadata.thing_classes)
reset_cls_test(predictor.model, classifier, num_classes)
output_score_threshold = 0.3
for cascade_stages in range(len(predictor.model.roi_heads.box_predictor)):
    predictor.model.roi_heads.box_predictor[cascade_stages].test_score_thresh = output_score_threshold

検出対象を「’headphone’, ‘webcam’, ‘paper’, ‘coffee’」に指定しました。

先ほどと同様にテストをしてみましょう。

outputs = predictor(im)
v = Visualizer(im[:, :, ::-1], metadata)
out = v.draw_instance_predictions(outputs["instances"].to("cpu"))
cv2_imshow(out.get_image()[:, :, ::-1])

指定した対象物のみ検出することができました。

コマンドからオリジナル画像をテスト

オリジナル画像でテストをしてみます。

ここではコマンドからテストを実行する方法を紹介します。

まずは学習済モデルをダウンロードしましょう。

!mkdir models
!wget https://dl.fbaipublicfiles.com/detic/Detic_LCOCOI21k_CLIP_SwinB_896b32_4x_ft4x_max-size.pth -O models/Detic_LCOCOI21k_CLIP_SwinB_896b32_4x_ft4x_max-size.pth
!wget https://web.eecs.umich.edu/~fouhey/fun/desk/desk.jpg

あとは次の通り実行するだけです。

「–input test.jpg 」の引数部分を実際に使用する画像に書き換えてください。

!python demo.py --config-file configs/Detic_LCOCOI21k_CLIP_SwinB_896b32_4x_ft4x_max-size.yaml --input test.jpg --output out.jpg --vocabulary lvis --opts MODEL.WEIGHTS models/Detic_LCOCOI21k_CLIP_SwinB_896b32_4x_ft4x_max-size.pth

結果は「out.jpg」として出力されます。

大きな物体だけでなく、小さな物体に対しても精度良く検出できていることがわかります。

コマンドからオリジナル動画をテスト

最後にオリジナル画像でテストをしてみます。

「–video-input」という引数を取ることで、動画を指定することができます。

python demo.py --config-file configs/Detic_LCOCOI21k_CLIP_SwinB_896b32_4x_ft4x_max-size.yaml --video-input monkey.mp4 --output monkey_out.mp4 --vocabulary lvis --opts MODEL.WEIGHTS models/Detic_LCOCOI21k_CLIP_SwinB_896b32_4x_ft4x_max-size.pth

動画でもDeticを使うことができました。

まとめ

最後までご覧いただきありがとうございます。

今回はDeticの実装方法を紹介しました。
データセットの確保を容易にしつつ、精度良く物体検出が可能となりました。

別な記事でも紹介しておりますが、物体検出データセット作成のためのアノテーション作業はとても負荷が大きい作業です。

アノテーションが不要となり、画像分類のデータセットでできるようになると、さらに物体検出が身近なものになりそうですね。

なお、今回のベースとなっているDetectron2の扱い方は以下の記事で紹介しております。

検出結果のスコアや座標の出力方法について興味がある方はぜひご覧ください。

【物体検出とセグメンテーション】Detectron2を使って物体検出とセグメンテーションを実装する

FacebookAIが開発した、PyTorchベースの物体検出・セグメンテーションのためのプラットフォームであるDetectron2について操作方法をまとめます。 Detectron2の発展版であ…

コメントを残す