Claude Media
Claudeで画像をリサイズすると座標がずれる原因と対処法

Claudeで画像をリサイズすると座標がずれる原因と対処法

Claudeは長辺だけでなくビジュアルトークンの上限でも画像を自動縮小し、返す座標は縮小後の画像基準になります。A4スキャンの実例と、事前リサイズ・エラー化・座標逆算という3つの対処法をまとめます。

A4を130DPIでスキャンした1075×1520pxの画像は、長辺(1568px)の上限には収まっているのに、Claudeに送ると924×1307pxへ縮小されます。原因は長辺の制限とは別に、ビジュアルトークン数の上限も同時にチェックされているためです。Claudeが返す座標は、この縮小後の画像を基準にした値なので、元画像にそのまま重ねるとズレます。対処法は3つあります。アップロード前に自分でリサイズする、リサイズが起きたらエラーとして検知する、リサイズ後の寸法から座標を逆算する、のいずれかです。

長辺の上限だけでは説明がつかない理由

Claudeは画像を処理する前に、次の順で寸法を決めます。

手順

Claudeが画像の寸法を決める流れ

  1. 1

    2つの上限を同時に判定する

    長辺の上限(標準ティア1568px、高解像度ティア2576px)と、ビジュアルトークン数⌈幅 / 28⌉ × ⌈高さ / 28⌉の上限(標準ティア1568、高解像度ティア4784)です。どちらか一方でも超えると縮小の対象になります。

  2. 2

    アスペクト比を保って縮小する

    両方を満たす最大のサイズを探します。

  3. 3

    28の倍数に切り上げてパディングする

    縮小したかどうかに関わらず、右端と下端に余白を足します。

  4. 4

    縮小後の画像を基準に座標を返す

    Claudeが返すのは、パディング前の縮小後画像上のピクセル位置です。元画像の座標ではありません。

ほとんどの写真・スクリーンショットで効くのはビジュアルトークンの上限です。長辺の上限が効くのは、パノラマや縦長のスマホ画面のような極端に細長い画像だけです。1920×1080pxのスクリーンショットは標準ティアで1456×819pxになり、長辺1568pxに合わせた1568×882pxにはなりません。長辺だけで手計算すると、その差の分だけ座標が実際とズレます。

元の画像サイズ標準ティアの縮小後(トークン)高解像度ティアの縮小後(トークン)
1000×1000px標準ティアの縮小後(トークン)縮小なし(1296)高解像度ティアの縮小後(トークン)縮小なし(1296)
1092×1092px標準ティアの縮小後(トークン)縮小なし(1521)高解像度ティアの縮小後(トークン)縮小なし(1521)
1920×1080px標準ティアの縮小後(トークン)1456×819px(1560)高解像度ティアの縮小後(トークン)縮小なし(2691)
2000×1500px標準ティアの縮小後(トークン)1269×952px(1564)高解像度ティアの縮小後(トークン)縮小なし(3888)
3840×2160px標準ティアの縮小後(トークン)1456×819px(1560)高解像度ティアの縮小後(トークン)2576×1449px(4784)
1170×2532px(縦長のスマホ画面)標準ティアの縮小後(トークン)725×1568px(1456)高解像度ティアの縮小後(トークン)縮小なし(3822)

最後の行は公式の表にない例で、resized_size(後述)で求めると標準ティアは725×1568pxです。トークン数は上限の1568に届いておらず、縮小を決めたのは長辺の上限です。

2000×1500pxの標準ティアは、公式の表では1269×952px、参照実装では1270×952pxと幅が1px食い違います。どちらもトークン上限1568の範囲内です。座標の逆算には参照実装の値を使い、1pxの差は許容誤差に含める扱いが現実的です。

自分の画像サイズが上限に近いかどうかを確認せずに座標処理を実装すると、テスト画像ではズレず、本番の別サイズの画像だけズレるという再現しにくい不具合になります。

A4スキャンが縮小される具体例

130DPIでスキャンしたA4は1075×1520pxです。長辺1520pxは標準ティアの上限1568pxに収まるので、一見縮小されないように見えます。

数字

A4スキャン(標準ティア)の寸法の変化

  • 元画像

    1075×1520px

    長辺は上限未満

  • トークン数

    2,145

    39×55。上限は1,568

  • 縮小後

    924×1307px

    1,551トークンに収まる

  • パディング後

    924×1316px

    下端に9px足される

縮小後の寸法を基準に座標が返ります

この縮小は長辺の上限だけを見ていても気づけません。公式の解説でも、ビジュアルトークンの上限による縮小は座標がズレる最も多い原因として挙げられています。

座標がズレるかどうかは、送り先モデルのティアでも変わります。

くらべる

同じA4スキャンを送ったときのティア別の結果

1568px / 1568トークン

標準ティア

上の例のとおり924×1307pxへ縮小され、返る座標も縮小後の画像基準です。Claude 4.7以降ではないモデルが、このティアに当たります。

2576px / 4784トークン

高解像度ティア

2,145トークンは上限4,784以内なので縮小されず、座標は元の1075×1520pxにそのまま重なります。対象はClaude 4.7以降のモデルです。

高解像度ティアは座標が合わせやすい反面、同じ画像でビジュアルトークンが最大で約3倍に増えます。公式の試算では、1000×1000pxの画像1,000枚はClaude Haiku 4.5(入力$1/100万トークン)で約$1.30です。Claude Opus 5(入力$5/100万トークン)では同じ画像が約$6.48、4K画像が約$23.92になります。座標の精度が不要な画像まで高解像度で送ると、費用だけが増えます。

パディングは右端・下端だけに入る

Claudeは画像を28×28pxのパッチ単位で処理しているため、縮小後の寸法が28の倍数ちょうどになるとは限りません。924×1307pxの例では924×1316pxまでパディングされ、縮小されなかった画像も同じです。パディング部分にコンテンツは含まれず、Claudeが実際に認識するページ内容は縮小後の924×1307pxの範囲だけです。パディングは右端と下端だけに追加され、原点(0, 0)や左端・上端の位置は変わりません。正規化やリスケールの計算では、パディング後の寸法ではなく縮小後の寸法で割ることが重要です。パディング後の寸法で割ると、すべての座標がわずかにズレます。

A4の例で縦座標1200を元の1520pxへ戻すと、縮小後の1307pxで割れば約1395.6px、パディング後の1316pxで割ると約1386.0pxです。9.5px前後の差が出ます。縮小後の寸法で割る点は、対処法3のコードでも同じです。

対処法の選び方

切り分け

状況別の3つの対処法

  • 画像を自分で作れる

    対処法1の事前リサイズが最も確実です。手元の画像とClaudeの見る画像が一致し、座標変換が要りません。

  • 縮小が起きたら気づきたい

    対処法2のtransformationsで、静かなズレを400エラーに変えます。モデルのティアを切り替える運用向きです。

  • 上流の画像を変えられない

    対処法3で縮小後の寸法を再計算し、座標を逆算します。元画像の寸法と送ったモデルのティアが必要です。

対処法1: アップロード前に自分でリサイズする

次の関数が、Claudeが縮小する寸法を同じ手順で求めます。

import math
 
 
def count_image_tokens(width: int, height: int) -> int:
    """28x28ピクセルのパッチ1つ = 1ビジュアルトークン"""
    return math.ceil(width / 28) * math.ceil(height / 28)
 
 
def resized_size(
    width: int,
    height: int,
    max_edge: int = 1568,
    max_tokens: int = 1568,
) -> tuple[int, int]:
    """Claudeがパディング前にリサイズする寸法。
    高解像度ティアのモデルではmax_edge=2576, max_tokens=4784を渡す。
    """
 
    def fits(w: int, h: int) -> bool:
        return (
            math.ceil(w / 28) * 28 <= max_edge
            and math.ceil(h / 28) * 28 <= max_edge
            and count_image_tokens(w, h) <= max_tokens
        )
 
    if fits(width, height):
        return (width, height)
    if height > width:
        resized_h, resized_w = resized_size(height, width, max_edge, max_tokens)
        return (resized_w, resized_h)
 
    aspect_ratio = width / height
    lo, hi = 1, width
    while lo + 1 < hi:
        mid = (lo + hi) // 2
        if fits(mid, max(round(mid / aspect_ratio), 1)):
            lo = mid
        else:
            hi = mid
    return (lo, max(round(lo / aspect_ratio), 1))
 
 
# A4スキャンの例
print(resized_size(1075, 1520))  # (924, 1307)
 
# Pillowで実際にリサイズする場合
# image.resize(resized_size(*image.size))

手計算で見積もるとこの関数の結果とズレることがあるため、実装に組み込んで使います。端数の丸め方にも注意が要ります。短辺を計算するとちょうど.5になる端数が出ることがあり、APIは四捨五入ではなく偶数丸めで決めます。偶数丸めは、0.5を丸めた結果が偶数になる側へ寄せる方式です。

Pythonのround()は偶数丸めなので上のコードのままで合います。JavaScriptのMath.roundは半端な値を切り上げるため、公式のTypeScript版は偶数丸めの関数を別に用意しています。たとえば1280×1000pxの画像を標準ティアで計算すると、偶数丸めでは1232×962px、切り上げ方式では1232×963pxになります。1px差でも、座標を整数のまま突き合わせる処理では不一致の原因になります。

対処法2: リサイズが起きたらエラーにする

事前リサイズは、パイプラインが常に正しい寸法を出力している間だけ効果があります。新しい画像ソースやモデルのティア変更で、気づかないうちにサーバー側リサイズが復活することもあります。この静かなズレを見える化するには、画像コンテンツブロックにtransformationsフィールドを付けます。

{
  "type": "image",
  "source": { "type": "base64", "media_type": "image/png", "data": "..." },
  "transformations": { "oversized_image": "error" }
}

このフィールドを付けた画像がリサイズされるはずのリクエストは、400のinvalid_request_errorで拒否されます。標準ティアのモデルに1920×1080pxを送ると、メッセージは次のようになります。

messages.0.content.0: image dimensions 1920x1080 exceed the maximum image size of a model named on this request and would be downsized to 1456x819; scale the image to at most 1456x819 or set the image's oversized_image setting to "downsize"

メッセージに出る縮小先に合わせてリサイズし、再送します。判定は、リクエストが指名するすべてのモデルの上限に照らして行われ、縮小先は全モデルが受け付ける最大サイズです。同じ1920×1080pxでも、高解像度ティアのモデルだけを指名すれば通ります。デフォルト("downsize")は今までどおり自動縮小で、エラー化した画像がリサイズされたままモデルに届くことはありません。設定は画像ブロックごとなので、座標が重要なスクリーンショットにはエラー化を付け、ロゴのような縮小されても問題ない画像には付けない、という使い分けもできます。PDFのdocumentブロックはこのフィールドを受け付けません。ページはサーバー側でラスタライズされるためです。documentの内容の中に入れた画像ブロックは、通常の画像と同じく受け付けます。

transformationsが防ぐのは自動縮小だけです。画像の最長辺が8000pxを超える場合は、"oversized_image"の設定に関係なく別のバリデーションエラーで拒否されます。1リクエストに20枚を超える画像を入れると、画像ごとの寸法上限がさらに厳しくなり、超えた画像は「many-image requests」を含むエラーで拒否されます。全プラットフォームで通すには、各辺を2000px以下にするか、画像と文書のブロックを20個以内にします。tool_resultに入れた画像も数に含まれます。URLやfile_idで渡した画像は、バイト列を取得できた時点でチェックされるため、エラーメッセージにリクエスト内での位置(何番目の画像か)が付きません。埋め込みBase64画像だけが位置つきで報告されます。

推論そのものを実行する前に確認したいなら、Token countingエンドポイントでもtransformationsの設定が反映されます。Messages APIを実際に呼ばなくても、埋め込み画像がリサイズされずに収まるかどうかを事前に確認できます。ただしToken countingはURLやfile_idの画像を取得せずに拒否するため、それらの画像の縮小判定はMessages APIを呼んだ時点で初めて行われます。Token countingが成功しても、Messages APIのリクエスト上限内に収まるとは限りません。送信時に拒否されることもあります。

対処法3: 事前リサイズできないときは座標を逆算する

上流システムから受け取った画像で、自分で事前リサイズできない場合は、resized_size関数でClaudeが見たサイズを再計算し、返ってきた座標を相対座標に変換してから元画像へ戻します。

def to_relative_coordinates(
    x: float,
    y: float,
    original_width: int,
    original_height: int,
    max_edge: int = 1568,
    max_tokens: int = 1568,
) -> tuple[float, float]:
    """Claudeが返したピクセル座標を、元画像上の[0, 1]の相対座標に変換する"""
    resized_w, resized_h = resized_size(
        original_width, original_height, max_edge, max_tokens
    )
    return (x / resized_w, y / resized_h)
 
 
# 縮小後のA4ページ上で(462, 653.5)を返した場合、元の1075x1520画像上では
rel_x, rel_y = to_relative_coordinates(462, 653.5, 1075, 1520)
print((rel_x * 1075, rel_y * 1520))  # (537.5, 760.0)

ティアを取り違えると、間違った縮小後サイズを逆算してしまい、座標がまた別方向にズレます。モデルを切り替えるたびに、max_edgeとmax_tokensを更新します。

プロンプトでは、座標を絶対ピクセルで返すよう指定します。たとえば[x1, y1, x2, y2](左上と右下の角)をピクセルで求めます。0〜1000のような正規化座標を頼むと精度が落ちるため、正規化が必要なら受け取った後に自分のコードで行います。

座標を機械可読なJSONで受け取りたいときは、structured outputsで[x1, y1, x2, y2]の配列を持つオブジェクトのスキーマを定義できます。詳しくはClaudeで座標・バウンディングボックスを正確に取得する方法にあります。

小さな対象は縮小で精度が落ちます。対処は2つで、高解像度ティアのモデルを使うか、その領域を切り出して送り、返ってきた座標に切り出し位置のオフセットを足して元画像に戻します。

# cropは (left, top, right, bottom)。切り出した画像上の座標を元画像へ戻す
left, top, right, bottom = crop
x_orig = left + x_in_crop
y_orig = top + y_in_crop

PDFではこの方法が使えない

PDFはページがサーバー側でラスタライズされ、その寸法をあらかじめこちらで制御できません。元画像のピクセル寸法を前提とする逆算方式は、そもそも「元画像」という概念が存在しないPDFには適用できません。PDFの内容に対して座標を扱いたいなら、自分でページを画像へラスタライズしてからアップロードし、対処法1のアップロード前リサイズの手順に合わせます。PDF全般の扱い方はClaudeのPDF読み込み・画像解析の使い方にまとめています。

Computer Useツールのスクリーンショットも別枠です。browser useやズーム画像も同じ扱いで、自動リサイズの対象外です。上限を超えると拒否されるため、この記事の縮小ロジックではなく専用のスケーリング計算が必要になります。詳細はComputer Useの座標ズレを直すスケーリング計算式にまとめています。

リサイズを直しても座標は近似値のまま

ここまで見た対処法1〜3は、いずれも「Claudeがどの寸法の画像を見ているか」というリサイズ由来のズレを解消する方法です。これを直しても、座標そのものの精度が完璧になるわけではありません。Claudeの空間認識には限界があり、低品質な画像・回転した画像・極端に小さい画像では見積もりの誤差が別途乗ります。リサイズ計算を正しく合わせたうえで、重要な用途では、結果を大量に処理する前に目視で抜き取り確認します。

まとめ

座標のズレを疑うときは、画像サイズ・送ったモデルのティア・座標を割った寸法の3点を順に照らし合わせます。縮小を放置できない画像にはtransformationsを付けておくと、ズレが静かに紛れ込みません。座標をそもそもどう取得するかはClaudeで座標・バウンディングボックスを正確に取得する方法、画像処理全般の得意・苦手はClaude画像解析でできることで扱っています。

この記事を共有:XはてブLinkedIn