Web Annotation Data Modelの基礎

IIIFにおけるアノテーションは、W3CのWeb Annotation Data Modelに準拠しています。このモデルでは、アノテーションは「何について」(target)「何を言っているか」(body)「なぜ」(motivation)の3要素で構成されます。

{
  "type": "Annotation",
  "motivation": "commenting",
  "body": {
    "type": "TextualBody",
    "value": "これは桐壺の冒頭部分です"
  },
  "target": "https://example.com/canvas/p1#xywh=100,200,300,150"
}

IIIF Presentation API v3では、アノテーションはCanvas内のannotationsプロパティにAnnotationPageとして格納されます。itemsプロパティ内のpainting motivationのアノテーションが画像や動画の描画に使われるのに対し、annotationsプロパティにはcommentingtaggingsupplementingなどのmotivationを持つ付加的なアノテーションが格納されます。

motivationの主な種類は以下の通りです。

  • painting: キャンバスへのコンテンツ描画(画像・動画・音声)
  • commenting: テキストコメントの付与
  • tagging: タグの付与
  • supplementing: 補足情報(字幕やトランスクリプトなど)の提供
  • highlighting: 強調表示

アノテーションの種類

IIIFアノテーションでは、対象領域の指定方法によってさまざまな形状のアノテーションを表現できます。

矩形アノテーション(Fragment Selector)

最も基本的な形式で、xywhパラメータにより矩形領域を指定します。

{
  "target": "https://example.com/canvas/p1#xywh=100,200,300,150"
}

これは座標(100, 200)を起点とし、幅300、高さ150の矩形を表します。シンプルで処理が軽いため、多くのユースケースで利用されます。

SVGアノテーション(SVG Selector)

SVGのpath要素を使って、任意の形状の領域を指定できます。ピンマーカーや複雑な形状の表現に適しています。

{
  "target": {
    "source": "https://example.com/canvas/p1",
    "type": "SpecificResource",
    "selector": {
      "type": "SvgSelector",
      "value": "<svg xmlns='http://www.w3.org/2000/svg'><path d='M2798,1309c0,-34 17,-68 51,-102...' fill-opacity='0.5' fill='#F3AA00' stroke='#f38200'/></svg>"
    }
  }
}

SVG Selectorでは色や透明度も指定できるため、視覚的に豊かなアノテーション表現が可能です。Miradorなどのビューアで正しく描画されます。

多角形アノテーション

SVG Selectorの応用として、多角形(ポリゴン)による領域指定があります。古地図上の地名や不規則な形状のテキスト領域など、矩形では正確に囲めない対象に有効です。

FragmentSelectorとSvgSelectorの併用

傾いた文字や回転した領域を扱う場合、FragmentSelectorとSvgSelectorの両方を使用することで、効率的な処理が可能になります。

{
  "selector": [
    {
      "type": "FragmentSelector",
      "value": "xywh=9030,15590,1231,244"
    },
    {
      "type": "SvgSelector",
      "value": "<svg xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M 9034.61 15828.17 L 10261.06 15835.12 L 10262.08 15596.18 L 9030.33 15590.72 Z\" /></svg>"
    }
  ]
}

FragmentSelectorはIIIF Image APIでの画像切り出しに使う境界ボックスを提供し、SvgSelectorは傾き計算のための正確な頂点座標を保持します。多角形の頂点を「左上 → 左下 → 右下 → 右上」の順序で指定すれば、上辺のベクトルから傾き角度をMath.atan2で計算でき、IIIF Image APIの回転パラメータとして活用できます。

Annotoriousを使ったアノテーション作成

Annotoriousは、Web上の画像にアノテーションを付与するためのJavaScriptライブラリです。OpenSeadragonプラグインが提供されており、IIIF画像への対話的なアノテーション作成が可能です。

OpenSeadragonとの統合

Annotorious OpenSeadragon Pluginを使用することで、IIIFマニフェストからロードした複数画像に対してアノテーションを付与できます。

Nuxt3で使用する場合、Annotoriousはクライアントサイド用プラグインとして読み込みます。ページ切り替え時にはアノテーションをクリアし、該当ページのアノテーションを再ロードする処理が必要です。

// ページごとのアノテーションをリアクティブオブジェクトで管理
const annotationsMap = ref({});

viewer.addHandler("page", () => {
  anno.clearAnnotations();
  showCurrentCanvasAnnotations();
});

const showCurrentCanvasAnnotations = () => {
  const index = viewer.currentPage();
  if (annotationsMap.value[index]) {
    annotationsMap.value[index].forEach((annotation) => {
      anno.addAnnotation(annotation);
    });
  }
};

Annotorious React版

AnnotoriousにはReact向けのライブラリも公開されています。OpenSeadragonとの統合がコンポーネントベースで行え、W3C Image FormatのFormatAdapterを適用することで、アノテーションの記述形式をW3C Web Annotation Data Modelに準拠した形式に変換できます。

import { W3CImageFormat } from "@annotorious/annotorious";

<OpenSeadragonAnnotator
  drawingEnabled={tool !== undefined}
  tool={tool || "rectangle"}
  adapter={W3CImageFormat("")}
>
  <OpenSeadragonViewer options={options} />
</OpenSeadragonAnnotator>

adapter={W3CImageFormat("")}を指定することで、Annotorious独自のフォーマットではなく、W3C標準形式でアノテーションが生成されます。これにより、他のIIIFツール(Miradorのmirador-annotationsプラグインなど)との互換性が向上します。

多角形アノテーションの実装

矩形では正確に囲めない対象に対して、多角形アノテーションが必要になる場面は少なくありません。古地図上の地名、傾いた文字、不規則な形状の図像などが代表的なケースです。

既存ツールの比較

多角形アノテーションを付与可能な既存ツールには、以下のようなものがあります。

  • Omeka Classic + IIIF Toolkit: Mirador 2ベースでポリゴンアノテーションが可能だが、サーバの準備・維持が必要
  • Recogito: 傾斜ボックスは付与可能だが、多角形には未対応。pctベースのIIIF画像アクセスで表示できないケースもある
  • Glycerine: Annotorious v2ベースで多角形対応・共同作業可能。ただし一括エクスポート機能がない

これらの制約を踏まえ、Annotorious(React版)とFirebase(Authentication + Firestore)を組み合わせた多角形アノテーション付与ツールの構築事例があります。このツールでは、ユーザ認証によるアノテーション管理、一括エクスポート機能、IIIF Presentation API v2/v3両対応(@iiif/parserによるv2からv3への変換)などの機能を提供しています。

エクスポート機能

付与したアノテーションは以下の形式でエクスポートできます。

  • アノテーション付きIIIFマニフェスト: Miradorなどのビューアで直接閲覧可能
  • TEI/XMLファイル: Oxygen XML Editorなどの学術用エディタで利用可能

Image Server未使用のマニフェストにも対応するには、serviceプロパティの有無に応じてOpenSeadragonのtileSourcesを切り替える処理が必要です。

フリーハンドから矩形への変換

アノテーション作成時、フリーハンド(自由描画)で領域を指定した方が直感的に操作しやすい場合があります。しかし、最終的には矩形として利用したい(例えば、IIIF Image APIで画像を切り出すため)というケースも多くあります。

Pythonを使って、SVG形式のフリーハンドアノテーションから外接矩形を計算し、xywh形式の矩形アノテーションに変換するライブラリが公開されています。フリーハンドのパス座標から最小・最大のx, y座標を抽出し、それを外接矩形として出力する仕組みです。

この手法により、直感的なフリーハンド操作で領域を指定しつつ、データとしては処理しやすい矩形形式を得ることができます。

IIIF Content Search APIの概要と静的実装

IIIF Content Search APIは、マニフェスト内のアノテーションを検索するためのAPIです。通常はサーバーサイドの実装が前提となりますが、Service Workerを活用することで、静的サイトでもクライアントサイドで検索機能を実現できます。

アーキテクチャ

[[JI[MSaIMievIirraFraviSadincCdocdrooreeinr]xpt]W.teojnrstGkoEenSTre]a/rsceharAcPhI/index.json?q=keyword

実装の流れ

  1. ビルド時に検索インデックスを生成: アノテーションデータからテキスト・キャンバスID・ターゲット情報を含むindex.jsonを作成
  2. Service Workerの実装: /search/index.json?q=を含むURLへのfetchリクエストをインターセプトし、インデックスに対して検索を実行
  3. レスポンスの生成: 検索結果をIIIF Content Search API 1.0形式のAnnotationListとして返却
  4. マニフェストへのサービス宣言: マニフェストのserviceプロパティにSearchService1を宣言
{
  "service": [{
    "@context": "http://iiif.io/api/search/1/context.json",
    "@id": "https://example.com/search/index.json",
    "@type": "SearchService1",
    "profile": "http://iiif.io/api/search/1/search"
  }]
}

メリットと制限

この手法の利点は、サーバーが不要でGitHub PagesやVercelなどの静的ホスティングで動作し、Mirador本体の改修も不要な点です。一方、大規模コレクションではインデックスの初回読み込みに時間がかかることや、HTTPS環境が必須である点に注意が必要です。大規模対応としては、マニフェストごとのインデックス分割や遅延読み込みが有効です。

アノテーション表示のパフォーマンス最適化

アノテーション数が多い場合、特に3Dビューアでの表示においてパフォーマンスが課題となります。背面判定(Raycast)処理がボトルネックとなり、毎フレーム実行すると60FPSの維持が困難になります。

Idle時のみRaycast実行

カメラが移動している間はRaycast処理をスキップし、カメラが停止してから一定フレーム数(約0.5秒)待機した後に1回だけ実行する方式が有効です。

const CAMERA_MOVE_THRESHOLD = 0.01;
const IDLE_FRAMES_BEFORE_RAYCAST = 30;

useFrame(() => {
  const cameraMoved = camera.position.distanceTo(prevCameraPosition) > CAMERA_MOVE_THRESHOLD;

  if (cameraMoved) {
    idleFrameCountRef.current = 0;
    needsRaycastRef.current = true;
    return; // Raycast処理をスキップ
  }

  idleFrameCountRef.current++;
  if (!needsRaycastRef.current) return;
  if (idleFrameCountRef.current < IDLE_FRAMES_BEFORE_RAYCAST) return;

  needsRaycastRef.current = false;
  // Raycast処理を実行(1回のみ)
});

2段階の判定処理

Raycast処理自体も最適化できます。第1パスで視野外のアノテーションをFrustum判定とカメラ前後判定により軽量に除外し、第2パスで残ったアノテーションのみにRaycast判定を行います。これにより、ドラッグ中の負荷をほぼゼロに抑えつつ、停止後には正確な背面判定を得られます。

テキスト比較ツールへの応用

IIIFアノテーションの活用例として、マニフェストに含まれるテキストアノテーションを利用した資料比較ツールがあります。

3つの比較モード

  1. 画像比較: OpenSeadragonを用いて2つの資料の画像を左右に並べ、ズーム・パン・回転・ページ送りに対応
  2. テキスト差分(Diff): テキストアノテーションを抽出し、文字単位での差分をハイライト表示。追加箇所は緑色、削除箇所は赤色の取り消し線で可視化
  3. 編集距離(Levenshtein Distance): 行単位のテキスト類似度を算出し、ネットワークグラフとして可視化。類似度の高い行同士がエッジで結ばれる

データフロー

マニフェストURLを入力すると、fetchManifest()関数がIIIF Presentation API v3のマニフェストをパースし、各キャンバスの画像URLとテキストアノテーションを抽出します。Zustandストアに格納されたデータを各コンポーネントがリアクティブに参照する設計です。

比較結果はURLパラメータとして保持されるため、URLを共有するだけで同じ比較画面を再現でき、embed=1パラメータによりiframeでの埋め込みにも対応します。

まとめ

IIIFアノテーションは、W3C Web Annotation Data Modelに基づく標準的な枠組みであり、矩形・多角形・SVG・フリーハンドなどさまざまな形状に対応しています。Annotoriousのようなライブラリを活用すれば対話的なアノテーション作成が可能であり、FormatAdapterの適用によりW3C標準形式での出力も容易です。

IIIF Content Search APIのService Workerによる静的実装は、サーバーレス環境でのアノテーション検索を実現する手法として注目に値します。また、アノテーションデータの活用はテキスト比較ツールのような高度な分析ツールの基盤としても機能します。アノテーション数が増大した場合のパフォーマンス最適化も、実運用においては重要な検討事項です。