mcpField
S
sn-da-image-caption

sn-da-image-caption

github.com/opensensenovaデータ・データベース6.0k139 回インストール2 日前に更新
リポジトリ

sn-da-image-caption について

sn-da-image-captionは、画像の説明文作成やデータ抽出を行うスキルです。グラフや表などの種類を判定し、バッチ処理と結果のキャッシュにも対応します。

主な機能

  1. 01画像のテキスト説明を生成
  2. 02グラフ、表、UI画像を判定
  3. 03カスタムプロンプトによる抽出指定
  4. 04画像ディレクトリの一括処理
  5. 05JSON出力と結果キャッシュ

活用シーン

  1. 01グラフ画像から数値を抽出
  2. 02表のスクリーンショットをMarkdown表に変換
  3. 03複数画像の説明結果を整理

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/opensensenova/sensenova-skills --skill sn-da-image-caption

インストール後、Claude Code で/sn-da-image-captionを入力して読み込まれたか確認します。

同梱ファイルscripts/caption.py

詳細

画像キャプション分析 — 画像の説明とデータ抽出

概要

画像ファイル(.png、.jpg、.jpeg、.gif、.webp、.bmp)を分析し、データを抽出したり、内容を理解したりできます。基本的なワークフローは次のとおりです。

  1. scripts/caption.py を実行して、画像のテキスト説明を取得します
  2. 説明を構造化データ(DataFrame など)に解析します
  3. 分析、可視化、またはエクスポートを行います

scripts/caption.py — 画像キャプション

このスクリプトは、ビジョンモデルを使って画像をテキストの説明に変換します。SN_API_KEY(必須)を設定するか、詳細に制御する場合は SN_VISION_API_KEY/SN_VISION_BASE_URL/SN_VISION_MODEL を使用してください。フォールバックの全順序については、プロジェクトの環境変数仕様を参照してください。

使い方
# Basic — get text description
python3 scripts/caption.py /mnt/data/image.png

# Custom prompt — guide what to extract
python3 scripts/caption.py /mnt/data/chart.png --prompt "提取所有数值,Markdown 表格格式"

# JSON output — includes detected type, usage stats, cache info
python3 scripts/caption.py /mnt/data/image.png --json

# Batch — process all images in a directory
python3 scripts/caption.py /mnt/data/images/ --batch --output /mnt/data/captions.json

# Override model (optional)
python3 scripts/caption.py /mnt/data/image.png --model gemini-3.1-flash-lite-preview
オプション
オプション説明
--prompt, -pカスタムプロンプト(自動検出を上書きします)
--model, -mビジョンモデル(デフォルト:sensenova-6.8-flash-lite)
--jsonプレーンテキストではなく、構造化 JSON を出力します
--batchディレクトリ内のすべての画像を処理します
--output, -oバッチ処理結果の出力ファイル
--no-cacheMD5 キャッシュをスキップします
自動的に行われる処理
  • 種類の検出:ファイル名から画像の種類(グラフ/表/UI/図/一般)を検出し、最適なプロンプトを選択します
  • 圧縮:5MB 超または 2048px 超の画像は、送信前に圧縮されます
  • キャッシュ:同じ画像+同じプロンプトの場合、キャッシュ結果を即座に返し、API コストはかかりません
  • エラー処理:失敗時は再試行し、再試行しても失敗する場合はエラーメッセージを返します
JSON 出力形式
{
  "file": "/mnt/data/image.png",
  "type": "chart",
  "description": "这是一张柱状图...",
  "usage": {"prompt_tokens": 1100, "completion_tokens": 400},
  "cached": false
}

Python からの呼び出し

import subprocess, json

CAPTION = "/path/to/skills/sn-da-image-caption/scripts/caption.py"

# Single image
result = subprocess.run(
    ["python3", CAPTION, "/mnt/data/chart.png", "--json",
     "--prompt", "提取图表数据,Markdown 表格输出"],
    capture_output=True, text=True, timeout=60
)
data = json.loads(result.stdout)
description = data["description"]

# Batch
result = subprocess.run(
    ["python3", CAPTION, "/mnt/data/images/", "--batch",
     "--output", "/mnt/data/captions.json"],
    capture_output=True, text=True, timeout=300
)
with open("/mnt/data/captions.json") as f:
    all_captions = json.load(f)

プロンプト戦略

画像の種類ごとに適したプロンプトは異なります。スクリプトは種類を自動検出しますが、--prompt を指定すると、より良い結果が得られます。

画像の種類場面推奨する --prompt
データグラフ棒グラフ/折れ線グラフ/円グラフ"グラフのタイトル、軸、各データポイントの値、凡例を抽出してください。Markdown テーブルで出力してください。"
表のスクリーンショット表のスクリーンショット"表のすべての内容を抽出してください。Markdown テーブル形式で、行と列の構造を保ち、数値は四捨五入しないでください。"
UI のスクリーンショットUI のスクリーンショット"フロントエンド開発者の視点で説明してください:レイアウト、コンポーネント、テキスト、色。"
図フローチャート/アーキテクチャ図"すべてのノード、接続関係(A→B)、分岐条件を説明してください。"
一般写真、その他--prompt を渡さず、デフォルトを使用します

キャプション結果の解析

キャプションは通常 Markdown テーブルを返すため、DataFrame に解析します。

import pandas as pd

def parse_markdown_table(text):
    lines = text.strip().split('\n')
    table_lines = []
    in_table = False
    for line in lines:
        stripped = line.strip()
        if '|' in stripped:
            in_table = True
            table_lines.append(stripped)
        elif in_table:
            break

    data_lines = []
    for l in table_lines:
        cells = [c.strip() for c in l.split('|') if c.strip()]
        if cells and not all(set(c) <= set('-: ') for c in cells):
            data_lines.append(cells)

    if len(data_lines) < 2:
        return None

    header = data_lines[0]
    rows = [r for r in data_lines[1:] if len(r) == len(header)]
    df = pd.DataFrame(rows, columns=header)

    # Auto numeric conversion
    for col in df.columns:
        try:
            cleaned = df[col].str.replace(',', '').str.strip()
            if cleaned.str.endswith('%').any():
                df[col] = pd.to_numeric(cleaned.str.rstrip('%'), errors='coerce')
            else:
                converted = pd.to_numeric(cleaned, errors='coerce')
                if converted.notna().sum() > len(df) * 0.5:
                    df[col] = converted
        except Exception:
            pass
    return df

可視化

中国語フォントの設定(必須)
import matplotlib.pyplot as plt
import matplotlib
import os

font_path = '/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc'
if os.path.exists(font_path):
    matplotlib.rcParams['font.family'] = 'WenQuanYi Zen Hei'
matplotlib.rcParams['axes.unicode_minus'] = False
カラーパレット
COLORS = ['#4C72B0', '#55A868', '#C44E52', '#8172B2', '#CCB974', '#64B5CD']
保存と表示
plt.savefig('/mnt/data/chart.png', dpi=150, bbox_inches='tight')
plt.show()
print("![图表](sandbox:/mnt/data/chart.png)")

Excel へのエクスポート

from openpyxl.styles import Font, PatternFill, Alignment

output_path = "/mnt/data/result.xlsx"
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
    df.to_excel(writer, index=False, sheet_name='提取数据')
    ws = writer.sheets['提取数据']
    fill = PatternFill(start_color='4472C4', end_color='4472C4', fill_type='solid')
    for cell in ws[1]:
        cell.font = Font(bold=True, color='FFFFFF')
        cell.fill = fill
        cell.alignment = Alignment(horizontal='center')
    for i, col in enumerate(df.columns, 1):
        w = max(df[col].astype(str).str.len().max(), len(str(col))) + 2
        ws.column_dimensions[chr(64 + i)].width = min(w * 1.2, 40)

print(f"[下载](sandbox:{output_path})")

複数画像の処理

import glob

image_files = sorted(glob.glob("/mnt/data/*.png"))
all_dfs = []

for img in image_files:
    r = subprocess.run(
        ["python3", CAPTION, img, "--json", "--prompt", "提取数据,Markdown 表格"],
        capture_output=True, text=True, timeout=60
    )
    desc = json.loads(r.stdout)["description"]
    df = parse_markdown_table(desc)
    if df is not None:
        all_dfs.append(df)

combined = pd.concat(all_dfs, ignore_index=True) if all_dfs else None

または、バッチモードを使用します。

python3 scripts/caption.py /mnt/data/images/ --batch --output /mnt/data/captions.json

よくある落とし穴

  • 必ず最初にキャプションを生成する — ファイル名から画像の内容を推測しないでください
  • 正確さを求める場合は --prompt を使用する — 自動検出でも問題ありませんが、プロンプトを明示するとより良い結果が得られます
  • 抽出したデータを確認する — 解析後に合計、割合、行数を確認してください
  • 大きな表は途中で切り詰められます — 2 回に分けてキャプションを生成します:「前半を抽出」+「後半を抽出」
  • 中国語フォント — matplotlib を呼び出す前に設定する必要があります。設定しないと出力が文字化けします
  • タイムアウト — 画像 1 枚あたり約 10~30 秒です。バッチ処理では適切なタイムアウトを設定してください

コメント