ホーム 記事一覧 ブック DH週間トピックス 検索 このサイトについて
English

最新の記事

GakuNin RDMとDydraを連携したRDFメタデータ管理システムの開発

GakuNin RDMとDydraを連携したRDFメタデータ管理システムの開発

はじめに 本記事では、GakuNin RDM(Research Data Management)とDydra RDFデータベースを連携させた、研究データのメタデータ管理システムの開発について解説します。このシステムは、研究プロジェクトのファイル管理とDublin Coreメタデータの登録・検索を統合的に扱うことができます。 システム概要 アーキテクチャ ┌─────────────────┐ │ Next.js 14 │ │ (App Router) │ └────────┬────────┘ │ ┌────┴────┐ │ │ ┌───▼───┐ ┌──▼─────┐ │GakuNin│ │ Dydra │ │ RDM │ │ RDF │ │ API │ │ DB │ └───────┘ └────────┘ 主要技術スタック: Next.js 14 (App Router) NextAuth.js (OAuth 2.0認証) Dydra (RDFデータベース) GakuNin RDM API SPARQL (クエリ言語) 1. GakuNin RDMとの連携 1.1 OAuth 2.0認証の実装 GakuNin RDMはOAuth 2.0による認証をサポートしています。NextAuth.jsを使用してこれを実装しました。 ...

Odeuropa Explorer の語彙階層構造を調査する

Odeuropa Explorer の語彙階層構造を調査する

はじめに Odeuropa Explorer は、ヨーロッパの嗅覚遺産をデジタル化した興味深いプロジェクトです。EU の Horizon 2020 研究プログラムの助成を受け、歴史的な匂いの体験を横断的に検索・探索できるプラットフォームを提供しています。 このプロジェクトでは、匂いに関連する情報を以下の3つの主要なカテゴリで分類しています: Smell sources : 匂いを発する物体や物質 Fragrant Spaces : 匂いに関連する場所や空間 Gestures and Allegories : 匂いに関する身振りや寓意的表現 本記事では、これらの語彙がどのような階層構造を持っているのか、Odeuropa vocabularies リポジトリで公開されている SKOS(Simple Knowledge Organization System)形式のデータを調査した結果を報告します。 調査方法 SKOS階層の可視化スクリプト 語彙の階層構造を理解するために、Node.js で SKOS Turtle ファイルを解析するスクリプトを作成しました。 import $rdf from 'rdflib'; import fs from 'fs'; const SKOS = $rdf.Namespace('http://www.w3.org/2004/02/skos/core#'); async function visualizeHierarchy(ttlFile) { const store = $rdf.graph(); const data = fs.readFileSync(ttlFile, 'utf8'); $rdf.parse(data, store, 'http://example.org/', 'text/turtle'); // Get all concepts const concepts = store.match(null, $rdf.sym('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), SKOS('Concept')); // Build maps for broader/narrower relationships const broaderMap = new Map(); const narrowerMap = new Map(); const conceptLabels = new Map(); for (const concept of concepts) { const subject = concept.subject; // Get prefLabel const labels = store.match(subject, SKOS('prefLabel'), null); if (labels.length > 0) { conceptLabels.set(subject.value, labels[0].object.value); } // Get broader concepts const broaders = store.match(subject, SKOS('broader'), null); if (broaders.length > 0) { const broader = broaders[0].object.value; broaderMap.set(subject.value, broader); if (!narrowerMap.has(broader)) { narrowerMap.set(broader, []); } narrowerMap.get(broader).push(subject.value); } } // Print hierarchy recursively function printHierarchy(conceptUri, indent = '', visited = new Set()) { if (visited.has(conceptUri)) return; visited.add(conceptUri); const label = conceptLabels.get(conceptUri); const children = narrowerMap.get(conceptUri) || []; console.log(`${indent}${label}`); children.forEach((child, index) => { const isLast = index === children.length - 1; const prefix = isLast ? '└── ' : '├── '; printHierarchy(child, indent + prefix, new Set(visited)); }); } // Find and display top-level concepts const topLevelConcepts = []; for (const concept of concepts) { if (!broaderMap.has(concept.subject.value)) { topLevelConcepts.push(concept.subject.value); } } topLevelConcepts.forEach(concept => printHierarchy(concept)); } このスクリプトの主要な処理: ...

DydraへのAPI経由でのRDFデータ登録ガイド

DydraへのAPI経由でのRDFデータ登録ガイド

はじめに Dydraは、クラウドベースのRDFデータベースサービスで、SPARQL endpointとREST APIを提供しています。本記事では、Dydra APIを使用してプログラマティックにRDFデータを登録する方法を解説します。 前提条件 Dydraアカウント APIキー Node.js環境(v16以上推奨、Node.js使用時) 注意: 本記事のコード例では、サンプルとして以下を使用しています: アカウント名: your-account リポジトリ名: your-repository APIキー: your_api_key_here 実際に使用する際は、ご自身のDydraアカウント情報に置き換えてください。 APIの基本情報 エンドポイント構成 ベースURL: https://dydra.com/{account}/{repository} 例: https://dydra.com/your-account/your-repository SPARQL Query: /sparql (GET) SPARQL Update: /sparql (POST) Statements: /statements (POST/GET/DELETE) 認証 DydraではBearerトークン認証を使用します: Authorization: Bearer YOUR_API_KEY 実装方法 Dydra APIへのアクセスは、curl、Python、Node.jsなど様々な方法で実装できます。それぞれの方法を紹介します。 方法1: curlでの実装(最もシンプル) curlを使えば、プログラミング言語なしで即座にデータ登録が可能です。 基本的な認証 # APIキーを環境変数に設定 export DYDRA_API_KEY="your_api_key_here" export DYDRA_BASE_URL="https://dydra.com/your-account/your-repository" Turtle形式でのデータ登録 # data.ttl ファイルから登録 curl -X POST \ -H "Authorization: Bearer ${DYDRA_API_KEY}" \ -H "Content-Type: text/turtle" \ --data-binary @data.ttl \ "${DYDRA_BASE_URL}/statements" data.ttl の例: ...

TEI Processing Modelで実現する宣言的なマルチフォーマット変換

TEI Processing Modelで実現する宣言的なマルチフォーマット変換

はじめに TEI (Text Encoding Initiative) は人文学テキストのデジタル化において広く使われている標準規格です。本記事では、TEI P5で導入された Processing Model という機能を使って、TEI XMLから複数のフォーマット(HTML、LaTeX/PDF、EPUB3)への変換を実現した事例を紹介します。 https://www.tei-c.org/Vault/P5/3.0.0/doc/tei-p5-doc/en/html/TD.html#TDPM 対象プロジェクトは「校異源氏物語」で公開されているテキストを例とします。 https://kouigenjimonogatari.github.io/ 背景 これまで、以下の記事で紹介したように、変換処理を個別に行ってきました。 ODD/RNGファイルのカスタマイズによる、使用するタグの限定 XSLTを用いたHTMLへの変換 XSLTを用いたTeX/PDFへの変換 EPUBへの変換 それぞれの取り組みにおいて、個別の変換ルールなどを記載したファイルを作成する必要があり、その煩雑さが課題となっていました。 Processing Modelとは Processing Modelは、TEI要素の変換ルールを宣言的 に記述する仕組みです。従来は各出力フォーマット用に個別のXSLTを書く必要がありましたが、Processing Modelを使うことで: ODDファイル内で変換ルールを定義 できる 複数の出力フォーマット に対応可能(web、latex、epubなど) スキーマと変換ルールを一元管理 できる Processing Modelの構造 <elementSpec ident="persName" mode="change"> <desc>Personal name</desc> <model> <!-- HTML output --> <modelSequence output="web"> <model behaviour="inline"> <outputRendition>span</outputRendition> <desc>Inline span for person name</desc> </model> </modelSequence> <!-- EPUB3 output --> <modelSequence output="epub"> <model behaviour="inline"> <outputRendition>span</outputRendition> <desc>Inline span for person name in EPUB3</desc> </model> </modelSequence> <!-- LaTeX output --> <modelSequence output="latex"> <model behaviour="inline"> <outputRendition>\person</outputRendition> <desc>Custom LaTeX command for person names</desc> </model> </modelSequence> </model> </elementSpec> 主な要素: ...

Miradorの表示方向を外部から制御する方法

Miradorの表示方向を外部から制御する方法

概要 Mirador viewerの表示方向(viewingDirection)をURLパラメータから動的に指定する実装について解説します。この機能により、同じマニフェストを左から右(left-to-right)または右から左(right-to-left)で表示することができます。 実装方法 1. URLパラメータの取得 URLからviewingDirectionパラメータを取得し、デフォルト値を設定します: // URLパラメータから表示方向を取得 const urlParams = new URLSearchParams(window.location.search); const viewingDirection = urlParams.get('viewingDirection') || 'right-to-left'; この実装では、パラメータが指定されていない場合は'right-to-left'(右から左)がデフォルトとして使用されます。 2. Mirador設定への適用 取得したviewingDirectionをMiradorの初期設定に組み込みます: const miradorConfig = { id: "viewer", windows: [{ id: 'known-window-id', loadedManifest: manifestUrl, viewingDirection: viewingDirection, // URLパラメータの値を使用 }], window: { allowClose: false, allowMaximize: false, allowFullscreen: false, hideWindowTitle: true, }, workspaceControlPanel: { enabled: false, }, }; 3. 使用例 右から左表示(デフォルト) https://example.com/viewer.xml または https://example.com/viewer.xml?viewingDirection=right-to-left 左から右表示 https://example.com/viewer.xml?viewingDirection=left-to-right XSLTでの実装 XSLTテンプレート内でこの機能を実装する場合、以下のコードをスクリプトセクションに追加します(mirador.xsl:222-230): <!-- URLパラメータから表示方向を取得 --> const viewingDirection = urlParams.get('viewingDirection') || 'right-to-left'; // Miradorの初期設定 const miradorConfig = { id: "viewer", windows: [{ id: 'known-window-id', loadedManifest: manifestUrl, viewingDirection: viewingDirection, }], // ... その他の設定 }; 利用可能な値 MiradorのviewingDirectionには以下の値が使用できます: left-to-right - 左から右へページをめくる(欧文書籍など) right-to-left - 右から左へページをめくる(和書、アラビア語書籍など) top-to-bottom - 上から下へ(巻物など) bottom-to-top - 下から上へ 注意点 マニフェストファイル内でviewingDirectionが指定されている場合、マニフェストの設定が優先されます。この方法は主にマニフェストファイル内で表示方向が指定されていない場合に有効です この設定はwindow単位で適用されます URLパラメータはページ読み込み時にのみ評価されます ユーザーがMirador UI上で表示方向を変更した場合、URLパラメータの値は上書きされます 関連ファイル xsl/mirador.xsl - XSLT変換テンプレート(実装箇所)

Odeuropa:歴史的文献から匂いを抽出するLinked Dataの世界

Odeuropa:歴史的文献から匂いを抽出するLinked Dataの世界

はじめに Odeuropa(オデウロパ)は、ヨーロッパの歴史的文献から「匂い」に関する記述を抽出し、Linked Dataとして構造化したユニークなプロジェクトです。本記事では、SPARQLエンドポイントを通じて実際のデータを探索し、その構造と設計思想を明らかにしていきます。 Odeuropaとは プロジェクト名 : Odeuropa(Odeurs d’Europe = ヨーロッパの匂い) データベースURL : https://data.odeuropa.eu/ SPARQLエンドポイント : https://data.odeuropa.eu/repositories/odeuropa Webインターフェース : https://explorer.odeuropa.eu/ データモデルの全体像 OdeuropaはCIDOC-CRM(文化遺産のための概念参照モデル)をベースに、匂いに特化した拡張オントロジーを使用しています。 主要な概念と関係性 Source (文献) ↓ P106_is_composed_of Fragment (テキスト断片) ↓ P67_refers_to ├─ Emission (放出イベント) ←── 中心的なハブ │ ├─ F3_had_source → Object (発生源) │ └─ F1_generated → Smell (匂い) ├─ Smell (匂い) └─ Experience (体験イベント) └─ F2_perceived → Smell (匂い) 重要なポイント: Fragment は直接的にEmission、Smell、Experienceを参照 Object へはEmission経由でアクセス(Fragment → Emission → Object) Emission がObjectとSmellを因果的に接続する中心的な役割 実例で学ぶデータ構造 1810年にドイツで出版された農業書「Grundsätze der rationellen Landwirthschaft」(合理的農業の原理)を例に、データ構造を見ていきましょう。 ...

Omeka-SのMroongaSearchモジュールで日本語全文検索を実現する

Omeka-SのMroongaSearchモジュールで日本語全文検索を実現する

はじめに Omeka-Sは強力なデジタルアーカイブシステムですが、デフォルトでは日本語の全文検索がほとんど機能しません 。本記事では、MroongaSearchモジュールを導入することで、日本語全文検索を実現する方法を解説します。 重要:なぜMroongaSearchモジュールが必要なのか Omeka-Sの標準検索の問題点 Omeka-Sの標準フルテキスト検索(FullTextSearchモジュール)は、InnoDBエンジンを使用しており、以下の致命的な問題があります: 日本語単語検索の例 : データ: 「東京大学で人工知能を研究する」 検索語: 「人工知能」 結果: ❌ ヒットしない InnoDBのフルテキスト検索は英語のようなスペース区切り言語を前提としているため、日本語では: 単語検索が不可能 : 文字列全体が1つの単語として扱われる 部分一致も機能しない : FULLTEXTインデックスが日本語を正しく処理できない 検索結果がゼロ : ユーザーは何も見つけられない MroongaSearchモジュールの解決策 MroongaSearchモジュール は、この問題を2段階で解決します: 1. フォールバック機能(モジュール導入直後から有効) 重要 : MroongaSearchモジュールをインストールするだけで、特別な設定なし で日本語検索が動作するようになります。 データ: 「東京大学で人工知能を研究する」 検索語: 「人工知能」 【MroongaSearchモジュールなし】 → ❌ 結果ゼロ 【MroongaSearchモジュールあり(Mroonga未設定でも)】 → ✅ LIKE '%人工知能%' にフォールバック → ✅ 検索結果が返る! MroongaSearchモジュールのフォールバック機能 : CJK(日本語・中国語・韓国語)の単一語検索を自動検出 LIKE '%term%' 検索に自動的にフォールバック Mroongaが設定されていなくても動作する これがないと、日本語全文検索がそもそもうまくいかない 2. Mroonga+TokenMecabによる高速・高精度検索(推奨) さらに、MariaDBにMroongaプラグインを設定すると: ✅ 形態素解析による精密な単語検索 ✅ 高速な全文検索(LIKEの数百倍高速) ✅ AND/OR検索の厳密な制御 MroongaSearchモジュールとは MroongaSearchは、Omeka-S用の全文検索強化モジュールです。 ...

Azure OpenAI GPT-4 vs Document Intelligence: 日本語縦書きOCRの比較検証

Azure OpenAI GPT-4 vs Document Intelligence: 日本語縦書きOCRの比較検証

概要 Microsoft Azureが提供する2つのOCRサービス(Azure OpenAI GPT-4 VisionとAzure Document Intelligence)を使用して、日本語の縦書き原稿用紙のOCR処理を実施し、その結果を詳細に比較検証しました。 検証対象画像 画像ソース : Canvaテンプレート(400字詰め原稿用紙) URL : https://www.canva.com/ja_jp/templates/EAFbqUoH7P8/ 画像の特徴 : 20×20の400字詰め原稿用紙 縦書きレイアウト 薄いグリッド線(マス目) タイトル欄と本文欄の区別 正解データ(Ground Truth) 原稿のタイトル 佐藤ちあき 原稿用紙に書くテキストが入ります。作文や小論文を作ったり、小説を書いたりなどにご活用ください。 このテキストを使用する場合は、日本語の全角を使うことでマスにあった文字を打つことができます。手書きで使用したい場合は、このテキストを削除し、印刷してご使用ください。 1. Azure OpenAI GPT-4.1 による認識結果 認識されたテキスト 原稿のタイトル 佐藤 ちあき 原稿用紙に書くテキストが入ります。作文や小論文を作ったり、小説を書いたりなどにご活用ください。 このテキストを使用する場合は、日本語の全角を使うことでマスにあった文字を打つことができます。手書きで使用したい場合は、このテキストを削除し、印刷してご使用ください。 評価 GPT-4.1は縦書きの原稿用紙に対して以下の特徴を示しました: ✅ タイトルと著者名の順序を正しく認識 ✅ 本文の開始部分を正確に認識 ✅ 原稿用紙のマス目に関する記述を認識 ✅ 縦書きの読み順(右から左)を完璧に理解 ✅ 文章の連続性を保持 正解データとの差異 「佐藤ちあき」→「佐藤 ちあき」(全角スペースが追加) これは画像上でスペースがあるように見えるための合理的な解釈 その他のテキストは完全に一致 精度評価: 99% 2. Azure Document Intelligence による認識結果 認識された領域の可視化 評価 Document Intelligenceは以下の特徴を示しました: ✅ 文字認識能力 - 個々の文字は正確に認識(「佐藤」「ちあき」「原稿」等) ⚠️ 文章の断片化 - マス目ごとに独立した要素として処理され、連続性が失われる ❌ 縦書き読み順の課題 - 縦書きの右から左への流れを適切に処理できない ⚠️ 後処理が必要 - 座標情報を使った再構成により、ある程度の復元は可能 ✅ 座標情報の詳細取得 - 各文字の正確な位置情報は完璧に取得 精度評価: 文字認識精度は約80%、ただし縦書きレイアウトの理解に課題あり ...

LLMによる原稿用紙OCR性能比較:縦書き日本語の認識精度検証

LLMによる原稿用紙OCR性能比較:縦書き日本語の認識精度検証

はじめに 本記事では、実際の原稿用紙画像を用いて 主要LLMモデルのOCR性能を比較検証しました。多くのOCRベンチマークが印刷文書や横書きテキストを対象とする中、日本独自の縦書き原稿用紙という特殊なフォーマット での認識精度を評価することで、各モデルの日本語文書理解能力をより実践的に検証しています。 本検証の特徴 原稿用紙という日本固有のフォーマットを使用 :マス目に収められた文字、縦書きレイアウト、特有の余白構成など、複雑な要素を含む画像での検証 実用シーンを想定 :作文、小説、論文など、実際の執筆場面で使用される原稿用紙での性能評価 最新モデルの網羅的比較 :GPT-5、GPT-4.1、Gemini 2.5 Pro、Claude Opus 4.1、Claude Sonnet 4という最新モデルを同一条件で比較 検証概要 使用画像 画像ソース : Canvaテンプレート(400字詰め原稿用紙) URL : https://www.canva.com/ja_jp/templates/EAFbqUoH7P8/ 画像の特徴 : 20×20の400字詰め原稿用紙 縦書きレイアウト 薄いグリッド線(マス目) タイトル欄と本文欄の区別 検証条件 使用プロンプト : 「OCRして」(全モデル共通) パラメータ : 各モデルのデフォルト設定 実行時期 : 2025年9月 正解テキスト 原稿のタイトル 佐藤 ちあき 原稿用紙に書くテキストが入ります。作文や小論文を作ったり、小説を書いたりなどにご活用ください。 このテキストを使用する場合は、日本語の全角を使うことでマスにあった文字を打つことができます。手書きで使用したい場合は、このテキストを削除し、印刷してご使用ください。 評価方法 本記事の精度スコアは、文字認識の正確性、レイアウト理解、文章構造の保持などを総合的に評価した主観的なスコア です。実用的な観点から、各モデルの強みと課題を分かりやすく数値化しています。 OCR結果詳細 🥇 Gemini 2.5 Pro - 精度スコア: 98/100 原稿のタイトル 佐藤ちあき 原稿用紙に書くテキストが入ります。作文や小論文を作ったり、小説を書いたりなどにご活用ください。 このテキストを使用する場合は、日本語の全角を使うことでマスにあった文字を打つことができます。手書きで使用したい場合は、このテキストを削除し、印刷してご使用ください。 評価ポイント : ✅ 文字認識: ほぼ完璧 ⚠️ 著者名のスペース欠落 ✅ 段落構成: 適切な2段落構成 ✅ レイアウト保持: 優秀 🥈 GPT-5 - 精度スコア: 97/100 原稿のタイトル 佐藤 ちあき 原稿用紙に書くテキストが入ります。作文や小論文を作ったり、小説を書いたりなどにご活用ください。このテキストを使用する場合は、日本語の全角を使うことでマスにあった文字を打つことができます。手書きで使用したい場合は、このテキストを削除し、印刷してご使用ください。 評価ポイント : ...

PDFの透明テキスト抽出における順序保持の課題と解決策

PDFの透明テキスト抽出における順序保持の課題と解決策

はじめに PDFファイルから透明テキストレイヤーを抽出する際、「テキストの順序が元のPDFと異なってしまう」という問題に直面しました。本記事では、この問題の原因と、JavaScriptとPythonそれぞれでの解決策について解説します。誤っている点もあるかもしれませんが、参考になりましたら幸いです。 PDFの透明テキストとは PDFの透明テキストレイヤーは、PDFファイル内に埋め込まれた検索可能なテキスト情報です。OCR処理されたPDFや、デジタル生成されたPDFには、この透明テキストレイヤーが含まれており、以下のような機能を実現しています: テキスト検索 コピー&ペースト スクリーンリーダーによる読み上げ 機械翻訳 問題:テキストの順序が乱れる理由 PDFの内部構造 PDFファイルは、テキストを「コンテンツストリーム」という形式で保存しています。このストリームには、テキストとその位置情報が含まれていますが、必ずしも読む順序で格納されているわけではありません。 例:PDFコンテンツストリームの概念図 [位置: x=100, y=200, テキスト="見出し"] [位置: x=300, y=400, テキスト="脚注"] [位置: x=100, y=300, テキスト="本文"] 一般的な抽出方法の問題点 多くのPDF処理ライブラリは、以下のような手順でテキストを抽出します: コンテンツストリームからテキストと位置情報を取得 座標でソート (上から下、左から右) ソート結果を出力 この「座標でソート」する処理が、テキスト順序の乱れを引き起こす主な原因です。 具体的な問題例 縦書きと横書きの混在 :日本語文書でよく見られる 複数カラムレイアウト :新聞や雑誌形式 図表の挿入 :本文の流れを分断する要素 ヘッダー・フッター :ページをまたぐ要素 解決策:言語別アプローチ JavaScript (PDF.js) での解決策 PDF.jsは、Mozillaが開発したJavaScriptベースのPDFレンダリングライブラリです。 順序を保持する実装 // PDF.jsを使用した順序保持テキスト抽出 async function extractTextWithOrder(page) { // getTextContent()はコンテンツストリームの順序を維持 const textContent = await page.getTextContent(); // itemsは元の順序を保持した配列 const orderedText = textContent.items.map(item => { return { text: item.str, x: item.transform[4], y: item.transform[5], width: item.width, height: item.height }; }); // 配列の順序をそのまま使用(座標ソートしない) return orderedText; } ポイント getTextContent()メソッドは、PDFの内部構造に忠実な順序でテキストを返す 配列のインデックスが元の順序を表現 座標による再ソートを行わない Python (PyMuPDF) での解決策 PyMuPDF(fitz)は、MuPDFライブラリのPythonバインディングです。 ...

TEI/XMLファイルをGitHubで公開する手順書

TEI/XMLファイルをGitHubで公開する手順書

はじめに この記事では、TEI(Text Encoding Initiative)形式のXMLファイルをGitHubにアップロードし、誰でも参照できるURLを作成する手順を説明します。 TEI/XMLは、歴史文献や文学作品などのテキストを構造的に記述するための国際標準形式です。GitHubを使うことで、あなたの研究データを世界中の研究者と共有できるようになります。 必要なもの パソコン(Windows、Mac、Linuxのいずれか) インターネット接続 TEI/XMLファイル(すでにお持ちのもの) メールアドレス(GitHubアカウント作成用) サンプルファイルについて TEI/XMLファイルをお持ちでない方は、以下の『校異源氏物語』のTEI/XMLファイルを練習用として使用できます: サンプルファイルURL : https://raw.githubusercontent.com/kouigenjimonogatari/kouigenjimonogatari.github.io/master/tei/01.xml このファイルをダウンロードする方法: 上記URLをブラウザで開く 右クリック→「名前を付けて保存」を選択 ファイル名を「koukin_genji_01.xml」などに設定して保存 ステップ1:GitHubアカウントの作成 1-1. GitHubのウェブサイトにアクセス ブラウザ(Chrome、Firefox、Safari等)を開きます アドレスバーに https://github.com と入力してEnterキーを押します 1-2. アカウント作成 右上の「Sign up」ボタンをクリックします 以下の情報を入力します: メールアドレス :普段お使いのメールアドレス パスワード :安全なパスワード(8文字以上、数字と記号を含む) ユーザー名 :他の人と重複しない名前(例:yamada-taro2024) 「Create account」をクリックします メールに届いた認証コードを入力します 💡 ヒント : ユーザー名は後から変更できないので、慎重に選びましょう。研究者として使う場合は、実名に基づいた名前がおすすめです。 ステップ2:新しいリポジトリの作成 リポジトリとは、ファイルを保管する「プロジェクトフォルダ」のようなものです。 2-1. リポジトリ作成画面へ GitHubにログインした状態で、右上の「+」マークをクリックします 「New repository」を選択します 2-2. リポジトリの設定 以下の項目を入力・選択します: Repository name(リポジトリ名) 英数字とハイフン(-)が使えます 例:tei-xml-collection、medieval-texts-tei Description(説明)※任意 プロジェクトの簡単な説明 例:「中世文献のTEI/XMLファイル集」 Public/Private(公開設定) Public を選択:誰でも閲覧可能(推奨) Private:招待した人のみ閲覧可能 Initialize this repository with:(初期化オプション) ✅ Add a README file にチェックを入れる その他はそのままで大丈夫です 緑色の「Create repository」ボタンをクリックします ステップ3:TEI/XMLファイルのアップロード 3-1. アップロード画面へ リポジトリが作成されると、ファイル一覧画面が表示されます 「Add file」ボタンをクリックします 「Upload files」を選択します 3-2. ファイルのアップロード 方法A:ドラッグ&ドロップ エクスプローラー(Windows)またはFinder(Mac)でTEI/XMLファイルがある場所を開きます アップロードしたいファイルを選択します(複数選択可) ブラウザの点線枠内にドラッグ&ドロップします 方法B:ファイル選択 「choose your files」をクリックします ファイル選択ダイアログでTEI/XMLファイルを選択します 「開く」をクリックします 実例:『校異源氏物語』のTEI/XMLファイルをアップロード サンプルファイルを使った具体例: ...

TEI ODDファイルのカスタマイゼーション:NDL古典籍OCRの事例

TEI ODDファイルのカスタマイゼーション:NDL古典籍OCRの事例

はじめに TEI (Text Encoding Initiative) は、人文学研究におけるテキストのデジタル化と共有のための国際標準です。本記事では、NDL古典籍OCR-Liteアプリケーションの出力形式に合わせてTEI ODDファイルをカスタマイズした過程を紹介します。 ODD (One Document Does it all) は、TEIスキーマをカスタマイズするための仕組みで、必要な要素と属性だけを含む独自のスキーマを定義できます。 背景:NDL古典籍OCR-Liteアプリケーションの開発 NDL古典籍OCR-Liteの出力結果をTEI/XMLで出力するアプリケーションを作成しています。このアプリケーションは、日本の古典籍をOCR処理し、その結果を標準的なTEI形式で出力することを目的としています。 出力されるTEI XMLには以下の情報を含めることにしました: テキスト情報 : OCRで認識した文字列 レイアウト情報 : 各行の座標情報(バウンディングボックス) 画像参照 : IIIF (International Image Interoperability Framework) 対応の画像URL メタデータ : 文書タイトル、処理情報など このアプリケーションで使用するスキーマをODDで記述してみました。以下、そのカスタマイゼーション過程を紹介します。 カスタマイゼーションのアプローチ 1. 初期アプローチ:標準モジュールの利用 最初は、TEIの標準モジュールを利用してODDを作成しました: schemaSpec ident="ndl_koten_ocr" start="TEI" prefix="tei_"> moduleRef key="tei"/> moduleRef key="header" include="teiHeader fileDesc titleStmt publicationStmt sourceDesc"/> moduleRef key="core" include="p title name resp respStmt lb pb graphic"/> moduleRef key="textstructure" include="TEI text body"/> moduleRef key="transcr" include="facsimile surface zone"/> schemaSpec> include属性の重要性 moduleRef要素のinclude属性は、モジュールから特定の要素のみを選択的に含める重要な機能です: ...

TEI GarageのAPIを使用したODDからRNG/HTMLへの変換

TEI GarageのAPIを使用したODDからRNG/HTMLへの変換

はじめに TEI(Text Encoding Initiative)のODD(One Document Does it all)ファイルから、スキーマ(RNG)やドキュメント(HTML)を生成する作業は、TEIプロジェクトにおいて重要な工程です。本記事では、Roma(TEIのODDエディタ)が内部で使用しているTEI Garage APIの仕組みを解析し、スクリプトから直接APIを呼び出してODDを変換する方法を紹介します。 TEI Garageとは TEI Garageは、TEIコミュニティが提供するWebサービスで、様々なフォーマット間の変換を行うことができます。特にODDファイルの処理において、以下の機能を提供しています: ODD → Compiled ODD への変換 Compiled ODD → RELAX NG スキーマへの変換 ODD → HTML ドキュメントへの変換 その他多数のフォーマット変換 Romaの内部動作を解析 Romaのネットワークトラフィックを観察すると、以下のような変換チェーンを使用していることがわかりました: HTMLドキュメント生成の場合 ODD → ODDC (Compiled ODD) → TEI → xHTML 実際のAPIエンドポイント: https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/TEI%3Atext%3Axml/xhtml%3Aapplication%3Axhtml%2Bxml/conversion RNGスキーマ生成の場合 ODD → ODDC (Compiled ODD) → RELAXNG 実際のAPIエンドポイント: https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/relaxng%3Aapplication%3Axml-relaxng/conversion 変換パラメータの詳細 Romaは変換時に以下のようなXML形式のプロパティを送信しています: conversions> conversion index="0"> property id="oxgarage.getImages">falseproperty> property id="oxgarage.getOnlineImages">falseproperty> property id="oxgarage.lang">japroperty> property id="oxgarage.textOnly">falseproperty> property id="pl.psnc.dl.ege.tei.profileNames">defaultproperty> conversion> conversion index="1"> property id="oxgarage.getImages">falseproperty> property id="oxgarage.getOnlineImages">falseproperty> property id="oxgarage.lang">japroperty> property id="oxgarage.textOnly">trueproperty> property id="pl.psnc.dl.ege.tei.profileNames">defaultproperty> conversion> conversions> 各プロパティの意味: ...

NDL古典籍OCR-lite Next.js版の開発

NDL古典籍OCR-lite Next.js版の開発

概要 @yuta1984 さんが「WebAssemblyを使用したNDL古典籍OCR-liteのWeb移植版」を開発されました。 https://github.com/yuta1984/ndlkotenocr-lite-web 今回は、上記のリポジトリを参考にさせていただき、Next.js版を作成しました。 https://nkol.vercel.app/ja/ 加えて、以下の点を追加しています。 IIIFマニフェストファイルの入力フォーム TEI/XMLファイルのダウンロード機能 出力フォーマットに関するODDファイルの作成 使い方 サンプルとして、九州大学附属図書館の源氏物語を利用させていただきます。 https://catalog.lib.kyushu-u.ac.jp/image/manifest/1/820/411193.json マニフェストファイルを入力し、「読み込む」ボタンを押すと、以下のように、画像の一覧が表示されます。 なお、内部的には、@iiif/parserを利用し、v2とv3、どちらのマニフェストファイルにも対応するようにしています。 その後、処理の実行ボタンを押すと、画像ごとにOCR結果のテキストが表示されます。 実行完了後、画面下部に結果のダウンロードボタンが表示されます。 ODDファイルの作成 TEI/XMLでのエクスポートにあたり、どのようなタグや形式が想定されているのか、という質問をいただくことがありました。 そこで、このフォーマットの共有にあたり、ODD(One Document Does it all)ファイルを作成しました。 このODDファイルの作成については、以下の記事も参考にしてください。 さらに、TEIGarageのAPIを利用し、RNGファイルやHTMLファイルを作成しています。この変換については、以下の記事を参考にしてください。 不完全な部分もありますが、このような方法を採ることで、TEIのエコシステムを活用しながら、スキーマを公開・共有することができそうです。 これまでに作成したツールと今後開発予定のツール これまでの開発 NDL古典籍OCR-liteについては、これまでにいくつかのツールを開発してきました。 まず、Gradio Appを作成しました。こちらは公式に提供されている「デスクトップアプリケーション」で代替可能なものでしたが、スマホやタブレットで撮影した画像に対してOCRをかけるといった用途では有用性があると考えられます。 次に、以下の記事で紹介したように、同じくGradioを用いたウェブアプリですが、IIIFマニフェストファイルを入力とし、TEI/XMLファイルを出力とするアプリを作成しました。IIIFとTEIを接続している点で有用性はありましたが、Hugging Faceの無料枠でアプリを公開しているため、多くの人が同時に使用できる環境ではないという課題がありました。 これらの課題に対して、@yuta1984 さんが作成されたウェブ版を参考に、IIIFとTEIの接続機能を維持しながら、ユーザの端末側でOCR処理を実行する環境を今回構築しました。これにより、複数人が同時に処理を実行できるようになりました。 今後の展望 人手でOCRをかける際には、公式のデスクトップアプリケーションを使用するか、@yuta1984 さんのウェブアプリ、あるいは今回開発したNext.js版のウェブアプリを使用することで、多くのニーズに対応できると考えています。 今後の取り組みとして、API等を介して大量の画像に対して一括でOCR処理を行う場合には、複数のサーバで並列にOCR処理を実行することで効率化を図ることができます。例えば、2000枚を超える画像から構成されるIIIFマニフェストファイルを対象とする際には、並列でOCR処理を行うことが、順次実行するよりも効果的です。 このような処理を実現するため、以下の記事で紹介しているように、Azure Container Appsを使用したスケーラブルなOCR処理システムの構築を進めています。 まだ不完全な点や考慮すべき点は多いものの、サーバレスな環境でOCRを提供することで、大規模な画像に対するOCR処理の実現を目指しています。 まとめ NDL古典籍OCR-liteの活用にあたり、参考になりましたら幸いです。

Azure Container AppsでNDL古典籍OCR Liteを用いたスケーラブルOCR処理システム

Azure Container AppsでNDL古典籍OCR Liteを用いたスケーラブルOCR処理システム

⚠️ 重要な利用上の注意 本記事で紹介するシステムは、外部サーバーに負荷をかける可能性があります。利用時は十分ご注意ください。 サーバー負荷 : 並列リクエストは対象サーバーに負荷を与えます DoS攻撃のリスク : 大量の同時アクセスはDoS攻撃と誤解される可能性があります 推奨アプローチ : 事前に画像をローカルにダウンロードし、OCR処理のみを並列実行することを推奨します 利用規約の確認 : 対象サーバーの利用規約を必ず確認し、必要に応じて事前許可を取得してください 適切なレート制限 : 実運用では慎重な並列数設定(5-10並列程度)を強く推奨します 責任ある利用 : サーバー管理者や他の利用者への配慮を忘れずに 本記事は技術的な実証実験の記録です。読者の皆様には責任を持った利用をお願いします。 はじめに 本記事では、国立国会図書館(NDL)が開発したNDL古典籍OCR Liteを活用し、Azure Container AppsでスケーラブルなOCR処理システムを構築した事例を紹介します。クラウドネイティブなアーキテクチャにより、従量課金とオートスケーリングを実現したシステムの設計と実装について解説します。 システム概要 アーキテクチャ IIIF画像 → Azure Container Apps → NDL古典籍OCR → TEI XML出力 ↓ オートスケーリング (0-30レプリカ) 主要コンポーネント OCRエンジン : NDL古典籍OCR Lite(日本古典籍特化) インフラ : Azure Container Apps(サーバーレスコンテナ) API設計 : REST API(画像URL → OCR結果) 出力形式 : TEI P5準拠XML スケーリング : 需要に応じた自動スケーリング NDL古典籍OCR Liteの特徴 日本古典籍に最適化されたOCR 縦書きレイアウト対応 : 古典籍特有の縦書き文書構造 読み順序最適化 : 右から左、上から下の日本語読み順 古典文字認識 : くずし字や変体仮名への対応 軽量実装 : Docker化によりクラウドデプロイ対応 Azure Container Appsの選択理由 サーバーレスコンテナの利点 # スケーリング設定例 scale: minReplicas: 0 # アイドル時: コスト0 maxReplicas: 30 # 需要時: 自動拡張 cooldownPeriod: 300 # 5分でスケールダウン コスト最適化 従量課金 : 使用した分のみ課金 0レプリカ : アイドル時は完全にコスト0 自動スケーリング : 需要に応じたリソース調整 システム実装 サーバーサイド実装 # Flask + NDL OCR統合 from flask import Flask, request, jsonify from flask_restx import Api, Resource from simple_ocr_service import OCRService app = Flask(__name__) api = Api(app, doc='/docs/') @api.route('/api/image') class ImageOCR(Resource): def get(self): image_url = request.args.get('image_url') # NDL OCRで画像処理 result = ocr_service.process_single_image(image_url) return result 読み順序アルゴリズム def sort_japanese_reading_order(lines): """日本古典籍の読み順序ソート""" return sorted(lines, key=lambda line: ( -line["bbox"][0], # x座標降順(右→左) line["bbox"][1] # y座標昇順(上→下) )) TEI XML出力 xml version="1.0" encoding="UTF-8"?> TEI xmlns="http://www.tei-c.org/ns/1.0"> teiHeader> fileDesc> titleStmt> title>桐壺title> titleStmt> respStmt> resp>Automated Transcriptionresp> name ref="https://github.com/ndl-lab/ndlkotenocr-lite"> NDL古典籍OCR Lite name> respStmt> fileDesc> teiHeader> facsimile> surface xml:id="surface-1"> zone xml:id="zone-1-1" ulx="3391" uly="1141" lrx="3727" lry="2924" cert="0.799"/> surface> facsimile> text> body> div type="transcription"> pb n="1" facs="#surface-1"/> lb n="1.1" corresp="#zone-1-1" cert="high"/> いづれの御時にか div> body> text> TEI> 処理結果事例 小規模テスト処理(桐壺) 対象 : 東京大学所蔵「桐壺」 ページ数 : 32ページ 処理時間 : 約30秒 成功率 : 100% 並列数 : 10並列 コスト : 約$0.05 パフォーマンス特性 処理時間 = 約1秒/ページ(並列処理時) コスト効率 = $1.5〜2.0/1000ページ スケーリング = 数秒で0→20レプリカ システムの技術的特徴 1. コールドスタート対応 async def process_with_retry(image_url, max_retries=3): """コールドスタート時の自動リトライ""" for attempt in range(max_retries + 1): try: if attempt > 0: wait_time = 2 ** (attempt - 1) await asyncio.sleep(wait_time) return await ocr_request(image_url) except (HTTPError, TimeoutError) as e: if attempt == max_retries: raise e 2. 設定の外部化 # 環境変数による設定 OCR_API_URL=https://your-ocr-service.azurecontainerapps.io DEFAULT_MAX_CONCURRENT=10 DEFAULT_CONFIDENCE_THRESHOLD=0.3 DEFAULT_OUTPUT_FORMAT=xml 3. Swagger UI統合 # API仕様の自動生成 api = Api(app, version='1.0', title='NDL古典籍OCR API', description='日本古典籍専用OCR処理API', doc='/docs/' ) デプロイメント Azure Container Appsデプロイ # コンテナアプリ作成 az containerapp create \ --name ocr-service \ --resource-group rg-ocr \ --environment container-env \ --image registry.azurecr.io/ocr-app:latest \ --target-port 80 \ --ingress external \ --min-replicas 0 \ --max-replicas 30 \ --cpu 2.0 \ --memory 4Gi Docker化 FROM python:3.11-slim # NDL OCRモデル配置 COPY model/ /app/model/ COPY config/ /app/config/ # アプリケーション設定 WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . EXPOSE 80 CMD ["gunicorn", "--bind", "0.0.0.0:80", "app:app"] 運用とモニタリング パフォーマンスメトリクス レスポンス時間 : 平均2-3秒/画像 スループット : 10-15画像/秒(20レプリカ時) 成功率 : 99%以上 コスト効率 : アイドル時$0、処理時のみ課金 ログ監視 # Container Appsログ確認 az containerapp logs show \ --name ocr-service \ --resource-group rg-ocr \ --follow 今後の展望 技術的改善点 画像キャッシュ : 重複処理の削減 バッチ処理 : 効率的な大量処理 GPU対応 : OCR処理の高速化 メトリクス強化 : 詳細な性能分析 応用可能性 デジタルアーカイブ : 図書館・博物館での活用 研究支援 : 人文学研究のデジタル化 教育分野 : 古典文献の教材化 文化保存 : 貴重資料のデジタル保存 まとめ NDL古典籍OCR LiteとAzure Container Appsを組み合わせることで、コスト効率とスケーラビリティを両立した古典籍OCRシステムを構築できました。サーバーレスアーキテクチャにより、従量課金と自動スケーリングを実現し、実用的なデジタルヒューマニティーズツールとして活用可能です。 ...

Omeka Sのテーマ更新とモジュール改修

Omeka Sのテーマ更新とモジュール改修

概要 以下のワークショップにおいて、Omeka Sの扱う機会がありました。今回は、本演習で参加者の方々からいただいたフィードバックに基づき、テーマやモジュールに加えた修正を紹介します。 https://dh.nihu.jp/news/post/dihuco_20250724 Universal Viewerモジュール Universal Viewerモジュールは、Omeka SにUniversal Viewerを導入するモジュールです。 https://gitlab.com/Daniel-KM/Omeka-S-module-UniversalViewer 本モジュールが提供する機能の一つとして、以下のようにアイテム一覧ページにUniversal Viewerを表示する機能があります。 ただ、この表示において、メディアが紐づいていないアイテムがあると、IIIFマニフェストファイル or IIIFコレクションファイルの作成に不具合が生じ、都度アラートが表示される事象が発生しました。 そこで、以下の機能修正を行い、プルリクエストを送りました。 https://gitlab.com/Daniel-KM/Omeka-S-module-UniversalViewer/-/merge_requests/3 実装した機能としては、以下のようなサイトごとの設定画面において、 http://localhost/admin/site/s/aaa#site-settings アイテムの一覧画面にUVを表示するか否かを設定できるオプションを追加しました。 結果、本設定をOFFにすると、以下のように、アイテム一覧画面にUVが表示されなくなります。 同様に、日本語訳を適用済みです。 Bootstrap5を用いたOmeka Sのテーマ 背景 Omeka Sのv.4系に合わせて、以下のテーマを作成しています。 https://github.com/nakamura196/Omeka-S-theme-Bootstrap5 以下は、もともとOmeka Sのv.3系向けに作成していたので、生成AIの力を借りて作り直しました。 https://github.com/ldasjp8/Omeka-S-theme-Bootstrap5 本テーマについての詳細は、別の記事で紹介したいと思います。 変更内容 変更前 変更後 本テーマでは、元々は上記の変更前 のように、正方形にクロップされたサムネイル画像を使用していました。 ただ、この設定の場合、ユーザが表示したい箇所をうまく表示できないことがありました。そこで、変更後 のような表示を可能にするためのオプションを追加しました。 具体的には、以下のように、テーマの設定画面に「サムネイル表示モード」を追加しました。 なお、この変更に用いたコミットは以下です。 https://github.com/nakamura196/Omeka-S-theme-Bootstrap5/commit/cc4ef7025950c90e2753d34d0ed52e81b782fac3 まとめ Omeka Sのテーマやモジュールなど、利用者のフィードバックに基づく改善や日本語環境への適用に向けて、引き続き改修を加えていく予定です。

Omeka SにPROV-Oオントロジーを登録する方法

Omeka SにPROV-Oオントロジーを登録する方法

はじめに Omeka Sでデジタルアーカイブを構築する際、メタデータの記述に標準的な語彙を使用することで、データの相互運用性が向上します。今回は、W3Cが策定したPROV-O(PROV Ontology)をOmeka Sに登録する手順を解説します。 PROV-Oは、データやデジタルオブジェクトの来歴(プロヴェナンス)情報を記述するためのオントロジーで、「誰が」「いつ」「どのように」データを作成・変更したかを構造化して記録できます。 前提条件 Omeka S(バージョン3.0以降)がインストール済み 管理者権限でログイン可能 インターネット接続環境(外部URLからのインポートに必要) 登録手順 1. 語彙管理画面へのアクセス Omeka S管理画面にログイン 左側メニューから「語彙の一覧」をクリック 右上の「新しい語彙を追加」ボタンをクリック 2. 基本情報の入力 語彙の基本情報を以下のように入力します: 項目 入力値 ラベル PROV-Oオントロジー コメント W3C PROV-O (PROV Ontology) - データの来歴情報を記述するための標準オントロジー 名前空間URI http://www.w3.org/ns/prov# 名前空間の接頭語 prov 重要 : 名前空間URIの末尾に#(ハッシュ)が必要です。これを忘れるとプロパティが正しく認識されません。 3. ファイルのインポート設定 Import typeの選択 「URL」を選択します(デフォルトで選択されているはずです)。 File URLの入力 以下のURLを入力します: https://www.w3.org/ns/prov-o このURLは内容交渉(Content Negotiation)に対応しており、Omeka Sが自動的に適切な形式(Turtle)で取得します。 ファイルフォーマット 「Turtle (.ttl)」が自動的に選択されます。変更の必要はありません。 4. 登録の実行 入力内容を確認 「インポート」ボタンをクリック 処理が完了するまで待機(数秒〜数十秒) 5. 登録の確認 登録が完了すると、語彙一覧にPROV-Oオントロジーが表示されます。 クリックして詳細を確認すると、以下のようなクラスとプロパティが登録されているはずです: 主要なクラス: prov:Entity - エンティティ(物や概念) prov:Activity - アクティビティ(プロセスや行為) prov:Agent - エージェント(人、組織、ソフトウェア) 主要なプロパティ: ...

画像コレクション管理ツール 技術アーキテクチャ解説

画像コレクション管理ツール 技術アーキテクチャ解説

概要 以下の記事で、IIIFの機能を簡単に試すことを目的とした「画像コレクション管理」ツールについて紹介しました。 https://zenn.dev/nakamura196/articles/7d6bb4cdc414c4 今回は、このツールの裏側で使われている技術について紹介します。 はじめに 画像コレクション管理ツールは、画像コレクションを国際標準規格であるIIIF(International Image Interoperability Framework)形式で管理・公開するためのWebアプリケーションです。本記事では、このツールの技術的な実装について、特にIIIF仕様の実装と地理空間情報の扱いに焦点を当てて解説します。 技術スタック フロントエンド : Next.js 14 (App Router), React, TypeScript バックエンド : Next.js API Routes データストレージ : AWS S3互換オブジェクトストレージ(Cloudflare R2) 認証 : NextAuth.js 地図表示 : Leaflet, MapLibre GL JS IIIF ビューア : Mirador 3, OpenSeadragon IIIF実装の詳細 1. IIIF Presentation API v2/v3の両方をサポート 本ツールは、IIIF Presentation APIのバージョン2とバージョン3の両方に対応しています。これにより、様々なIIIFビューアとの互換性を確保しています。 v2とv3の主な違い // IIIF v2の構造 { "@context": "http://iiif.io/api/presentation/2/context.json", "@id": "https://example.com/manifest", "@type": "sc:Manifest", "label": "タイトル", "sequences": [{ "@type": "sc:Sequence", "canvases": [...] }] } // IIIF v3の構造 { "@context": "http://iiif.io/api/presentation/3/context.json", "id": "https://example.com/manifest", "type": "Manifest", "label": { "ja": ["タイトル"] }, "items": [...] // canvasの配列 } 2. マルチ言語対応 v3では、ラベルや説明文を言語別に管理できます: ...

「画像コレクション管理」ツールの使い方ガイド

「画像コレクション管理」ツールの使い方ガイド

概要 IIIFの機能を簡単に試すことを目的とした、「画像コレクション管理」ツールを作成しました。 https://pocket.webcatplus.jp https://pocket.webcatplus.jp/ 本ツールの使い方について紹介します。 コレクション管理 コレクションの作成 ダッシュボードで「新規コレクション」ボタンをクリック 必要情報を入力: コレクション名 (必須): わかりやすい名前を付ける 説明 (任意): コレクションの内容を説明 公開設定 : 公開/非公開を選択 「作成」をクリック コレクションの編集 コレクション一覧から編集したいコレクションの「⋮」メニューをクリック 「編集」を選択 情報を更新して「保存」 コレクションの削除 コレクション一覧から削除したいコレクションの「⋮」メニューをクリック 「削除」を選択 確認ダイアログで「削除」をクリック ⚠️ 注意 : コレクションを削除すると、含まれるすべてのアイテムも削除されます アイテム(画像)管理 アイテムの追加 方法1: ドラッグ&ドロップ コレクションページを開く 「新規アイテム」ボタンをクリック 画像ファイルをドラッグ&ドロップエリアにドロップ タイトルと説明を入力 「作成して編集」をクリック 方法2: ファイル選択 「ファイルを選択」ボタンをクリック アップロードしたい画像を選択(複数選択可) タイトルと説明を入力 「作成して編集」をクリック 方法3: URLから追加 「URLから追加」タブを選択 画像のURLを入力 「追加」をクリック 方法4: IIIF画像の追加 「info.jsonから追加」タブを選択 IIIF info.jsonのURLを入力 「追加」をクリック アイテムの編集 アイテム一覧から編集したいアイテムをクリック 編集画面で以下の情報を更新: 基本情報 : タイトル、説明、公開設定 位置情報 : 緯度、経度、場所の名前 詳細情報 : 帰属表示、権利情報 追加情報 : カスタムフィールド(作成年、作者など) 「保存」をクリック ...

IIIF Georeference ViewerのMapLibre GL移行と機能改善

IIIF Georeference ViewerのMapLibre GL移行と機能改善

本記事はAIが作成し、人間が追記しました。 概要 IIIF Georeference ViewerにおけるマップコンポーネントをLeafletからMapLibre GLへ移行し、複数の機能改善を実施しました。本記事では、実装した主要な機能とその技術的詳細について説明します。 https://nakamura196.github.io/iiif_geo/ 主要な改善点 1. 画像の自動回転機能 IIIF画像を地図上に正しい向きで表示するため、コントロールポイント(対応点)から自動的に回転角度を計算する機能を実装しました。 機能概要 画像座標と地理座標の対応点から、画像を北が上になるように回転させる角度を自動計算 2点間または3点以上の分布パターンから最適な回転角度を決定 URLパラメータによる回転角度の保存と復元 実装のポイント // utils/calculateImageRotation.ts export function calculateImageRotation(features: Feature[]): RotationCalculationResult | null { // 最も離れた2点を見つける(より正確な角度計算のため) const validFeatures = features.filter((f) => f.properties?.resourceCoords && f.geometry?.coordinates ); // 画像座標系でのベクトルと地理座標系でのベクトルから回転角度を計算 const imgVector = { x: img2.x - img1.x, y: img2.y - img1.y }; const geoVector = { x: geo2.lng - geo1.lng, y: geo2.lat - geo1.lat }; // 北を基準とした角度の差を計算 const rotationDeg = geoAngleFromNorthDeg - imgAngleDeg; return normalizeAngle(rotationDeg); } UI実装 自動回転ボタン(🔧アイコン)をOSDビューアーに配置 rotationパラメータが未指定の場合は自動的に回転角度を計算 手動での角度調整用スライダーも提供 2. LeafletからMapLibre GLへの移行 移行の背景 パフォーマンス向上 : MapLibre GLはWebGLベースのレンダリングにより、大量のマーカー表示時のパフォーマンスが向上 スムーズなアニメーション : 地図の移動やズーム時のアニメーションがより滑らかに ベクタータイルのサポート : ラスタータイルに加えてベクタータイルの表示が可能 実装のポイント import { Map, NavigationControl, Marker, Popup } from "maplibre-gl"; import "maplibre-gl/dist/maplibre-gl.css"; const mapInstance = ref<Map | null>(null); // MapLibre GL初期化 mapInstance.value = new Map({ container: mapContainer.value!, style: mapStyles.value[0].style, center: initialCenter, zoom: zoom_.value, attributionControl: false }); 3. 現在地表示機能 ブラウザのGeolocation APIを使用して、ユーザーの現在地を地図上に表示する機能を実装しました。 ...