はじめに

IIIFビューアのMiradorには検索機能があり、IIIF Search APIに対応したマニフェストでは検索結果をハイライト表示できます。しかし、Search APIに非対応のマニフェストでも、任意の領域をハイライト表示したいケースがあります。

本記事では、Miradorの内部APIを利用して、外部データソースからのアノテーション情報を基にハイライト表示を実現する方法を紹介します。

デモ

ユースケース

  • 独自のOCRシステムで抽出したテキスト領域のハイライト
  • 機械学習で検出したオブジェクトの領域表示
  • 外部データベースに保存されたアノテーションの可視化
  • Search API非対応のIIIFサーバーでの検索結果表示

実装方法

基本的な仕組み

Miradorは内部でReduxを使用しており、receiveSearchアクションを通じて検索結果を登録できます。このアクションにIIIF Search API形式のJSONを渡すことで、任意のデータソースからのハイライトを表示できます。

必要な情報

ハイライトを表示するために必要な情報は以下の3つです:

  1. キャンバスURI - ハイライトを表示するページのURI
  2. 座標(xywh) - ハイライト領域の位置とサイズ(x, y, width, height)
  3. テキスト - ハイライトに関連付けるテキスト(検索パネルに表示される)

サンプルコード

以下は、国立国会図書館デジタルコレクションの源氏物語で「いつれの御時にか…」の冒頭部分をハイライト表示するサンプルです。

<<<<!hh/b//Dte<<<<ho<<<bhOmammts/eddss/otCldeeitb#sayiccc}c}f}lc}sdmT>tttyomtd>vrro;o)ueo)cylYlaalldiy>iinmch]nislw}w}w};nc}c}vcc)i}tniccci};r>>Paeeyrlippsaai,Msdeai]i,o,co;o)ioo;fsfooofiEncn>>aedtttnng{}it:lnnimct,naaasretn'''w}r}ncp;ennic)vhtnnnhuapghaM{d>=>ivh,regddaahdlllikniIs@@@i,e)soowcssd(o;ii(sss(indth=amio"scfalxtam'cuo:nnuollldsaoItcitt'ts''mr}o)tnseottsn'scseguhtttmgsd>t"rermrmroesiyedimtawivmwoooepbnIodyh@oo@@oe,n,tirm=esweaewhniahuHmjs=aa-icnsIgwxoriegs'fab:wwwBalFsn'pittuitts'c:aet.pss>atianaelsgsmmnlbilae"drvr=ftdhhtrarde:wesnFCMaceaet:enyardyio@hdnisaternrvrriuhtaaiisg>"tvogia"iU:t::daT:isIa{ulareddSae':plc'pvutacdtotnaascsdcac.gblannfgch>=iriedhgrsodh[ntdiloxOC:derxc:e:e:earyraA:noitrtheohshshsitiiehrl"enwotl':''roe'{dI:llsipoHacta{'s'tcpsnc:roecaCawCIRttcgeffstiiUwC:ert=:h3VrmjodNsemenfirh'n':h:c:iee:vt'enhtor-odeoArheetAbgTpur-pt[0i-eaw:cac:intagcR:vsiao:'ais'.W=Cemc1msrdit=ssdehFos0vs{'t9ev:'-ovrz:rlhheac'ghnn:hsoerdio.ph'p+pedbAtt&d(t-rt;{i:hp5wi,1cniefeosls's:shivo:{iInaiinvmcaA,ao.eedms&e)s8toe/ts,ee''ofgea:tleiAphIAclgaa'gdrgsdiponcnndddi=d;(""mpww/t:6rwl,nianlrP,gPotdn:ihs:'ch=chpoeamitisi=er=!m>aieup/9eifgt:sfuahIntnLglIAsnl+htawwnpoises=damm=icHddrns/4=rgi.ieaentsp+oahidnctiM''tIeianonepm)dsaaroidt"p:d,'hgcot,l,ese:tytgn::g'i,,cdronWnWaafiotnntangih>k/l9M,t.anrsl(/aesh+opCh#rh.niiirtarrraiirdthn:<g/.7i'mnPue:v=/tr.ttaotxa(sWon=ncclaeVtffuoelg/.dn,r,avoe,iisi'lsain.ydatinddhhsdtieeeerni:1dcld2anas,{e{ieo,e./tnttwodonWoMo'(eoue.ss;Vtg0io.l0disiwiannmhiteehrdrdiwiw,s;rrwmtti=h00vmn.5ofItefrLgaioinx=.AeonIrIeVneas.e"t;%>/dg1redir.citpgnntt'ac.wddadai;rn[iww;mlo'.s,o,ihsh(h'gA,dtgIo)d,re.icseiS}i..,vtno't,(l,'s+diedwocwsfoFrdahrgjiU:c,'hi,TCots{rhetene,tmeaoperaa,igehonS=[.Arosfthpid./wl'npghxim)tirc.rticc=lgojae,fvihttgp;aOdetsesghodehrppraa/l'hatb]cit..ine<t@/i(rssi,lnej.eoogmnfv/:4a/{-Iegii(ecinreagiit.pirdah+go)cov)etngci10iii,rthn;tne;.S{i&.et0./igc,itW.tSst}f&c-l00ifhhhn.ikeeua;eawev-i/ti/idxnenabtsmni>hai3'g1neydytrsetavd;lf4,h/dxwoscc(Unatp/3lce,hw(=hr)rish}h37iox,(s=(i;lfI,a46gn)'t=b]ed.38'htwae;s,i176,te=it'(tn56/sx>nes(.ci/8c)td.e)jotd6a.(ocasnii/n{j{wor=ofasmvs-mc>niltaao1ph)g-/nsn'a'{.smi/',n{hcif2,iiare2{oglas'nhedt,Wl=o.ii1rjng..sdh0moot"inws>n's).,);j.sf"i>n<d/(script>

コードの解説

1. 設定パラメータ

c}o;nmch]saai,tnng{}ivh,cfalxtoesiyensIgwxftdhhtiU:t::grsl':''=:h3t[0{'t9hp5ts,t:6p/9s/4:d,./l9./.7.dn,'ld2,.l0n.5dg1lo'..,gjop./japp/ia/piii/iifi/i3f4/3374638766/8c6a/nmvaansi/f2e2s't,.json',
  • manifestUrl: IIIFマニフェストのURL
  • canvasId: ハイライトを表示するキャンバスのURI
  • highlights: ハイライト情報の配列。複数のハイライトを追加可能

2. IIIF Search API形式のレスポンス構築

c}o;n''r}s@@e)tcts'mr}o)oyo@oe,n,snputts'c:eteryio@hae'cpvutacrx:eearyracts'tcpsnh''::iee:vR:so:'aechn:hss':io:{iIphAga'gdotnh:'chntnlAsnl+spoinctie:tgn::g'/ahopCh#=/tttaotxiisain.y{io.tnttwinmiteehfLaoinx=.ipnntt'is('gA,ot(,'s+/'h,Ta,iehpgxiihtg/l'hsi,legiahgrthc,th./ix1ny/dwcehox,n)te=x>t.(j{son',

ポイントは on プロパティで、キャンバスURI#xywh=x,y,width,height の形式でハイライト領域を指定します。

3. マニフェスト読み込み完了の検知

lc}eo)tniccci};sfooofhtnnnhuai(sss(indguhtttmgsdhniahuHlsgsmmnlbiiuhtaaiisggblannfgchhsitiiehrltcgeffstiiArheetAbgdit=ssdehdbAtt&d(teedms&e)sddi=d;(=er=!m=damm=im)dsaarfiotnntaarrraiirdlaeVtffuosdtieeeereoue.ss;V;rrwmttiVneas.ei;rn[iwe.icsewsfoFretene,rosft.rticcsesghot..inogmnfreagietng.S{i&.st}f&cua;eabtsmnsetavc(Unar)risi;lfIb]ede;s,(t(.c)josn=of>ni)g{.{highlights);

MiradorはReduxを使用しているため、store.subscribe()でステート変更を監視できます。マニフェストのisFetchingfalseになり、jsonが存在する状態になったタイミングでハイライトを追加します。

これにより、setTimeoutを使用するよりも確実にマニフェスト読み込み完了後にハイライトを追加できます。

4. Miradorへの登録

c}vc)vo)io;incp;en'scsesoowsweaewtnsetianaetirnrvrraet.sdcac.dniseohshsdtotawCIRtA:nor-odeoc:rc1msrt'eh'p+peis'.A,ao.oerdcnndnaiitisirgsises=chponephtanWaaM''tirti,,c=nccrhdhha(Mo'(daiw,sodrIerdada.Ad,racocdtrhdi.ACorconetm)cip;eoainnv)ie;oSneWairncdho(w('window-1',{

receiveSearchアクションを使用して、構築したレスポンスをMiradorに登録します。

応用例

複数のハイライト

h]ig{{{hlxxxiyyygwwwhhhht:::s:'''158[000000,,,269000000,,,321005000,,,432005000''',,,ttteeexxxttt:::'''123'''}}},,,

APIからデータを取得

a}casodyccr}ndnooe)使sHcnntxt)tissuye;gfttrwxhhunhtilnrd::giceadhgtstaaalhipatnnitooanngsnn=.ooh(sa..tmleanctsiownoera=aoox=aditrtdHatad,aoiwtiwrgarinaVhieoaiiltsntteipsewgfo.slehenm,orttsaa,scepdFh.(Hcr(jaioo`sngnm/onhfAanoliPp(igIi)=g.(/;>hccataan(snnn{FvvoraatossamIItAddiP,)oIn(h{sci?ogcnhaflniivgga.hsct=as$n){v;eanscIodd)e;URIComponent(canvasId)}`);

URLパラメータから動的に生成

このリポジトリのviewer.htmlでは、URLパラメータからハイライト情報を受け取り、動的にビューアを生成しています。

cccccooooonnnnnssssstttttpmcxtaaayernnwxaivhtmfases==sI=tdppUaanr=rrelaawpmm=assUr..RpaggLameeSrsttea.((amg''rsextc.tyehg(wxPe'htatc''r(a))a'n;mmvsaa(nswi''if)Hne;idsgothw'l.)il;gohcta't;ion.search);

座標の取得方法

ハイライト領域の座標(xywh)を取得するには、以下の方法があります:

  1. IIIF Image APIのRegion指定 - 画像編集ソフトで座標を計測
  2. OCRエンジンの出力 - Tesseract等のOCR結果に含まれる座標情報
  3. アノテーションツール - IIIF対応のアノテーション作成ツールを使用
  4. 機械学習モデルの出力 - 物体検出モデルのバウンディングボックス

まとめ

MiradorのreceiveSearchアクションを活用することで、IIIF Search APIに非対応のマニフェストでも任意の領域をハイライト表示できます。この方法は:

  • データソースに依存しない - API、ファイル、データベース等から取得したデータを利用可能
  • Search APIと同じUI - Miradorの標準的な検索結果表示機能を活用
  • 複数ハイライト対応 - 配列で複数の領域を一度に登録可能
  • 確実なタイミング制御 - store.subscribe()によりマニフェスト読み込み完了を検知

ファイル構成

miradRLCmdoEIOiorACNrc-DETashMNRdiviESInig.EBrdehmU-ewldTcxeiIu.rgNsh.hGttht.omt/mmlmd-lhighlight.md#######MGMIiiTtrHaudborPages

参考リンク