はじめに

今回はこちらを参考にさせていただき、Amazon Novaを使って物体検知をしていきたいと思います。

Amazon Novaにも多くのモデルが存在しますが、今回はNova ProとNova Premierで試していきたいと思います。

ここでは、簡単な実装手順と実際に比較して私の所感で説明していきたいと思います。

Amazon Novaとは

Amazon Novaは、Amazon Bedrock で利用できる最先端のインテリジェンスと業界をリードするコストパフォーマンスを実現する新世代の基盤モデルです。Amazon Bedrock とのシームレスな統合により、開発者は Amazon Nova 基盤モデルを使用して生成 AI アプリケーションを構築およびスケーリングできます。Amazon Nova で構築を開始するには、Amazon Bedrock を使用して API からモデルにアクセスする必要があります。

現時点で使用可能なモデルは以下になります

  • Nova Micro
    • テキストのみのモデルで、最低のレイテンシーのレスポンスを非常に低コストで実現
  • Nova Lite
    • 非常に低コストのマルチモーダルモデルで、画像、動画、テキスト入力を高速に処理してテキスト出力を生成
  • Nova Pro
    • 幅広いタスクに対応する精度、速度、コストの最適な組み合わせを備えた高性能なマルチモーダルモデル
  • Nova Premier
    • 複雑なタスクを実行したり、モデル蒸留の教師として機能させたりする上で、当社の最も有能なモデル
  • Nova Canvas
    • プロンプトで提供されるテキストまたは画像からプロフェッショナルグレードの画像を作成する最先端の画像生成モデル
  • Nova Reel
    • 入力テキストと画像から短い動画を生成することをサポートする動画生成モデル
  • Nova Sonic
    •  自然なインタラクションによる、 人間のようなリアルタイムの音声会話が可能なモデル
  • Nova Act
    • Webブラウザ内で自動的にアクションを実行するモデル
  • AWS re:Invent 2025で発表されたAmazon Nova2シリーズたち
    • ここでは紹介を割愛します

 

Amazon Novaを使用して画像から対象の物体を検知してみる

ここでは、早速Amazon Novaを使用して画像から対象の物体が検知できるか試していきたいと思います。

前提条件

  • 今回はpythonを使用します
  • AWS SDKであるboto3がインストールされていること
  • 画像処理ライブラリの Pillow をインストールされていること
  • 対象のAmazon Novaのモデルが有効化されていること

1. 画像を準備する

私は今回こちらの画像ファイルで検証していきます。

2. 以下のソースコードを実行する

こちらを参考にソースコードを作りました。

import boto3
import io
import json
import re
from PIL import Image, ImageDraw, ImageFont

# --- Amazon Bedrock Runtime クライアントの初期化 ---
modelId = "us.amazon.nova-premier-v1:0"  # 利用するモデルID
accept = "application/json"
contentType = "application/json"
bedrock_rt = boto3.client("bedrock-runtime", region_name="us-east-1")  # リージョンは適宜変更

# --- JSON出力を安全に読み込む関数 ---
def safe_json_load(json_string):
    try:
        json_string = re.sub(r"\s", "", json_string)
        json_string = re.sub(r"\(", "[", json_string)
        json_string = re.sub(r"\)", "]", json_string)
        json_string = re.sub(r"(\]\},\])", "]}", json_string)
        return json.loads(json_string)
    except Exception as e:
        print("JSON parse error:", e)
        return []

# --- フォント取得 ---
def get_font(height):
    try:
        return ImageFont.truetype("Arial", size=height // 20)
    except:
        return ImageFont.load_default()

# --- 検出関数 ---
def detection(image_path, category_list, image_short_size=360):
    image_pil = Image.open(image_path)
    width, height = image_pil.size
    ratio = image_short_size / min(width, height)
    width, height = round(ratio * width), round(ratio * height)
    image_pil = image_pil.resize((width, height), resample=Image.Resampling.LANCZOS)

    buffer = io.BytesIO()
    image_pil.save(buffer, format="webp", quality=90)
    image_data = buffer.getvalue()

    category_str = ",".join([f'"{category}"' for category in category_list])
    prompt = f"""
Detect and output only {category_str} objects in the image with their bounding boxes.
Please identify and locate only {category_str} objects with high confidence.
Output in a list of bounding box format.
Output example: [ {{"{category_list[0]}": [x1, y1, x2, y2]}}, ... ]
"""

    prefill = """[ {" """

    messages = [
        {
            "role": "user",
            "content": [
                {
                    "image": {
                        "format": "webp",
                        "source": {"bytes": image_data},
                    }
                },
                {"text": prompt},
            ],
        },
        {
            "role": "assistant",
            "content": [{"text": prefill}],
        },
    ]

    response = bedrock_rt.converse(
        modelId=modelId,
        messages=messages,
        inferenceConfig={
            "temperature": 0.0,
            "maxTokens": 1024,
        },
    )

    output = prefill + response.get("output")["message"]["content"][0]["text"]
    result = safe_json_load(output)

    draw = ImageDraw.Draw(image_pil)
    font = get_font(height)

    for idx, item in enumerate(result):
        label = next(iter(item))
        x1, y1, x2, y2 = item[label]
        x1, x2 = x1 / 1000 * width, x2 / 1000 * width
        y1, y2 = y1 / 1000 * height, y2 / 1000 * height
        bbox = (x1, y1, x2, y2)
        draw.rectangle(bbox, outline="red", width=3)
        draw.text((x1 + 5, y1 + 5), label, fill="red", font=font)

    image_pil.show()
    image_pil.save("output_person_detected.png")
    print("検出完了: output_person_detected.png に保存しました。")

# --- 実行例 ---
detection("33457258_s.jpg", category_list=["car"])

modelIdには、今回使用するAmazon NovaのモデルIDを入力します。

最後の行に対象の画像ファイルのパスを指定し、どの物体を検知するか指定します。

promptを定義して指示を与えています。(各自適切なプロンプトに変更してください)

3. 実行結果

各モデルで実行した結果を以下に載せます。今回は対象検知を[person]と[car]でそれぞれ定義してどのような結果になるか比較してみました。

・Nova Pro

物体[person]は3人分検知していて良い結果となりました。

物体[car]は存在しないはずなのに誤検知されてしまっています、、、

・Nova Premier

どちらも期待値通りの結果となりました!!

↓ ↓参考にさせていただいたブログから一部を抜粋したものになりますが、今回の検証を通して本当にその通りだなと感じました!!

この手法の何がすごいかというと、プロンプトを変更するだけで、検出したい対象を柔軟に変えられる点です。従来の物体検出のように、特定の対象物を見つけるためにモデルの再学習をしたり、ファインチューニングをしたり・・・といった追加の作業やコストが不要になります。
「白いワンちゃん」を見つけたい時はプロンプトに “white dog” と記述し、「おもちゃのにんじん」を見つけたい時は “Toy carrot” と記述するだけです。さらには、「座っている白いワンちゃん」など、より具体的で状況に依存した対象物の検出も、プロンプトの工夫次第で実現できる可能性があります。
この「基盤モデルによる物体検出」というアプローチは、従来の物体検出技術が持つ「定義済みのカテゴリに対する高速・高精度な検出」という強みとは異なる、「プロンプトに基づく柔軟性と適応性の高さ」という新たな価値を提供します。これにより、今まで専門的な知識や追加の学習コストが必要だった多様な物体検出タスクをよりお手軽に利用することができるのです。

まとめ

Amazon Novaシリーズのモデルを使用して物体検知を検証することができました。

Nova Proでは、3人分の「person」を問題なく検知しましたが、実際に映っていない「car」が誤検知されてしまう結果となってしまいました。

一方でNova Premierでは、3人分の「person」を検知し、「car」は検知しない結果となり、素晴らしい結果となりました。

それぞれのモデルによって精度が異なる結果となりましたが、プロンプトやパラメータなどモデル側の設定等を微修正することで精度が向上する可能性はあると思います。

AWS re:Invent 2025でAmazon Nova2シリーズが発表されたので次回はNova2を使用して、検証していきたいと思います!

ぜひ皆さんも試してみてください。