Claude 4.5 APIにおける画像入力のトークン数計算と最適化ガイド

Claude 4.5 APIにおける画像入力のトークン数計算と最適化ガイド
Photo by pine watt / Unsplash

こんにちは!

今回は、Claude 4.5 sonnet/haiku、Claude 4.1 OpusをAPIからつかうときの画像のトークン数計算方法について詳しく解説します。

画像トークン数の計算方法

Claude 4.5 APIに送信する画像は、テキストと同様にトークンとしてカウントされ、料金計算の基礎となります。画像がAPIのサイズ制限内でリサイズ不要な場合、以下の簡単な計算式でトークン数を推定できます。

基本計算式
トークン数 = (横幅px × 縦幅px) ÷ 750

この計算式を使用することで、アップロード前にコストを予測し、必要に応じて画像を最適化することが可能になります。例えば、1000×1000ピクセルの画像は約1334トークンを消費し、Claude 4.5の料金体系では、画像1枚あたりのコストを事前に計算できます。1092×1092ピクセル(1.19メガピクセル)の画像であれば約1590トークンとなり、これを基準にバッチ処理のコストも見積もることが可能です。

画像サイズの制限と最適化

Claude 4.5 APIには画像サイズに関するいくつかの重要な制限があります。単一のAPIリクエストでは最大100枚の画像を送信可能ですが、画像のサイズには以下の制約が適用されます。基本的には8000×8000ピクセルを超える画像は拒否され、20枚を超える画像を同時に送信する場合は、この制限が2000×2000ピクセルに縮小されます。また、リクエスト全体のサイズは32MBを超えることはできません。

パフォーマンスの観点から、画像の長辺が1568ピクセルを超える場合、または約1600トークンを超える場合、APIは自動的にアスペクト比を保持しながら画像をスケールダウンします。この自動リサイズ処理は追加の処理時間を要するため、事前に適切なサイズに調整することで、レスポンスタイムを大幅に改善できます。

コード実装例

1. Base64エンコード形式での画像送信

最も基本的な実装方法は、画像をBase64形式にエンコードしてAPIに送信する方法です。この方法はローカルファイルやメモリ上の画像データを直接送信する際に有効です。

import base64
import anthropic
from pathlib import Path

client = anthropic.Anthropic(api_key="your-api-key")

# 画像をBase64にエンコード
def encode_image(image_path):
    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode('utf-8')

# トークン数の事前計算
def estimate_tokens(image_path):
    from PIL import Image
    img = Image.open(image_path)
    width, height = img.size
    tokens = (width * height) / 750
    return int(tokens)

image_path = "sample.jpg"
image_data = encode_image(image_path)
estimated_tokens = estimate_tokens(image_path)

print(f"推定トークン数: {estimated_tokens}")

# Claude 4.5 APIへのリクエスト
message = client.messages.create(
    model="claude-3-opus-20240229",  # Claude 4.5モデル指定
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": "image/jpeg",
                        "data": image_data
                    }
                },
                {
                    "type": "text",
                    "text": "この画像を詳しく分析してください"
                }
            ]
        }
    ]
)

print(message.content)

2. URL参照による画像送信

オンラインでホストされている画像を処理する場合、URLを直接指定することで、エンコーディングのオーバーヘッドを回避できます。この方法は大量の画像を処理する際や、外部サービスと連携する場合に特に効率的です。

const Anthropic = require('@anthropic-ai/sdk');

const anthropic = new Anthropic({
    apiKey: process.env.ANTHROPIC_API_KEY,
});

// 画像URLからトークン数を推定(事前にサイズ情報が必要)
async function estimateTokensFromURL(imageUrl) {
    // 実際の実装では画像のメタデータを取得
    const assumedWidth = 1200;
    const assumedHeight = 800;
    return Math.floor((assumedWidth * assumedHeight) / 750);
}

async function analyzeImageFromURL() {
    const imageUrl = "https://example.com/image.jpg";
    const estimatedTokens = await estimateTokensFromURL(imageUrl);
    
    console.log(`推定トークン数: ${estimatedTokens}`);
    
    const message = await anthropic.messages.create({
        model: 'claude-3-opus-20240229',  // Claude 4.5モデル
        max_tokens: 1024,
        messages: [{
            role: 'user',
            content: [
                {
                    type: 'image',
                    source: {
                        type: 'url',
                        url: imageUrl
                    }
                },
                {
                    type: 'text',
                    text: '画像内のオブジェクトを識別し、その配置を説明してください'
                }
            ]
        }]
    });
    
    console.log(message.content);
}

analyzeImageFromURL();

3. 複数画像の効率的な処理とトークン最適化

複数の画像を同時に処理する場合、トークン数の合計を管理し、必要に応じて画像をリサイズすることで、コストとパフォーマンスを最適化できます。

import anthropic
from PIL import Image
import io
import base64

class ImageTokenOptimizer:
    def __init__(self, api_key):
        self.client = anthropic.Anthropic(api_key=api_key)
        self.max_dimension = 1568  # 推奨される最大サイズ
        self.target_megapixels = 1.15  # 最適なメガピクセル数
    
    def optimize_image(self, image_path):
        """画像を最適なサイズにリサイズしてトークン数を削減"""
        img = Image.open(image_path)
        width, height = img.size
        
        # 現在のトークン数を計算
        current_tokens = (width * height) / 750
        
        # リサイズが必要かチェック
        if max(width, height) > self.max_dimension:
            # アスペクト比を保持してリサイズ
            ratio = self.max_dimension / max(width, height)
            new_width = int(width * ratio)
            new_height = int(height * ratio)
            
            img = img.resize((new_width, new_height), Image.LANCZOS)
            optimized_tokens = (new_width * new_height) / 750
            
            print(f"画像リサイズ: {width}x{height} → {new_width}x{new_height}")
            print(f"トークン削減: {int(current_tokens)} → {int(optimized_tokens)}")
        else:
            optimized_tokens = current_tokens
            print(f"リサイズ不要: トークン数 {int(optimized_tokens)}")
        
        # Base64エンコード
        buffer = io.BytesIO()
        img.save(buffer, format='JPEG', quality=95)
        img_str = base64.b64encode(buffer.getvalue()).decode()
        
        return img_str, int(optimized_tokens)
    
    def batch_process_images(self, image_paths, prompt):
        """複数画像をバッチ処理"""
        total_tokens = 0
        image_contents = []
        
        for path in image_paths:
            img_data, tokens = self.optimize_image(path)
            total_tokens += tokens
            
            image_contents.append({
                "type": "image",
                "source": {
                    "type": "base64",
                    "media_type": "image/jpeg",
                    "data": img_data
                }
            })
        
        print(f"\n合計推定トークン数: {total_tokens}")
        
        # テキストプロンプトを追加
        image_contents.append({
            "type": "text",
            "text": prompt
        })
        
        # Claude 4.5 APIにリクエスト
        message = self.client.messages.create(
            model="claude-3-opus-20240229",
            max_tokens=2048,
            messages=[{
                "role": "user",
                "content": image_contents
            }]
        )
        
        return message.content, total_tokens

# 使用例
optimizer = ImageTokenOptimizer(api_key="your-api-key")

image_files = ["image1.jpg", "image2.jpg", "image3.jpg"]
prompt = "これらの画像の共通点と相違点を分析してください"

result, total_tokens = optimizer.batch_process_images(image_files, prompt)
print(f"\n分析結果: {result}")
print(f"使用トークン数: {total_tokens}")

アスペクト比別の推奨サイズ

異なるアスペクト比の画像を処理する際は、以下の推奨サイズを参考にすることで、最適なトークン消費を実現できます。正方形(1:1)の画像では1092×1092ピクセル、縦長の画像(9:16)では819×1456ピクセル、横長の画像(16:9)では1456×819ピクセルが推奨されます。これらのサイズは、1.15メガピクセルの制限内で最大の画質を保ちながら、処理効率を最適化するように設計されています。

ベストプラクティス

Claude 4.5 APIで画像処理を行う際は、まず画像品質の確保が重要です。ぼやけた画像やピクセル化された画像は認識精度を低下させるため、鮮明な画像を使用することが推奨されます。画像内にテキストが含まれる場合は、そのテキストが読みやすいサイズであることを確認する必要があります。

コスト最適化の観点では、処理前に画像サイズを確認し、必要に応じてリサイズすることが重要です。バッチ処理を行う場合は、合計トークン数を事前に計算し、予算内で処理が完了することを確認することをお勧めします。また、頻繁に使用する画像については、Files APIを使用して一度アップロードし、複数回参照することで、エンコーディングのオーバーヘッドを削減できます。

パフォーマンスチューニングにおいては、画像を1568ピクセル以下に事前リサイズすることで、API側での自動リサイズを回避し、応答時間を短縮できます。複数の画像を処理する場合は、並列処理ではなく適切なバッチ処理を行うことで、APIレート制限を遵守しながら効率的に処理を進めることができます。

推奨される画像サイズ

最適なパフォーマンスを実現するため、Claude 4.5では画像を1.15メガピクセル以下(両辺とも1568ピクセル以内)にリサイズすることを推奨しています。

アスペクト比に応じた推奨サイズは、1:1の正方形画像であれば1092×1092ピクセル、3:4の縦長画像なら951×1268ピクセル、16:9のワイド画像の場合は819×1456ピクセルが最適です。

実装例1: Base64エンコードによる画像送信

最も基本的な画像送信方法はBase64エンコーディングを使用する方法です。この方法は画像データを直接リクエストに含めるため、外部ホスティングが不要で、セキュアな環境での利用に適しています。

import anthropic
import base64
from PIL import Image
import io

# 画像のリサイズとトークン計算
def prepare_image(image_path, max_dimension=1568):
    with Image.open(image_path) as img:
        # 画像サイズの取得
        width, height = img.size
        
        # トークン数の計算
        estimated_tokens = (width * height) / 750
        print(f"元の画像サイズ: {width}x{height}px")
        print(f"推定トークン数: {estimated_tokens:.0f}")
        
        # 必要に応じてリサイズ
        if max(width, height) > max_dimension:
            ratio = max_dimension / max(width, height)
            new_width = int(width * ratio)
            new_height = int(height * ratio)
            img = img.resize((new_width, new_height), Image.LANCZOS)
            
            # リサイズ後のトークン数を再計算
            new_tokens = (new_width * new_height) / 750
            print(f"リサイズ後: {new_width}x{new_height}px")
            print(f"新しいトークン数: {new_tokens:.0f}")
        
        # Base64エンコード
        buffered = io.BytesIO()
        img.save(buffered, format="PNG")
        return base64.b64encode(buffered.getvalue()).decode()

# Claude 4.5 APIへの送信
client = anthropic.Anthropic(api_key="your-api-key")

image_base64 = prepare_image("sample.jpg")

response = client.messages.create(
    model="claude-3-5-sonnet-20241022",  # Claude 4.5相当のモデル
    max_tokens=1000,
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": "image/png",
                        "data": image_base64
                    }
                },
                {
                    "type": "text",
                    "text": "この画像に含まれる要素を詳しく分析してください"
                }
            ]
        }
    ]
)

実装例2: URL参照による画像送信

公開されている画像URLを使用する方法は、大量の画像を処理する際に帯域幅を節約できる効率的な手法です。画像データがリクエストボディに含まれないため、リクエストサイズの制限を回避しやすくなります。

const Anthropic = require('@anthropic-ai/sdk');

// トークン数を事前計算する関数
async function calculateImageTokens(imageUrl) {
    // 画像のメタデータを取得(実装例)
    const response = await fetch(imageUrl, { method: 'HEAD' });
    const contentLength = response.headers.get('content-length');
    
    // 簡易的なサイズ推定(実際は画像を解析して正確なピクセル数を取得すべき)
    const estimatedPixels = contentLength * 0.3; // 概算値
    const estimatedTokens = estimatedPixels / 750;
    
    console.log(`画像URL: ${imageUrl}`);
    console.log(`推定トークン数: ${Math.round(estimatedTokens)}`);
    
    return estimatedTokens;
}

// Claude 4.5 APIへの複数画像送信
async function analyzeMultipleImages() {
    const anthropic = new Anthropic({
        apiKey: process.env.ANTHROPIC_API_KEY,
    });
    
    const imageUrls = [
        'https://example.com/image1.jpg',
        'https://example.com/image2.jpg'
    ];
    
    // 総トークン数の計算
    let totalTokens = 0;
    for (const url of imageUrls) {
        totalTokens += await calculateImageTokens(url);
    }
    console.log(`総推定トークン数: ${Math.round(totalTokens)}`);
    
    // APIリクエストの構築
    const message = await anthropic.messages.create({
        model: 'claude-3-5-sonnet-20241022',
        max_tokens: 1500,
        messages: [{
            role: 'user',
            content: [
                {
                    type: 'text',
                    text: 'これらの画像を比較分析してください'
                },
                ...imageUrls.map(url => ({
                    type: 'image',
                    source: {
                        type: 'url',
                        url: url
                    }
                }))
            ]
        }]
    });
    
    return message;
}

実装例3: バッチ処理での最適化

大量の画像を処理する場合、バッチ処理と適切なサイズ調整を組み合わせることで、コストとパフォーマンスの両方を最適化できます。

import asyncio
import aiohttp
from typing import List, Dict
import numpy as np
from PIL import Image
import anthropic

class ImageTokenOptimizer:
    def __init__(self, api_key: str):
        self.client = anthropic.Anthropic(api_key=api_key)
        self.token_budget = 10000  # トークン予算の設定
        
    def calculate_optimal_size(self, original_width: int, original_height: int, 
                              target_tokens: int = 1500) -> tuple:
        """目標トークン数に基づいて最適な画像サイズを計算"""
        current_tokens = (original_width * original_height) / 750
        
        if current_tokens <= target_tokens:
            return original_width, original_height
        
        # スケーリング係数の計算
        scale_factor = np.sqrt(target_tokens * 750 / (original_width * original_height))
        
        new_width = int(original_width * scale_factor)
        new_height = int(original_height * scale_factor)
        
        # 最大サイズ制限の確認
        max_dim = 1568
        if max(new_width, new_height) > max_dim:
            ratio = max_dim / max(new_width, new_height)
            new_width = int(new_width * ratio)
            new_height = int(new_height * ratio)
        
        return new_width, new_height
    
    async def process_image_batch(self, image_paths: List[str]) -> Dict:
        """画像のバッチを処理し、トークン使用量を最適化"""
        processed_images = []
        total_tokens = 0
        
        for path in image_paths:
            with Image.open(path) as img:
                width, height = img.size
                
                # 最適サイズの計算
                optimal_width, optimal_height = self.calculate_optimal_size(
                    width, height, 
                    target_tokens=self.token_budget // len(image_paths)
                )
                
                # リサイズ処理
                if (optimal_width, optimal_height) != (width, height):
                    img = img.resize((optimal_width, optimal_height), Image.LANCZOS)
                
                # トークン数の記録
                image_tokens = (optimal_width * optimal_height) / 750
                total_tokens += image_tokens
                
                processed_images.append({
                    'path': path,
                    'original_size': (width, height),
                    'optimized_size': (optimal_width, optimal_height),
                    'tokens': image_tokens,
                    'image': img
                })
        
        print(f"バッチ処理完了:")
        print(f"  処理画像数: {len(processed_images)}")
        print(f"  総トークン数: {total_tokens:.0f}")
        print(f"  平均トークン/画像: {total_tokens/len(processed_images):.0f}")
        
        return {
            'images': processed_images,
            'total_tokens': total_tokens,
            'within_budget': total_tokens <= self.token_budget
        }
    
    async def send_optimized_batch(self, batch_data: Dict) -> str:
        """最適化された画像バッチをClaude 4.5に送信"""
        # ここで実際のAPI送信処理を実装
        # batch_data['images']の各画像をBase64エンコードして送信
        pass

# 使用例
async def main():
    optimizer = ImageTokenOptimizer(api_key="your-api-key")
    
    image_paths = [
        "image1.jpg", 
        "image2.jpg", 
        "image3.jpg"
    ]
    
    # バッチ処理と最適化
    batch_result = await optimizer.process_image_batch(image_paths)
    
    # 最適化された画像をAPIに送信
    if batch_result['within_budget']:
        response = await optimizer.send_optimized_batch(batch_result)
        print("バッチ送信成功")
    else:
        print("トークン予算を超過しています。画像を分割して処理してください")

# 実行
asyncio.run(main())

それでは次回またお会いしましょう!

関連記事

・Open AI GPTシリーズの画像トークン消費量計算

【OpenAI API】Vision対応LLMの画像トークン消費量計算法 2025年最新版
こんにちは! OpenAIのVision対応(つまり画像も入力できるLLM)モデルは、画像をトークンに変換する際に2つの異なる計算方式を採用しています。 最新のGPT-5系列やGPT-4.1系列では、従来のタイル方式とは異なるパッチベース方式が導入されました。この変更により、画像処理の効率性が大幅に向上し、より細かな制御が可能になっています。 2つの計算方式の違い OpenAIは現在、パッチベース方式とタイルベース方式という2つの計算方法を並行して運用しています。 パッチベース方式は、GPT-4.1-mini、GPT-4.1-nano、GPT-5-mini、GPT-5-nano、o4-miniといった新世代モデルで採用されています。この方式では画像を32×32ピクセルという非常に小さなパッチに分割します。従来のタイル方式が512×512ピクセルだったことを考えると、約256分の1のサイズで処理することになり、より精密な画像理解が可能になりました。 一方、GPT-4o、GPT-4.1、GPT-5、o1、o3などの主力モデルは引き続きタイルベース方式を採用しています。こちらは

・Google Geminiシリーズの画像トークン消費量計算

Gemini 2.5 Pro/Flashにおけるマルチモーダルトークン(画像のトークン数、動画のトークン数など)計算ガイド
こんにちは! 本日は、Gemini 2.5 ProおよびGemini 2.5 Flashを使用する際、料金計算やコンテキストウィンドウの管理において、トークン数の正確な把握は非常に重要です。本記事では、画像、動画、音声といったマルチモーダルコンテンツのトークン計算方法について詳しく解説します。 基本概念:トークンとは Gemini 2.5シリーズにおいて、1トークンは約4文字に相当し、100トークンは約60-80語(英語)に相当します。すべての入力と出力はトークン単位で処理され、課金もトークン数に基づいて行われます。 Gemini 2.5シリーズのモデルと料金 利用可能なモデル * Gemini 2.5 Pro: 高度な推論能力を持つフラグシップモデル * Gemini 2.5 Flash: コスト効率に優れた高速モデル * Gemini 2.5 Flash Image: 画像生成専用モデル コンテキストウィンドウ 両モデルとも1,000,000トークンの大規模なコンテキストウィンドウを提供します。

Read more

Google GenAI SDK のストリーミングでマルチターン画像編集🍌が不安定になる問題と対処法

Google GenAI SDK のストリーミングでマルチターン画像編集🍌が不安定になる問題と対処法

こんにちは! Gemini 3 Pro Image (Nano banana Pro)を使ったマルチターン画像編集機能を実装していたところ、動いたり動かなかったりするという厄介な問題に遭遇しました。 本記事では、この問題の現象、原因調査の過程、そして解決策を共有します。 問題の現象 実行環境 Google GenAI SDKライブラリ(pip): google-genai 1.56.0 期待する動作 1. ユーザー: 「かわいい子猫の画像を生成して」 2. Gemini: 子猫の画像を生成 3. ユーザー: 「この子にメガネをかけて」 4. Gemini: 同じ子猫にメガネをかけた画像を生成 実際に起きた現象 1. ユーザー: 「かわいい子猫の画像を生成して」 2. Gemini: 茶色の子猫の画像を生成 3. ユーザー: 「この子にメガネをかけて」 4. Gemini: メガネをかけた女の子の画像を生成

By Qualiteg プロダクト開発部
【出展報告】TOKYO DIGICONX 2026

【出展報告】TOKYO DIGICONX 2026

こんにちは! 先日、「TOKYO DIGICONX 2026」に出展してまいりましたのでレポートさせていただきます! TOKYO DIGICONX 2026 TOKYO DIGICONX 2026は、2026年1月8日(木)~10日(土)に東京ビッグサイト 南3・4ホールで開催された、XR・メタバース・AI・Web3をテーマにした総合展示会です。 正式名称は「第3回 TOKYO XR・メタバース&コンテンツビジネスワールド」で、東京都、XRコンソーシアム、Metaverse Japan、東京商工会議所で構成されるXR・メタバース等産業展実行委員会が主催しています。 180社以上のスタートアップや企業が出展し、ビジネスデイ(8日・9日)とパブリックデイ(10日)の3日間にわたり、XR・メタバース・AI分野の最前線を体感できるイベントとなりました。 冬の東京ビッグサイト 新年明けて間もない1月の東京ビッグサイト。お正月気分もそこそこに、気合を入れて会場入りしました�

By Qualiteg ビジネス開発本部 | マーケティング部
コーディングエージェントの現状と未来への展望 【第2回】主要ツール比較と構造的課題

コーディングエージェントの現状と未来への展望 【第2回】主要ツール比較と構造的課題

こんにちは! 今回は、コーディングエージェントシリーズ第2回です! 前回の第1回では、2025年12月時点で百花繚乱状態にあるAIコーディングエージェントの全体像を俯瞰しました。 AIコーディングエージェント20選!現状と未来への展望 【第1回】全体像と基礎こんにちは! 今回は、20種類以上あるまさに百花繚乱なAIコーディングツールを一挙に紹介&解説していきたいとおもいます! AIをつかったコーディングはもはや常識となり、日々目まぐるしく新しいツールが登場しています。当社でも自社開発のAIコーディングツールをふくめ複数のツールを活用してソフトウェア開発をすすめていますが、次々とナイスなツールがでてきて興奮しつつも、正直キャッチアップが追いつかない…!という状況です。 「結局どれを使えばいいの?」「Claude CodeとCursorって何が違うの?」「オープンソースでも使えるやつあるの?」——そんな疑問を持っている方も多いのではないでしょうか。 そこで本シリーズでは、2025年12月時点でのAIコーディングツールを徹底的に整理してみました。商用サービスからオープンソースまで、20

By Qualiteg コンサルティング
LLM学習の現実:GPU選びから学習コストまで徹底解説

LLM学習の現実:GPU選びから学習コストまで徹底解説

こんにちは! なぜOpenAIやAnthropicは世界最高水準のLLMを作れるのに、それに肩を並べる日本発のLLMは存在しないのでしょうか? 技術力の差でしょうか。それとも人材の問題でしょうか。 答えはもっとシンプルです。GPUの枚数とお金です。 今日はそんな 「LLMの学習」にフォーカスをあて、そのリアルについて徹底解説いたします! 1. はじめに 「LLMを自分で学習させてみたい」 そう思ったとき、最初にぶつかる壁がGPUの問題です。 どのGPUを何枚使えばいいのか。クラウドで借りるべきか、オンプレで買うべきか。そもそも個人や小規模チームでLLM学習は現実的なのか。 本記事では、こうした疑問に対して、具体的な数字と事例を交えながら答えていきます。 たとえばLLaMA 2の学習にはA100が2,048枚使われました。DeepSeek-V3は約8億円かかりました。では、あなたの手元のGPUでは何ができるのか。そこを明らかにしていきたいと思います。 対象読者は、LLM学習に興味があるエンジニアや研究者です。PyTorchでモデルを書いたことがある程度の知識を前提とし

By Qualiteg プロダクト開発部, Qualiteg 研究部