見出し画像

Intel iGPU で Florence-2 を動かしてみた (第2回 : text prompt で特定の物体検出編)

0. はじめに

会社で支給されるような普通のWindowsノートPCで、Florence-2を動かしてみたという話です。Florence-2とは、これ。

前回、環境構築とIntel最適化についてご紹介しましたが、その内容を前提に続きを書きますので、まだの方は先にそちらをご覧ください。



1. Florence-2でできること

1.1) 単一モデルで14タスクも!

技術の進歩は凄まじいもので、Florence-2は単一モデルで画像に対する14ものタスクをこなすことができます。
詳細は割愛しますが、中身がすごいのなんのって。
具体的なタスクと必要なpromptについては、このページをご覧ください。

1.2) 今回使うのは

今回は、物体検出をしてみましょう。
それも、text prompt を与え、そのphraseやwordに反応した物体のみを検出してみます。


2. サンプルコードの説明

頭から順を追って説明していきます。
これまでの記事同様、最初に言い訳しておきますが、Pythonを勉強し始めて2週目に書いたものなので、お約束的な書き方になっていない箇所もあろうかと思いますが、その辺りはご容赦を。

また、元ネタとしては、本家OpenVINOのサイトに書かれているドキュメントと、前述したGitHubのページなのですが、今回の環境に合わせてサンプルコードをちょこちょこ書き換えています。
OpenVINOの原典を読みたいという方は、こちらをご参照ください。


2.1) OpenVINO IRの保存場所とモデルの選択

前回の記事で書いた階層に、OpenVINO IR のモデルが既に存在しているという前提です。

from pathlib import Path

# model_name = "Florence-2-base"        # Pretrained model with FLD-5B
# model_name = "Florence-2-large"       # Pretrained model with FLD-5B
model_name = "Florence-2-base-ft"       # Finetuned model on a collection of downstream tasks
# model_name = "Florence-2-large-ft"    # Finetuned model on a collection of downstream tasks

model_id = "microsoft/" + model_name    # ov_florence2_helper.pyが想定している値なので変えない

model_path = Path("model")              # modelの保存場所
model_path = model_path / "Florence-2"  # Florence-2の各modelの保存場所
model_path = model_path / model_name    # 選択したmodelの保存場所

2.2) modelの読み込み

どうやら、ov_florence2_helper.pyがいろんなことしてくれるようで、こんな簡単な記述で終わります。裏では、Intel最適化のためのコンパイルもしています。

from ov_florence2_helper import OVFlorence2Model
model = OVFlorence2Model(model_path, device="AUTO")
print("Initialized.", flush=True)


from transformers import AutoProcessor
processor = AutoProcessor.from_pretrained(model_path, trust_remote_code=True)
print("Florence-2 model loaded.", flush=True)

device="AUTO"の解説は、SAM2の記事を参照してください。

2.3) task prompt の設定

ここで、14タスクのうち、どのタスクにするのかを指定します。
今回は、<CAPTION_TO_PHRASE_GROUNDING>を指定し、この後で text prompt の設定をします。
ちなみに、text prompt を与えない、お任せ物体検出は<OD>です。

# task_prompt = "<CAPTION>"                 # Caption
# task_prompt = "<DETAILED_CAPTION>"        # Detailed Caption
# task_prompt = "<MORE_DETAILED_CAPTION>"   # More Detailed Caption
# task_prompt = "<DENSE_REGION_CAPTION>"    # Dense Region Caption

# task_prompt = "<REGION_PROPOSAL>"         # Region Proposal (output: bbox, empty label)

# task_prompt = "<OD>"                                  # Object Detection
task_prompt = "<CAPTION_TO_PHRASE_GROUNDING>"           # Phrase Grounding (input: text)

# task_prompt = "<REFERRING_EXPRESSION_SEGMENTATION>"   # Referring Expression Segmentation (input: text, output: polygon)
# task_prompt = "<REGION_TO_SEGMENTATION>"              # Region to Segmentation (input: loc_x1, lox_y1, loc_x2, loc_y2)
# task_prompt = "<OPEN_VOCABULARY_DETECTION>"           # Open Vocabulary Detection (input: text)

# task_prompt = "<REGION_TO_CATEGORY>"      # Region to Texts (input: loc_x1, loc_y1, loc_x2, loc_y2)
# task_prompt = "<REGION_TO_DESCRIPTION>"   # Region to Texts (input: loc_x1, loc_y1, loc_x2, loc_y2) 

# task_prompt = "<OCR>"                     # OCR (output: text)
# task_prompt = "<OCR_WITH_REGION>"         # OCR with Region (output: text, label)

2.4) 対象画像の設定

ざっくり、以下のことをしています。

  1. 画像を読み込む

  2. RGB情報に変換する (RGB以外のチャネルを落とし、RGBの順に並び替え)

from PIL import Image

image = Image.open("images/test45.png")
image = image.convert("RGB")
print("Image file opened.", flush=True)

2.5) text prompt の設定

前述した通り、今回は text prompt を与えて特定の物体を検出したいので、text prompt を設定します。(wordでもphraseでもよし。)

# text_prompt = None      # text prompt を与えない場合
text_prompt = "sky"       # text prompt を与える場合
# text_prompt = "<loc_x1><loc_y1><loc_x2><loc_y2>"    # 座標を与える場合 x1, y1, x2, y2を数値に

コメント文の通り、text prompt のないタスクは、Noneを設定しておきます。
また、座標を与える場合は、矩形の左上と右下の座標を設定します。

2.6) 最終的なpromptの設定

ここで、各タスクに合ったpromptを設定します。

if text_prompt is None:
    prompt = task_prompt
else:
    prompt = task_prompt + text_prompt

2.7) 推論

これで材料が揃いましたので、これらを投入。

inputs = processor(text=prompt, images=image, return_tensors="pt")
print("Inference started.", flush=True)

generated_ids = model.generate(
    input_ids=inputs["input_ids"],
    pixel_values=inputs["pixel_values"],
    max_new_tokens=1024,
    do_sample=False,
    num_beams=3
)

generated_text = processor.batch_decode(generated_ids, skip_special_tokens=False)[0]

2.8) 推論結果の表示

推論結果は、すべてテキスト情報です。
その中から、該当タスクのdictを抽出して、表示します。

parsed_answer = processor.post_process_generation(
    generated_text,
    task=task_prompt,
    image_size=(image.width, image.height)
)

results = parsed_answer[task_prompt]    # 該当task_promptのdictを抽出
print(results, flush=True)

3. 次回は

実際にFlorence-2で物体検出を行ない、どんな結果になったのかをご紹介します。
お楽しみに。

いいなと思ったら応援しよう!