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

ログを ちょこっと grep するツール "ちょこぐれっぷ" つくりました

ログを ちょこっと grep するツール "ちょこぐれっぷ" つくりました

こんにちは! 今日はちょこっとしたツールをつくりました。 ログをちょこっとgrepするツールです。もちろん無料。 chocoGrep - ちょこっとgrep!ログフィルタツールちょこっとgrepするならchocoGrep!「error or warning」と書くだけの簡単or/and検索。AIエージェントに渡す前にログを最適化。正規表現不要、インストール不要。chocoGrepQualiteg Inc. Cursor、Devin、Claude Code、ChatGPT——AIコーディングエージェントにエラーログを渡してデバッグを手伝ってもらう。もう日常ですよね。 でも、 * ログを全部貼り付けたら、AIの応答がやたら遅い * 「トークン制限を超えました」と怒られる * 大量のログの中から、AIが的外れな部分に注目してしまう そこで、つくったちょこっとgrepするためのツールです 名付けて ちょこぐれっぷ!chogoGrep! chocoGrepって何? ブラウザで動く、ゆるいgrepツールです。 ログを貼り付けて、検索ワードを入れるだけ。インストール不要

By Qualiteg プロダクト開発部
GPUを使った分散処理で見落としがちなCPUボトルネックとtasksetによる解決法

GPUを使った分散処理で見落としがちなCPUボトルネックとtasksetによる解決法

こんにちは! 複数枚のGPUをつかった並列処理システムを設計しているときCPUについてはあまり考えないでシステムを設計してしまうことがあります。 「機械学習システムの主役はGPUなんだから、CPUなんて、あんまり気にしなくてよいのでは」 いいえ、そうでもないんです。 推論中のあるタイミングに急に動作が遅くなったりするときCPUが原因であることがけっこうあります。 概要(5分で分かる要点) 先日GPUを使った並列処理システムで、予期しないCPUボトルネックが発生し、パフォーマンスが大幅に低下する問題に遭遇しました。 複数のプロセスが異なるGPUを使用しているにも関わらず、処理が極端に遅くなる現象の原因は、処理パイプラインの一部に含まれるCPU集約的な計算処理でした。 問題の症状 * 単一プロセス実行時:正常な速度 * 複数プロセス並列実行時:処理時間が数倍に増加 * GPUリソースに競合なし(nvidia-smiで確認済み) 根本原因 処理パイプラインにGPUに適さないCPU集約的な計算(データ前処理、統計変換など)が含まれており、複数プロセスが同じCP

By Qualiteg プロダクト開発部
Model Context Protocol完全実装ガイド 2025- 仕様変遷から最新Streamable HTTPまでの全て

Model Context Protocol完全実装ガイド 2025- 仕様変遷から最新Streamable HTTPまでの全て

こんにちは! 現在、LLM業界で破竹の勢いでひろまっているMCPについて、本日はとくに実装面について解説していきたいとおもいます。 MCP、MCPとひとくちにいっていますが、実は短期間でけっこう「標準」とよばれる仕様が変化しておりますので、仕様のバリエーションを順を追って解説しつつ、実際に実装をしていきたいとおもいます。 さて、MCPですが、2024年後半、Anthropicが発表したModel Context Protocol(MCP)は、AI分野における重要な転換点となりました。 従来、各AIベンダーが独自に実装していたツール呼び出し機能(tool useと呼びます)を標準化し、AIモデルと外部システムの連携を統一的に扱える仕組みを提供しました 本記事で、MCPの誕生から現在に至るまでの技術的変遷を詳細に追いながら、2025年時点での最適な実装方法を完全なソースコードと共に解説します。特に、仕様の変化に振り回されがちな実装者の視点から、なぜ現在の形に収束したのか、そして今後どのような実装アプローチを取るべきかを明確にしていきます。 第1章 MCPが解決しようとした問題

By Qualiteg プロダクト開発部
【出展報告】ASCII STARTUP TechDay 2025

【出展報告】ASCII STARTUP TechDay 2025

こんにちは! 本日、「ASCII STARTUP TechDay 2025」に出展してまいりましたのでレポートさせていただきます! ASCII STARTUP TechDay 2025 ASCII STARTUP TechDay 2025は、2025年11月17日(月)に東京・浅草橋ヒューリックホール&カンファレンスで開催された、ディープテック・スタートアップのエコシステム構築をテーマにした展示交流・カンファレンスイベントです。 秋の展示会は本当にいいですね 本日はとてもよいお天気で、涼しくて、展示会にはピッタリの気候で朝からルンルンでした。しかも午後からの展示会ということで、気持ちに余裕をもって朝の業務をこなしていたところ、けっこうすぐに昼前になり、あわてて現場へ。 浅草橋は当社からもわりと近いという立地の良さを甘く見ておりましたが💦、なんとか予定時刻前に到着しました。やっぱり、都心開催は本当にありがたいですね。 会場へ急いでいると、おなかが「ぐ~」と鳴り 「そういえば、朝食まだだったわ」 とおもったところに、なんと私の大好きなエッセンさん🍞のトラックがあるで

By Qualiteg ビジネス開発本部 | マーケティング部