ホーム 記事一覧 ブック DH週間トピックス 検索 このサイトについて
English
Insta360動画ファイルからGPS情報の有無を機械的に判別する方法

Insta360動画ファイルからGPS情報の有無を機械的に判別する方法

Insta360で撮影した360度動画ファイル(.insv)にGPS情報が含まれているかどうかを、コマンドラインから機械的に確認する方法を紹介します。 背景 Insta360カメラで撮影した動画には、GPS機能が有効な場合に位置情報が埋め込まれます。しかし、撮影時の設定やGPS信号の受信状況によって、GPS情報が含まれるファイルと含まれないファイルが混在することがあります。 大量のファイルを整理する際、GPS情報の有無でファイルを分類したいケースがあります。 使用ツール exiftool を使用します。macOSの場合、Homebrewでインストールできます。 brew install exiftool ポイント:-ee オプションが必須 Insta360の.insvファイルは、GPS情報を標準的なEXIFタグではなく、MP4コンテナ内の独自トラックに埋め込んでいます。 そのため、通常のexiftoolコマンドではGPS情報を読み取れません。 # これではGPS情報が見つからない exiftool -GPSPosition video.insv # (出力なし) -ee(extractEmbedded)オプションを使用することで、埋め込まれたメタデータトラックからGPS情報を抽出できます。 # これでGPS情報が読み取れる exiftool -ee -GPSPosition video.insv # GPS Position : 26 deg 20' 37.88" N, 126 deg 49' 43.32" E 単一ファイルの確認 exiftool -ee -GPSPosition ファイル名.insv GPS情報がある場合は位置情報が出力され、ない場合は何も出力されません。 複数ファイルの一括確認 以下のシェルスクリプトで、フォルダ内のすべての.insvファイルのGPS有無を確認できます。 #!/bin/bash echo "=== GPS情報の確認 ===" echo "" for f in /path/to/folder/*.insv; do filename=$(basename "$f") gps=$(exiftool -ee -GPSPosition "$f" 2>/dev/null | grep "GPS Position" | head -1) if [ -n "$gps" ]; then echo "✓ GPS あり: $filename" echo " $gps" else echo "✗ GPS なし: $filename" fi done 実行例 === GPS情報の確認 === ✓ GPS あり: VID_20251124_102711_00_020.insv GPS Position : 26 deg 20' 30.42" N, 126 deg 52' 53.72" E ✓ GPS あり: VID_20251124_102928_00_021.insv GPS Position : 26 deg 20' 21.86" N, 126 deg 53' 12.79" E ✗ GPS なし: VID_20251124_111033_00_026.insv ✗ GPS なし: VID_20251124_111204_00_027.insv ✓ GPS あり: VID_20251124_113446_00_029.insv GPS Position : 26 deg 20' 37.88" N, 126 deg 49' 43.32" E ファイルを自動分類するスクリプト GPS情報の有無でファイルを別フォルダに分類するスクリプトです。 ...

Deep Zoom画像を完全復元:タイル画像からBigTIFFへの変換技術

Deep Zoom画像を完全復元:タイル画像からBigTIFFへの変換技術

はじめに Webサイト上で高解像度画像をスムーズにズーム表示するために使用されるDeep Zoom技術。Microsoft Deep Zoom Composerなどで生成されたタイル化された画像データから、元の高解像度画像を復元する必要に迫られることがあります。 本記事では、Deep Zoom形式で公開されている画像データから、元の高解像度TIFF画像を復元する技術について解説します。 Deep Zoom画像の仕組み タイル構造 Deep Zoom画像は、1枚の大きな画像を複数の小さなタイル画像に分割し、ピラミッド構造で保存します: レベル0 : 最も低解像度(通常1タイル) レベルN : 最高解像度(元画像の解像度に相当) 各レベルで解像度が2倍になる ファイル構成 dzc_output.xml # メタデータ dzc_output_files/ ├── 0/ │ └── 0_0.jpg # レベル0の唯一のタイル ├── 1/ │ ├── 0_0.jpg │ └── ... └── 16/ # 最高レベル ├── 0_0.jpg ├── 0_1.jpg └── ... # 数万枚のタイル 実装の課題と解決策 課題1: XMLメタデータの名前空間の違い Deep Zoomには複数のバージョンがあり、XMLの名前空間が異なります: http://schemas.microsoft.com/deepzoom/2008 http://schemas.microsoft.com/deepzoom/2009 解決策 : 複数の名前空間に対応した柔軟なXMLパーサーを実装 ...

BDRC Tibetan OCR:チベット語OCRツールの紹介と実装事例

BDRC Tibetan OCR:チベット語OCRツールの紹介と実装事例

はじめに チベット語写本のデジタル化は、デジタル人文学における重要な課題の一つです。貴重な仏教経典や歴史文書が世界中の図書館に保管されていますが、その多くはまだテキストデータ化されていません。手作業での文字起こしには膨大な時間とコストがかかり、専門知識を持つ研究者も限られています。 本記事では、BDRC Tibetan OCR を紹介します。このツールは、Buddhist Digital Resource Center (BDRC) によって開発されたオープンソースのチベット語OCRシステムです。 また、チベット語写本カンギュール114点 をデジタル化するプロジェクトでの実装事例も紹介します。 BDRC Tibetan OCRとは BDRC Tibetan OCR は、チベット語の画像からテキストを自動抽出する無料のオープンソースツールです。 主要な特徴 1. デスクトップアプリケーション Windows、macOS(Intel/M1,M2)で動作するGUIアプリケーションです。 インストール方法: リリースページから各OS用のZIPファイルをダウンロード 解凍して実行ファイルを起動するだけ 2. 複数の出力形式 プレーンテキスト : 抽出されたUnicodeチベット文字 PageXML : 座標情報付きXML(Transkribusと互換) Wylie : ローマ字転写形式 3. 画像補正機能 歪み補正(Dewarping) : ページの湾曲を補正 回転補正 : 自動的にページの傾きを検出・補正 行検出 : 行分割機能 4. バッチ処理対応 複数の画像ファイルを一括処理 PDFファイルからの直接OCR IIIF(International Image Interoperability Framework)マニフェストからの自動取得・処理 4つの専門OCRモデル BDRC Tibetan OCRの特徴の一つは、書体や資料の種類に応じて最適化された4つの専門モデル を提供している点です。 1. ウチェン(Uchen)モデル - 現代印刷用 用途: 印刷された経典、現代の出版物 データセット: 440万サンプルの統一ウチェンモデル 特徴: チベット語で最も標準的な書体 適用例: コンピューターフォントで印刷されたテキスト、木版印刷 ウチェンは「正書体」を意味し、チベット語で最も標準的な書体です。現代の印刷物やデジタルフォントで使用されます。 ...

Cesium 1.135.0におけるマーカー位置ズレ問題と解決方法

Cesium 1.135.0におけるマーカー位置ズレ問題と解決方法

問題の概要 Cesium.js 1.135.0を使用したReactアプリケーションにおいて、CLAMP_TO_GROUND設定を使用したビルボードマーカーの位置が、カメラの移動やズーム操作後に不正確になる現象が確認された。 環境 Cesium.js : 1.135.0(問題発生)→ 1.134.0(問題解消) フレームワーク : Next.js 16.0.1 + React 19.2.0 地形データ : Cesium World Terrain (Cesium.Terrain.fromWorldTerrain()) マーカー設定 : clampToGround: true heightReference: Cesium.HeightReference.CLAMP_TO_GROUND 症状 特定のマーカーをクリックしてズーム(拡大) カメラの視点を変更(回転・パン) 遠くにあるマーカーを確認すると、地形から浮いているか、不正確な位置に表示される この問題は、カメラが近距離に移動した際に読み込まれる高解像度の地形データ(LOD: Level of Detail)と、遠方のマーカーが参照する低解像度の地形データとの不整合によって発生すると考えられる。 調査プロセス 試行1: カメラ制御の明示化 マーカークリック時にsampleTerrainMostDetailedを使用して地形高度を取得し、明示的にカメラを移動させる実装を試みたが、問題は解消されなかった。 試行2: heightReferenceの変更 heightReferenceをCLAMP_TO_GROUNDからNONEに変更し、disableDepthTestDistanceを使用する実装を試みたが、この場合はマーカーが地形に正しく配置されず、別の問題が発生した。 試行3: バージョン比較 動作確認用のHTMLファイル(Cesium 1.110.0使用)では同様の問題が発生しないことを確認。Cesiumのバージョンが問題の原因である可能性を特定。 解決策 Cesium.jsを1.135.0から1.134.0にダウングレードすることで問題が解消された。 npm install cesium@1.134.0 技術的背景 CLAMP_TO_GROUNDの動作 CesiumのCLAMP_TO_GROUND設定は、エンティティを地形の表面に固定する機能を提供する。この機能は地形タイルのLOD(Level of Detail)に依存しており、カメラの位置によって異なる解像度の地形データが使用される。 理論上、Cesiumは地形タイルの更新に応じてエンティティの位置を再計算する必要があるが、1.135.0ではこの再計算メカニズムに問題がある可能性が考えられる。 関連Issue CesiumGS/cesium GitHub repositoryで類似の問題が報告されている: Issue #13012: https://github.com/CesiumGS/cesium/issues/13012 このissueでは、clampToGroundの動作に関連する問題が議論されている。 コード比較 問題発生時(1.135.0) Cesium.GeoJsonDataSource.load(geojson, { markerColor: config.color, markerSize: 24, clampToGround: true // 地形LOD変化で位置ズレが発生 }).then((dataSource: any) => { // ... entity.billboard.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND }) 解決後(1.134.0) 同一のコードで正常に動作。バージョンのみを変更。 ...

Protoweb:90年代のインターネットを体験できるタイムマシン

Protoweb:90年代のインターネットを体験できるタイムマシン

現代のインターネットは高速で洗練されていますが、かつての「インターネット黎明期」の雰囲気を懐かしく思う方も多いのではないでしょうか。Protowebは、そんな1990年代のインターネット体験を現代に蘇らせる、コミュニティ主導の公共サービスです。 Protowebとは? Protowebは、インターネット黎明期のウェブサイトをホスティングし、当時のブラウジング体験を再現するプロキシサーバーサービスです。歴史的なウェブサイトを保存・復元することで、1995年頃のインターネットの姿をそのまま体験できる環境を提供しています。 主な特徴 歴史的なウェブサイトの復元 :天気予報、ニュース、音楽、ゲーム、ダウンロードサイトなど、多様なコンテンツが利用可能 プロキシサーバー方式 :ブラウザの設定を変更するだけで、すぐに体験できる 登録不要 :アカウント作成やサインアップは必要なし 日々更新 :新しいクラシックウェブサイトが継続的に追加されている プロキシサーバーとは?初心者向け解説 Protowebを使うには「プロキシサーバー」の理解が必要です。初めて聞く方にもわかりやすく説明します。 プロキシサーバーの基本 プロキシサーバー とは、あなたのパソコンとインターネットの間に立って、通信を「中継」してくれるコンピュータのことです。 通常のインターネット接続 あなたのパソコン → 直接 → ウェブサイト プロキシサーバーを使う場合 あなたのパソコン → プロキシサーバー → ウェブサイト なぜProtowebにはプロキシ設定が必要なの? 重要:プロキシサーバーの設定をしないと、Protowebにアクセスできません。 理由は、Protowebが提供しているのは「普通のウェブサイト」ではなく、1990年代のウェブサイトを再現した特別な環境 だからです。 Protowebの仕組み 通常のインターネット接続 例:google.com にアクセス → 現代のGoogleが表示される Protowebのプロキシ経由 例:google.com にアクセス → Protowebが保存している1998年のGoogleが表示される つまり、Protowebのプロキシサーバーは**「タイムマシンの入り口」**のような役割をしています。プロキシを設定することで、「90年代のインターネット世界」に入ることができます。 プロキシ設定をしないとどうなる? http://www.inode.com/ にアクセスしても、何も表示されないか、エラーになる Protowebが復元したウェブサイトには一切アクセスできない 普通の現代のインターネットしか見られない プロキシサーバー設定の本質 プロキシ設定とは、ブラウザに対して以下のように指示することです: 「これから先は、直接インターネットにアクセスせずに、まず wayback.protoweb.org の 7851番ポート を経由してからアクセスしてね」 ポート番号とは? ポート番号 は、コンピュータの「入口の番号札」のようなものです。 マンションに例えると: 住所(ドメイン名) :wayback.protoweb.org(マンションの住所) 部屋番号(ポート番号) :7851(何号室に用事があるか) 一つのコンピュータには何万ものポート(入口)があり、それぞれ違うサービスが待機しています。 ポート80番 :通常のウェブサイト(HTTP) ポート443番 :暗号化されたウェブサイト(HTTPS) ポート7851番 :Protowebのプロキシサービス 使い始める方法 Protowebの利用方法は大きく分けて2つあります:**専用ブラウザを使う方法(簡単)と 既存のブラウザでプロキシ設定する方法(少し手間)**です。 ...

OCFLによる長期デジタル保存の実践 - 入門ガイド

OCFLによる長期デジタル保存の実践 - 入門ガイド

はじめに デジタルデータの長期保存は、図書館、アーカイブ、研究機関にとって重要な課題です。データ形式の変化、ソフトウェアの陳腐化、ストレージ技術の進化など、様々な要因がデジタル情報の持続可能性を脅かしています。 本記事では、この課題に対する解決策の一つである**OCFL(Oxford Common File Layout)**について、その概念、意義、そして実装例を紹介します。 OCFLとは OCFL(Oxford Common File Layout) は、デジタル情報を構造化され、透明で、予測可能な方法で保存するための仕様です。オックスフォード大学のボドリアン図書館とスタンフォード大学図書館を中心に開発され、現在はコミュニティ主導のオープンスタンダードとして発展しています。 OCFLの公式定義 “OCFLは、アプリケーション非依存のアプローチでデジタル情報を保存するための仕様であり、長期保存とデータの完全性を保証します。” OCFLの5つの主要原則 完全性(Completeness) - リポジトリをストレージファイルから完全に再構築可能 解析可能性(Parsability) - 人間と機械の両方が理解できる構造 堅牢性(Robustness) - エラーや破損に対する耐性 バージョン管理(Versioning) - オブジェクトの変更履歴を保持 ストレージの多様性(Storage Diversity) - 様々なストレージインフラに対応 なぜOCFLが必要なのか デジタル保存の課題 従来のデジタル保存には、以下のような課題があります: ベンダーロックイン - 特定のシステムやソフトウェアに依存してしまう 移行の困難さ - システム更新時のデータ移行が複雑 透明性の欠如 - データがどのように保存されているか不明瞭 長期的な可読性 - 数十年後もデータを読み取れる保証がない OCFLによる解決 OCFLは、以下のアプローチでこれらの課題を解決します: シンプルなファイル構造 - 標準的なファイルシステムを使用 JSONによるメタデータ - 人間が読める形式で管理情報を保存 ハッシュによる完全性検証 - データの破損を検出可能 透明なバージョニング - すべての変更履歴が追跡可能 OCFLの基本構造 OCFLリポジトリは、以下のような階層構造を持ちます: ocfl_root/ ├── 0=ocfl_1.1 # OCFL仕様バージョンを示すマーカー ├── ocfl_layout.json # レイアウト情報 └── object-001/ # OCFLオブジェクト ├── 0=ocfl_object_1.1 # オブジェクトバージョンマーカー ├── inventory.json # オブジェクトの完全な履歴 ├── inventory.json.sha512 # インベントリのチェックサム └── v1/ # バージョン1 ├── inventory.json # このバージョンまでの履歴 ├── inventory.json.sha512 └── content/ # 実際のコンテンツ └── sample.txt inventory.json - OCFLの心臓部 inventory.jsonはOCFLオブジェクトの最も重要な要素で、以下の情報を含みます: ...

MacでHexエディタを使うなら「HexEd.it」:HxDの代替ツールガイド

MacでHexエディタを使うなら「HexEd.it」:HxDの代替ツールガイド

はじめに iPRES(International Conference on Digital Preservation)のワークショップに参加した際、デジタル保存の実践的な演習でHexエディタ「HxD」が使用されました。バイナリファイルの構造解析やファイルフォーマットの確認など、デジタルアーカイブの現場では欠かせないツールです。 しかし、HxDはWindowsのみ対応 で、Macでは使用できません。ワークショップ後、Mac環境で同様の作業を行うための代替ツールを探した結果、Web版のHexエディタを見つけました。 そこで本記事では、Macユーザー向けに**Web版Hexエディタ「HexEd.it」**の使い方を詳しく紹介します。iPRESワークショップで学んだHxDの使い方を、HexEd.itでも実践できるようガイドします。 HxDとは?なぜMacで使えないのか HxD Hex Editorは、Windows向けの高機能なHexエディタです。無料で使えて動作が軽快なため、多くの開発者やセキュリティ研究者に使用されています。 HxDの主な特徴 高速な動作 大容量ファイル対応 RAM編集機能 ディスクエディタ機能 チェックサム計算 しかし、HxDはWindows専用アプリケーション として開発されており、macOSには対応していません。仮想環境やWineを使えば動作させることも可能ですが、手間がかかります。 HexEd.it - ブラウザで使える代替ツール Mac環境で使用できる代替ツールとしてHexEd.it (https://hexed.it/)があります。 HexEd.itの特徴 ✅ クロスプラットフォーム対応 Windows、Mac、Linux、どのOSでもブラウザがあれば使える インストール不要で即座に使える ✅ プライバシー重視 ファイルはブラウザ内で処理され、サーバーにアップロードされない オフラインでも動作可能 ✅ 豊富な機能 Hex/ASCII同時表示 バイト編集 検索・置換 ファイルの比較 データ型変換(int, float等) エクスポート機能 ✅ 無料で使える 基本機能は完全無料 HexEd.itの使い方 1. ファイルを開く ブラウザで https://hexed.it/ にアクセス 「Open file」ボタンをクリック 編集したいファイルを選択 または、ファイルを画面にドラッグ&ドロップすることもできます。 2. インターフェースの見方 HexEd.itの画面は主に3つのエリアに分かれています: ┌─────────────┬──────────────────────────┬──────────────┐ │ オフセット │ Hex表示エリア │ ASCII表示 │ ├─────────────┼──────────────────────────┼──────────────┤ │ 00000000 │ 50 4B 03 04 14 00 00 00 │ PK..........│ │ 00000010 │ 08 00 00 00 21 00 AB CD │ ....!.......│ │ 00000020 │ EF 01 23 45 67 89 AB CD │ ..#Eg.......│ └─────────────┴──────────────────────────┴──────────────┘ オフセット(左側) ...

DROIDで見つける隠れたファイル形式の問題:デジタル保存の必須ツール

DROIDで見つける隠れたファイル形式の問題:デジタル保存の必須ツール

デジタルアーカイブや長期保存を担当している方なら、「このファイル、本当に拡張子通りの形式なのか?」と疑問に思ったことがあるはずです。今回は、そんな疑問を解決してくれる強力なツール「DROID」について、実際の分析結果を交えながら紹介します。 DROIDとは? DROID(Digital Record Object Identification)は、英国国立公文書館(The National Archives)が開発したファイル形式識別ツールです。ファイルの拡張子だけでなく、ファイルの内部構造(シグネチャ)を分析 して、真の形式を特定します。 DROIDの主な機能 バイナリシグネチャによる識別 :ファイルの内容を直接分析 PRONOMレジストリとの連携 :15,000以上のファイル形式データベースを活用 一括処理 :フォルダ単位での大量ファイル分析 拡張子ミスマッチの検出 :拡張子と実際の形式の不一致を発見 CSV出力 :分析結果をデータとして活用可能 なぜDROIDが必要なのか? デジタルファイルには、以下のような問題がよくあります: 意図的な拡張子変更 :ファイル形式を隠すため 誤った拡張子の付与 :人為的ミスやシステムエラー 形式変換時の拡張子未更新 :変換後に拡張子が古いまま 拡張子のない/不明なファイル :古いシステムからの移行時など これらの問題は、長期保存計画や移行戦略に深刻な影響 を与える可能性があります。 実例で見るDROIDの威力 実際にDROIDで分析したデジタル保存ワークショップのサンプルファイルから、興味深い問題が複数見つかりました。 🚨 発見された主な問題 1. 音声ファイルが画像ファイルを装っている ファイル名: 412016__skymary__cat-purring-and-meow.tif 拡張子: .tif(TIFF画像形式を示唆) 実際の形式: Waveform Audio (PCMWAVEFORMAT) PUID: fmt/141 MIME Type: audio/x-wav 状態: EXTENSION_MISMATCH = true 問題点 :画像として扱われる可能性があり、適切な音声再生ツールでアクセスできない恐れがあります。 2. 新形式なのに古い拡張子 ファイル名: AusPreserves-CodeofConduct_20181115.doc 拡張子: .doc(Word 97-2003形式を示唆) 実際の形式: Microsoft Word for Windows 2007 onwards (.docx) PUID: fmt/412 MIME Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document 状態: EXTENSION_MISMATCH = true 問題点 :古いWordバージョンでは開けない可能性があり、互換性の問題が発生します。 ...

自動遷移機能を持つIIIF画像座標エディタの開発

自動遷移機能を持つIIIF画像座標エディタの開発

概要 今回開発したエディタは、IIIF対応の高解像度画像上で任意の座標を記録・管理するためのWebベースのツールです。URLパラメータで画像を指定でき、様々な研究プロジェクトで利用可能な汎用的な座標記録ツールとして設計されています。 https://youtu.be/UqPo5Xrkin8 主要技術スタック OpenSeadragon : IIIF画像ビューアライブラリ (v4.1) SVGオーバーレイ : マーカー表示用 localStorage : データの永続化 Vanilla JavaScript : フレームワークレス実装 技術的特徴 1. URLパラメータによる画像指定 ツールの最大の特徴は、URLパラメータで任意のIIIF画像を指定できることです: function getImageUrlFromQuery() { const urlParams = new URLSearchParams(window.location.search); const urlParam = urlParams.get('u'); if (urlParam) { try { return decodeURIComponent(urlParam); } catch (e) { console.error('Error decoding URL parameter:', e); alert('URLパラメータのデコードに失敗しました。デフォルト画像を使用します。'); } } // Default image URL return 'https://img.toyobunko-lab.jp/iiif/premodern_chinese/suikeichuzu/Suikeichuuzu_grid_l.tif'; } const imageUrl = getImageUrlFromQuery(); 使用例: intersection_editor.html?u=https%3A%2F%2Fexample.com%2Fiiif%2Fimage.tif URLエンコードされた画像URLを?u=パラメータで渡すだけで、任意の画像を開けます。 2. 画像URLごとのデータ分離 localStorageのキーに画像URLを含めることで、画像ごとに独立したデータを管理: const imageUrl = getImageUrlFromQuery(); const storageKey = `intersection_points_${btoa(imageUrl).substring(0, 50)}`; 画像URLをBase64エンコードしてキーの一部とすることで、複数の画像プロジェクトを同時に管理できます。 3. IIIF画像の自動読み込み 画像URLから自動的にIIIF info.json URLを生成: function getIIIFInfoUrl(imageUrl) { if (imageUrl.endsWith('info.json')) { return imageUrl; } let baseUrl = imageUrl.replace(/\.(jpg|jpeg|png|tif|tiff)$/i, ''); return `${baseUrl}/info.json`; } const viewer = OpenSeadragon({ id: "viewer", tileSources: imageUrl.startsWith('http') ? getIIIFInfoUrl(imageUrl) : imageUrl, showNavigationControl: true, showNavigator: true }); .tifや.jpgなどの拡張子を自動的に処理し、IIIF Image API 2.0に準拠したinfo.jsonをリクエストします。 ...

Odeuropa Visualization: SKOS語彙とSPARQLを活用した香りデータの可視化プラットフォーム

Odeuropa Visualization: SKOS語彙とSPARQLを活用した香りデータの可視化プラットフォーム

はじめに Odeuropaは、ヨーロッパの香りの歴史を研究するプロジェクトで、絵画、文学、その他の歴史的資料に描かれた香りの表現を収集・分析しています。本記事では、OdeuropaのSPARQLエンドポイントを活用し、SKOS(Simple Knowledge Organization System)語彙体系に基づいた香りデータの可視化Webアプリケーションの実装について紹介します。 https://odeuropa-seven.vercel.app/ja/ プロジェクト概要 技術スタック フロントエンド : Next.js 15 (App Router) UI : Material-UI v5 国際化 : next-intl データ取得 : SPARQLクエリ (Odeuropa SPARQLエンドポイント) 言語 : TypeScript ホスティング : 静的サイト生成(SSG) 主な機能 1. 香り検索 (/odeuropa-sources) アプリケーションの中核となる機能で、Odeuropaプロジェクトが収集した香りの知覚イベント(smell perception events)を検索・閲覧できます。 主な特徴: 複雑なSPARQLクエリによるデータ取得 香り放出イベント(emission)、香りオブジェクト、ソース(絵画・文学作品など)、テキスト断片を結合 CRMベースのオントロジー(ecrm:P67_refers_to, od:F1_generatedなど)を活用 多軸フィルタリング SKOS語彙による香りの源でフィルタ(?xパラメータ) ソースタイプフィルタ(視覚的アイテム E36_Visual_Item / 言語オブジェクト E33_Linguistic_Object) リッチな情報表示 香りのラベル、ソース情報(タイトル、画像、URI) テキスト断片の引用 嗅覚体験の質的情報(Olfactory Experience) ページネーション - 20件ずつの効率的な表示 SPARQLクエリ例: SELECT DISTINCT ?source ?source_title ?fragment ?fragment_value ?emission ?smell ?smell_label ?source_image WHERE { ?emission od:F3_had_source ?x . ?emission od:F1_generated ?smell . # ソースとの関連(フラグメント経由または直接) { ?fragment ecrm:P67_refers_to ?emission . ?fragment rdf:value ?fragment_value . ?source ecrm:P165_incorporates ?fragment . } UNION { ?source ecrm:P67_refers_to ?emission . } } 2. 香り詳細ページ (/odeuropa-sources/item) 個別の香りに関する詳細情報を表示するページです。 ...

Omeka Sで独立した作者データベースを構築する方法

Omeka Sで独立した作者データベースを構築する方法

はじめに 美術館や図書館のデジタルアーカイブでよく見られる課題として、「作品と作者の関係を適切に管理したい」というニーズがあります。特に、一人の作者が複数の作品を制作している場合や、複数の作者が共同で一つの作品を制作している場合、その関係性を明確に表現し、検索可能にすることが重要です。 この記事では、Omeka Sで作者データベースを独立して構築し、作品とリンクさせる方法について解説します。 課題の要点 独立した作者データベースの構築 : 作品データベースとは別に、作者(執筆者)のデータベースを作成し、両者をリンクさせることは可能か? 複数作者への対応 : 一つの論文やデザインに複数の作者がいる場合、どのように表現すればよいか? 解決方法 1. 作者を独立したアイテムとして登録する Omeka Sでは、作者を独立した「アイテム」として登録することで、作者データベースを構築できます。 手順: ステップ1: 作者用のアイテムセットを作成 「アイテムセット」から「新規アイテムセット」を作成 タイトルを「作者一覧」などとする このアイテムセットに全ての作者アイテムを収納 ステップ2: 作者アイテムを登録 「アイテム」→「新規アイテム」 クラスは foaf:Person を選択(推奨) 作者情報を入力: dcterms:title(作者名) foaf:firstName(名) foaf:familyName(姓) dcterms:description(経歴や専門分野) その他、所属機関など必要な情報 作成した「作者一覧」アイテムセットに追加 2. 作品から作者へリンクを設定する 作品アイテムの dcterms:creator(作成者)プロパティで、作者アイテムへの参照を設定します。 手順: ステップ1: 作品アイテムを編集 作品アイテムの編集画面を開く dcterms:creatorプロパティを見つける 「値を追加」→「Omekaリソース」を選択 ステップ2: 作者アイテムをリンク 「選択リソース無し」ボタンをクリック サイドバーが開き、アイテム検索が可能になる 作成済みの作者アイテムを検索 該当する作者を選択して「追加」 これにより、作品アイテムと作者アイテムが関連付けられます。 3. 複数作者への対応 Omeka Sでは、同一プロパティに複数の値を追加できます。 手順: 作品アイテムの dcterms:creator フィールドで、「値を追加」ボタンを再度クリック 2人目、3人目の作者アイテムを同様に選択して追加 必要な人数分だけ繰り返す 重要なポイント: Dublin Coreの dcterms:creator は、複数の値を持つことが想定されています 同じプロパティに複数の作者アイテムをリンクすることで、共著論文やコラボレーション作品を適切に表現できます 4. 作者の作品一覧を表示する 作者アイテムのページから、その作者が制作した全作品を一覧表示できます。 ...

Leaflet-IIIFでのアノテーション座標変換の完全ガイド

Leaflet-IIIFでのアノテーション座標変換の完全ガイド

概要 IIIF (International Image Interoperability Framework) Presentation API v3のマニフェストに含まれるアノテーション座標(xywh形式)を、Leaflet-IIIFを使用したマップビューアー上で正確に表示する方法について解説します。 この問題は一見シンプルに見えますが、Leaflet-IIIFの内部動作を理解しないと正確な座標変換ができません。 問題の背景 IIIFマニフェストのアノテーション形式 IIIF Presentation API v3では、アノテーションの対象領域は以下のようなxywh形式で指定されます: { "id": "https://example.org/iiif/canvas/1/annotation/1", "type": "Annotation", "motivation": "commenting", "body": { "type": "TextualBody", "value": "雅屯河", "language": "ja" }, "target": "https://example.org/iiif/canvas/1#xywh=41012,81,115,49" } このxywh=41012,81,115,49は: x: 41012(左端のピクセル位置) y: 81(上端のピクセル位置) w: 115(幅) h: 49(高さ) を意味します。これらは元画像のピクセル座標 です。 Leaflet-IIIFの座標系 Leaflet-IIIFは、IIIF Image APIで提供される高解像度画像をタイル形式で表示するLeafletプラグインです。内部的には: CRS.Simple座標参照系を使用 画像を複数のズームレベルで縮小して管理 ズームレベルごとに異なる座標スケールを使用 この複雑な座標系のため、単純にmap.unproject()やpointToLatLng()を使っても正しい位置に配置できません。 試行錯誤の過程 失敗した試み1: map.unproject()の直接使用 // ❌ これは動かない const point = L.point(x, y); const latLng = map.unproject(point, 3); // ズームレベル3を指定 問題点 : unproject()は現在のマップの座標系を前提としており、Leaflet-IIIFが内部で使用している座標系とは異なります。 失敗した試み2: マップ境界からの比例計算 // ❌ これも不正確 const bounds = map.getBounds(); const normX = imgX / imageWidth; const normY = imgY / imageHeight; const lng = bounds.getWest() + (normX * (bounds.getEast() - bounds.getWest())); const lat = bounds.getNorth() - (normY * (bounds.getNorth() - bounds.getSouth())); 問題点 : Leaflet-IIIFは画像のアスペクト比を保持するため、マップ境界と実際の画像境界は異なります。 ...

Omeka-S Docker環境を別サーバーに移行する完全ガイド

Omeka-S Docker環境を別サーバーに移行する完全ガイド

はじめに 本記事では、Docker ComposeでセットアップされたOmeka-S環境を、volumeデータを含めて別のサーバーに移行する手順を解説します。データの整合性を保ちながら、安全に移行作業を進めることができます。 環境 移行元サーバー : Ubuntu 22.04 移行先サーバー : Ubuntu 22.04(新規セットアップ) 構成 : Omeka-S + MariaDB + phpMyAdmin + Traefik + Mailpit 移行の流れ 移行元サーバーでのバックアップ ローカルマシンへのダウンロード 移行先サーバーのDocker環境セットアップ データの復元と起動 ステップ1: 移行元サーバーでのバックアップ 1.1 現在の環境確認 # 実行中のコンテナを確認 docker ps # Dockerボリュームを確認 docker volume ls 出力例: DRIVER VOLUME NAME local omeka-s-docker_mariadb local omeka-s-docker_omeka 1.2 バックアップファイルの作成 # /optディレクトリに移動 cd /opt # 設定ファイル等をバックアップ(約60MB) sudo tar -czf omeka-backup-$(date +%Y%m%d).tar.gz omeka-s-docker/ # Dockerボリュームのデータをバックアップ(約1GB) sudo docker run --rm \ -v omeka-s-docker_omeka:/data/omeka \ -v omeka-s-docker_mariadb:/data/mariadb \ -v /opt:/backup \ alpine tar -czf /backup/omeka-volumes-$(date +%Y%m%d).tar.gz -C /data . # バックアップファイルの確認 ls -lh /opt/*.tar.gz 出力例: ...

RDFSとSHACLの使い分け:rangeとpropertyShapeの関係を理解する

RDFSとSHACLの使い分け:rangeとpropertyShapeの関係を理解する

はじめに RDF(Resource Description Framework)でデータを扱う際、「RDFS(RDF Schema)」と「SHACL(Shapes Constraint Language)」という2つの仕組みが出てきます。どちらもプロパティやクラスの制約を定義できますが、目的も動作も全く異なります 。 この記事では、特に混乱しやすい以下の疑問に答えます: rdfs:domain / rdfs:range と SHACL の sh:class / sh:datatype は何が違うのか? RDFS の range と異なる SHACL 制約を設定してもいいのか? range がクラス(foaf:Person)なのに SHACL でデータ型(xsd:string)を指定するのは問題ないか? 1. RDFSとSHACLの根本的な違い RDFS:推論(Inference)のため RDFS は**「もしこのプロパティが使われたら、こういう知識が導き出せる」**という宣言です。 # RDFS スキーマ定義 ex:author rdfs:domain ex:Book ; rdfs:range ex:Person . 意味 : ex:author が使われたら、主語(subject)は自動的に ex:Book のメンバーと推論される 目的語(object)は自動的に ex:Person のメンバーと推論される # 元のデータ ex:book1 ex:author ex:john . # 推論エンジンが自動的に導き出す知識 ex:book1 a ex:Book . # domain から推論 ex:john a ex:Person . # range から推論 特徴 : ...

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」(合理的農業の原理)を例に、データ構造を見ていきましょう。 ...