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

サブスクビジネス完全攻略 第1回~『アープがさぁ...』『チャーンがさぁ...』にもう困らない完全ガイド

サブスクビジネス完全攻略 第1回~『アープがさぁ...』『チャーンがさぁ...』にもう困らない完全ガイド

なぜサブスクリプションモデルが世界を変えているのか、でもAI台頭でSaaSは終わってしまうの? こんにちは! Qualitegコンサルティングです! 新規事業戦略コンサルタントとして日々クライアントと向き合う中で、ここ最近特に増えているのがSaaSビジネスに関する相談です。興味深いのは、その背景にある動機の多様性です。純粋に収益モデルを改善したい企業もあれば、 「SaaS化を通じて、うちもデジタルネイティブ企業として見られたい」 という願望を持つ伝統的な大企業も少なくありません。 SaaSという言葉が日本のビジネスシーンに本格的に浸透し始めたのは2010年代前半。それから約15年が経ち、今やSaaSは「先進的な企業の証」のように扱われています。 まず SaaSは「サーズ」と読みます。 (「サース」でも間違ではありません、どっちもアリです) ほかにも、 MRR、ARR、アープ、チャーンレート、NRR、Rule of 40…… こうした横文字が飛び交う経営会議に、戸惑いながらも「乗り遅れてはいけない」と焦る新規事業担当者の姿をよく目にします。 しかし一方で、2024

By Qualiteg コンサルティング
ASCII STARTUP TechDay 2025に出展します!

ASCII STARTUP TechDay 2025に出展します!

株式会社Qualitegは、2025年11月17日(月)に東京・浅草橋ヒューリックホール&カンファレンスで開催される「ASCII STARTUP TechDay 2025」に出展いたします。 イベント概要 「ASCII STARTUP TechDay 2025」は、日本のディープテックエコシステムを次のレベルへ押し上げ、新産業を創出するイノベーションカンファレンスです。ディープテック・スタートアップの成長を支えるエコシステムの構築、そして成長・発展を目的に、学術、産業、行政の垣根を越えて知を結集する場として開催されます。 開催情報 * 日時:2025年11月17日(月)13:00~18:00 * 会場:東京・浅草橋ヒューリックホール&カンファレンス * 住所:〒111-0053 東京都台東区浅草橋1-22-16ヒューリック浅草橋ビル * アクセス:JR総武線「浅草橋駅(西口)」より徒歩1分 出展内容 当社ブースでは、以下の3つの主要サービスをご紹介いたします。 1.

By Qualiteg ニュース
大企業のAIセキュリティを支える基盤技術 - 今こそ理解するActive Directory 第4回 プロキシサーバーと統合Windows認証

大企業のAIセキュリティを支える基盤技術 - 今こそ理解するActive Directory 第4回 プロキシサーバーと統合Windows認証

11月に入り、朝晩の冷え込みが本格的になってきましたね。オフィスでも暖房を入れ始めた方も多いのではないでしょうか。 温かいコーヒーを片手に、シリーズ第4回「プロキシサーバーと統合Windows認証」をお届けします。 さて、前回(第3回)は、クライアントPCやサーバーをドメインに参加させる際の「信頼関係」の確立について深掘りしました。コンピューターアカウントが120文字のパスワードで自動認証される仕組みを理解いただけたことで、今回のプロキシサーバーの話もスムーズに入っていけるはずです。 ChatGPTやClaudeへのアクセスを監視する中間プロキシを構築する際、最も重要なのが「確実なユーザー特定」です。せっかくHTTPS通信をインターセプトして入出力内容を記録できても、アクセス元が「tanaka_t」なのか「yamada_h」なのかが分からなければ、監査ログとしての価値は半減してしまいます。 今回は、プロキシサーバー自体をドメインメンバーとして動作させることで、Kerberosチケットの検証を可能にし、透過的なユーザー認証を実現する方法を詳しく解説します。Windows版Squid

By Qualiteg AIセキュリティチーム
エンジニアリングは「趣味」になってしまうのか

エンジニアリングは「趣味」になってしまうのか

こんにちは! 本日は vibe coding(バイブコーディング、つまりAIが自動的にソフトウェアを作ってくれる)と私たちエンジニアの将来について論じてみたいとおもいます。 ちなみに、自分で作るべきか、vibe codingでAIまかせにすべきか、といった二元論的な結論は出せていません。 悩みながらいったりきたり考えてる思考過程をツラツラと書かせていただきました。 「作る喜び」の変質 まずvibe codingという言葉についてです。 2025年2月、Andrej Karpathy氏(OpenAI創設メンバー)が「vibe coding」という言葉を広めました。 彼は自身のX(旧Twitter)投稿で、 「完全にバイブに身を任せ、コードの存在すら忘れる」 と表現しています。 つまり、LLMを相棒に自然言語でコードを生成させる、そんな新しい開発スタイルを指します。 確かにその生産性は圧倒的です。Y Combinatorの2025年冬バッチでは、同社の発表によれば参加スタートアップの約25%がコードの95%をAIで生成していたとされています(TechCrunch, 2

By Qualiteg プロダクト開発部