Jekyll2021-06-04T23:49:29+00:00/feed.xmlThe digitised pastThis is a blog investigating different use cases around IIIF and other web technologies to help explore the past through historical documents and objects.Glen RobsonNLW Journals Writeup2021-06-04T12:27:22+00:002021-06-04T12:27:22+00:00/iiif/2021/06/04/NLW-Journals<p><a href="https://journals.library.wales">NLW Journals</a> write up from 2017. I often find that I link to this article but the original isn’t always available so I have copied it here for posterity. The original is available on the <a href="https://dev.llgc.org.uk/wiki/index.php?title=IIIF_Journals">NLW Dev Site</a>.</p>
<h1 id="welsh-journals-technical-writeup">Welsh Journals Technical Writeup</h1>
<p>Authors:</p>
<ul>
<li>Glen Robson - Head of Systems,</li>
<li>Dan Field - Head of Development,</li>
<li>Dylan Jones - Senior Web Developer,</li>
<li>Kim Botticelli - Senior Web Developer</li>
</ul>
<p>This document describes how the National Library of Wales (NLW) has built the new Journals website https://journals.library.wales. The new website brings together two collections of Welsh Journals and also provides access to content that hasn’t previously been available. The amount of content in the new website includes:</p>
<ul>
<li>Total titles 479</li>
<li>Total new titles 395</li>
<li>Total number of pages 1,226,816</li>
<li>Total number of new pages 669,223</li>
</ul>
<p>The development was done on top of the NLW IIIF infrastructure including harvesting using Sitemaps and indexing the IIIF Manifests and Annotations lists.</p>
<h2 id="background">Background</h2>
<p>The NLW has worked on two Journal projects. The first project was funded by JISC digitising 50 modern Welsh Journals. The second project was funded by the Welsh Government and the European Regional Development fund to digitise over one million pages of Journal content. The content of the Journals ranges from academic and scientific publications to literary and popular magazines. Further details on the collection can be seen at:</p>
<p><a href="https://www.llgc.org.uk/index.php?id=7594">https://www.llgc.org.uk/index.php?id=7594</a></p>
<p>The JISC-funded modern Welsh Journals project was undertaken around 2008 and included content that was under copyright so Authors and Publications had to be identified and rights status established. As part of the digitisation workflow articles were identified by noting the article start and end page. The project website was launched around 2009/10.</p>
<p>The second project learned a number of lessons from the previous project particularly in what metadata was captured and the workflow involved in making the items available. For this project Journals were chosen which were out of copyright and article metadata wasn’t captured as part of the digitisation process. 36 titles were shared with Europeana and were made available on a temporary website while development was undertaken to merge the two datasets. The project included digitising 425 titles and around 1 million pages.</p>
<h2 id="iiif-interface-to-the-data">IIIF interface to the data</h2>
<p>The Journal pages were scanned to TIFF files and a number of derivatives were created to support the previous website including a 650px image, 50% image and a PFF zoomable image. The OCR was stored as ALTO and also in AbbyyFineReader xml. For the set of Journals that were shared with Europeana the access file was JPEG2000 and the NLW had undertaken a migration to replace the previous images with a single JPEG 2000. After delivery of the Europeana project the NLW developed a PFF to IIIF image server so converting the images not covered by this project was no longer necessary. Now both JP2 and PFF images appear in the website as IIIF images and the differing source formats is no longer an issue. Using the IIIF image standard has also made the 650px and 50% images redundant.</p>
<p>The metadata for the Journals is stored in the NLW fedora repository as METS documents and these were converted to IIIF Manifests and Collections as can be seen in the diagram below. The IIIF standard promotes using a seeAlso link to point to structured metadata and we converted our MODS metadata to EDM. The list of Journals which are part of the project are listed in a sitemap and this is what we used for indexing.</p>
<p><img src="http://dev.llgc.org.uk/iiif/IIIF_Journals_Technical_ARC.jpg" alt="Technical infrastructure diagram" /></p>
<h3 id="sitemap">Sitemap</h3>
<p>An example of the sitemap we used is below and includes live links to IIIF collections for Public Domain Titles:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:iiif="http://iiif.io/api/presentation/2/">
<url>
<iiif:manifest>http://dams.llgc.org.uk/iiif/2.0/2000001/manifest.json</iiif:manifest>
</url>
<url>
<iiif:manifest">http://dams.llgc.org.uk/iiif/2.0/2035242/manifest.json</iiif:manifest>
</url>
….
<url>
<iiif:manifest>http://dams.llgc.org.uk/iiif/2.0/2007313/manifest.json</iiif:manifest>
</url>
<url>
<iiif:manifest>http://dams.llgc.org.uk/iiif/2.0/2007768/manifest.json</iiif:manifest>
</url>
</urlset>
</code></pre></div></div>
<p>There wasn’t time to add last modification dates into the sitemap but this would have been very useful to enable the indexer to pickup when a manifest changed. This process of re-indexing was managed through an issue tracking system but became complicated to manage at times.</p>
<h3 id="europeana-data-model-edm-metadata">Europeana Data Model (EDM) Metadata</h3>
<p>An example EDM record for a title can be seen below:</p>
<p><a href="http://dams.llgc.org.uk/behaviour/llgc-id:2000001/fedora-sdef:rdf/toRDF">http://dams.llgc.org.uk/behaviour/llgc-id:2000001/fedora-sdef:rdf/toRDF</a></p>
<p>Issue level manifests also contain links to EDM but it was only the title level that was indexed for this project. The EDM record provided the following information in the SOLR record:</p>
<ul>
<li>Publication title - dc:title</li>
<li>Publisher details - dc:publisher (Welsh and English)</li>
<li>Language of Journal - dc:language</li>
<li>Description of Journal - dc:description (Welsh and English)</li>
</ul>
<p>Frequency of publication was added later to the EDM.</p>
<h3 id="articles">Articles</h3>
<p>The original Welsh Journals project contained Article information and this has been encoded using IIIF Ranges and an example can be seen at:</p>
<p><a href="http://dams.llgc.org.uk/iiif/2.0/1097087/manifest.json">http://dams.llgc.org.uk/iiif/2.0/1097087/manifest.json</a></p>
<p>The ranges contain an article title, author and type although only the title is shown through the Universal Viewer. The Universal Viewer displays these ranges in the index panel and this manifest can be seen in isolation at:</p>
<p><a href="https://viewer.library.wales/1097087">https://viewer.library.wales/1097087</a></p>
<p>When viewing this manifest in the Journals website the Universal Viewer shows the current issue within its context of running Journals issues:</p>
<p><a href="https://journals.library.wales/view/1093205/1097087">https://journals.library.wales/view/1093205/1097087</a></p>
<p>In the index section you can view the issues either by label (from the Journal Title IIIF Collection) or by navDate.</p>
<h3 id="missing-pages">Missing Pages</h3>
<p>During the processing of the second Journals project the NLW developed a tool which would allow the re-arrangement of images and also the adding of missing pages where the original pages weren’t available for digitisation. These images are noted in the METS document and in the generated IIIF manifests these appear as canvases without a IIIF Image service. See the following as an example which is a slightly extreme example picked up during testing. We believe that there was only one image (page 16) available for this issue hence the first 16 pages are marked as missing. The more common case is where a single image is missing in a sequence:</p>
<p><a href="https://viewer.library.wales/2886549">https://viewer.library.wales/2886549</a> (<a href="http://dams.llgc.org.uk/iiif/2.0/2886549/manifest.json">http://dams.llgc.org.uk/iiif/2.0/2886549/manifest.json</a>)</p>
<h3 id="broken-images">Broken Images</h3>
<p>During the validation of images we undertook during development we found 6 images which required attention. Some of these could be regenerated from the original tiff file but some images will require further work after the project has completed. One jp2 in particular passes jhove validation and jpylyzer analysis but still doesn’t work using IIP image and will have to be reported. To create a valid manifest we treated these errors similar to above and marked them as missing. See page 35 of the following:</p>
<p><a href="https://viewer.library.wales/2161205">https://viewer.library.wales/2161205</a> (<a href="http://dams.llgc.org.uk/iiif/2.0/2161205/manifest.json">http://dams.llgc.org.uk/iiif/2.0/2161205/manifest.json</a>)</p>
<h3 id="rights-protected-images">Rights protected Images</h3>
<p>In the original Welsh Journals project there are a number of pages which are protected due to copyright reasons. Some images have been blanked but others are protected by the Fedora rights management process. These images present a 401 when requested. We looked into how this would work in the Universal Viewer and if it was a use case for the IIIF Authentication API. The following manifest responds to 401s in two different ways:</p>
<p><a href="https://viewer.library.wales/1272050">https://viewer.library.wales/1272050</a> (<a href="http://dams.llgc.org.uk/iiif/2.0/1272050/manifest.json">http://dams.llgc.org.uk/iiif/2.0/1272050/manifest.json</a>)</p>
<p>Pages 162 and 163 return a 401 if the info.json is requested with a customer error message in Welsh and English. If you request these images using CURL you get the following response:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HTTP/1.1 401 Nid yw'r hawliau gennym i arddangos y deunydd hwn. - We do not have the rights to display this material.
</code></pre></div></div>
<p>This works in the Universal Viewer as it displays the message in a information box. The possibly more correct way of doing this is in page 166 to 177 where the info.json displays a rights service with a description saying the content is unavailable. Unfortunately currently this isn’t working in the UV and more experimentation is needed to see what needs to be in the info.json to make this use case work. The experimental info.json for page 166 is:</p>
<p><a href="https://damsssl.llgc.org.uk/iiif/2.0/image/1272222/info.json">https://damsssl.llgc.org.uk/iiif/2.0/image/1272222/info.json</a></p>
<h3 id="validation">Validation</h3>
<p>One of the things we found most useful during the development of the website was to have a validation script that would go through the sitemap and validate all of the IIIF collections and manifests and identify missing fields that were considered ‘mandatory’ for the project. The validator for this project checked the following:</p>
<ul>
<li>All collections and manifests were valid JSON and existed in the cache</li>
<li>All Journal titles and Manifests had valid navDates - there were a handful of issues which didn’t have dates and even after investigation dates couldn’t be assigned.</li>
<li>All Journal titles had descriptions and frequency information (not all missing frequencies could be fixed by the end of the project) in the EDM</li>
<li>All Issues had a search api pointer</li>
<li>All images responded to at least an info.json request</li>
</ul>
<p>This validator was run regularly and on a daily basis towards the end of the project. The navDates were created by converting textual string dates e.g. ‘Nov 1852’ or ‘Spring 1924’ into ISO dates and so the validation picked out problems with this conversion. It also picked out mistakes in the data like 30th Feb 2001.</p>
<h2 id="indexing">Indexing</h2>
<p>In order to deliver site content in a timely manner, we have indexed the IIIF manifests, EDM and Sitemap to a Solr search index. This allows our front-end web developers to converse with a simple HTTP search API and receive JSON content for inclusion in the website.</p>
<p>We developed an indexing script which firstly iterated over the Sitemap in order to collect all of the top-level manifest documents for the project. Each manifest was then processed and a page-level document was indexed to solr containing the full text contained on the journal page along with associated metadata for faceting e.g Issue Date, Publication Title, page Order within issue (used to land on correct page within the Universal Viewer). We also indexed a single ‘publication’ document which was used for the publication information page.</p>
<p>Page-level documents needed to store the location of each word on the page in pixel co-ordinates. This is stored as ALTO XML but converted on the fly to use IIIF Annotations. Storing the annotations as separate records in SOLR would have meant a lot of redundant information being stored and it wouldn’t be possible to make use of SOLRs ranking algorithms which can show results containing multiple word matches on a page higher. We devised a cut down version of an annotation in JSON for storing the string and coordinates and stored this as a string within solr. This could be extracted in the IIIF search API implementation in order to highlight search terms on the page within the Universal Viewer.</p>
<p>Each word would be marked up as [x,y,width,height, word] e.g. [“671”,”178”,”21”,”14”,”cymdeithas”] and each word was stored in an array of all words on the page, which made up the Json object.</p>
<p>We considered a number of alternatives to compressing the annotations into SOLR including:</p>
<ul>
<li>Reading the Annotation List at query time
We were concerned this might lead to performance problems. We currently have 100 results per page and this could lead to 100 annotation list requests per user per search. It would also take time for search implementation to processes the JSON and find the annotations for that result.</li>
<li>Storing the annotations in a separate annotation store
This would also lead to similar amount of requests to the above and we would have to develop a similar method of matching the initial query with annotations. We were also concerned about keeping another system alongside SOLR up to date.</li>
<li>Indexing the annotation as annotations (like the SimpleAnnotationServer does)
This would produce a SOLR instance that was large and contained repeated information for example over 1 million copies of the same motivation. We would also have to work on developing something that would match searches for phrases as these would cross annotations assuming we encoded them at word level. If we encoded them at another level e.g. line or paragraph the highlight box in the Universal Viewer would be bigger than it needs to be.</li>
</ul>
<p>An example Solr Page document is included below with comments after the – symbol.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> "Doctype":"page",
"page_coords":"[[\"580\",\"299\",\"163\",\"84\",\"YR\"],[\"773\",\"295\",\"31\",\"84\",\"\"],[\"834\",\"295\",\"861\",\"88\",\"HYFFORDDWR.\"],[\"347\",\"524\",\"104\",\"42\",\"Cyp.\"],[\"473\",\"524\",\"111\",\"54\",\"III.]\"],[\"1000\",\"520\",\"129\",\"48\",\"MAI,\"]]", -- encoded page annotations
"page_text":" YR HYFFORDDWR. Cyp. III.] MAI", -- the above text without coordinate information
"Id":"2005214", -- cutdown page identifier
"Publicationpid":"llgc-id:2004553", -- cut down identifier of title
"publicationtitle":"Yr hyfforddwr", -- title from EDM dc:title
"publicationtitle_facet":"Yr hyfforddwr", -- SOLR processed copy of above for faceting
"publisherdetails_en":"Hughes and Co.", -- from EDM dc:publisher[@xml:lang=en]
"publisherdetails_cy":"Hughes and Co.", -- from EDM dc:publisher[@xml:lang=en]
"Publicationlanguage":["cy"], -- from EDM dc:language
"publicationdetails_en":"The monthly Welsh language religious periodical of the Campbellite Baptists in Wales. The periodical's main contents were religious articles and poetry. The periodical was edited by the poet and man of letters, John Edwards (Meiriadog, 1813-1906). Associated titles: Yr Hyfforddiadyr (1855); Y Llusern (1858).", -- from EDM dc:description[@xml:lang=en]
"publicationdetails_cy":"Cylchgrawn crefyddol, Cymraeg ei iaith, y Bedyddwyr Campbellaidd yng Nghymru. Prif gynnwys y cylchgrawn oedd erthyglau crefyddol a barddoniaeth. Golygwyd y cylchgrawn gan y bardd a llenor, John Edwards (Meiriadog, 1813-1906). Teitlau cysylltiol: Yr Hyfforddiadyr (1855); Y Llusern (1858).", -- from EDM dc:description[@xml:lang=cy]
"Issuepid":"llgc-id:2005213", -- cut down issue identifier
"issuelabel":"Cyf. III rhif. 5 - Mai 1854", -- from Issue manifest label
"Issueorder":31, -- Important for linking into the Universal Viewer index of issue within the Title (from IIIF Collection)
"isodate":"1854-05-01T00:00:00Z", -- From Issue Manifest
"Issuedate_decade":1850, -- Created from Nav date for facets and front page graphic.
"Issuedate_year":1854, -- Created from Nav date for facet
"Issuedate_month":5, -- Created from Nav date for facet
"Issuedate_day":1, -- Created from Nav date for facet
"Issuedate_weekday":1, -- Created from Nav date for facet
"issuerightsurl":"https://creativecommons.org/publicdomain/mark/1.0/", -- from license field in IIIF manifest
"Pagepid":"llgc-id:2005214", -- cutdown Page identifier
"Pagelabel":"[65]", -- from Issue manifest, canvas label
"Pageorder":2, -- Important for linking into the Universal Viewer, index of canvas in sequence from issue manifest.
"Project":"scif", -- internal project identifier. If it has rangers this would be ccymod.
"timestamp":"2017-04-07T12:15:48.112Z"} -- indexing timestamp to for debugging purposes.
</code></pre></div></div>
<p>Due to the iterative development process found in an Agile project like this, we needed to implement caching on the indexing server to reduce stress on the IIIF server. Certain content like the Annotation Lists was unlikely to change between iterations so a gziped cache of the JSON content was stored locally with the indexer. A MD5 sum of the URL was used to name the file on the filesystem so it could be easily matched for future cache requests. Gzipping kept the file sizes down and the entire cache of the project is only 12GB in size.</p>
<p>In order to access the metadata, as IIIF does not promote the storage of structured metadata within the manifest, we instead opted to provide access to the metadata in an EDM file linked from the manifests. This enabled us to use many existing vocabularies such as Dublin Core, RDF, DCTerms to further mark up the data.</p>
<h2 id="website">Website</h2>
<p>The website is written in PHP and is built on top of SOLR. The majority of the searching and the website front page is generated directly from queries into SOLR. The IIIF manifests and collections come in when you start viewing an item using the Universal Viewer. The Universal Viewer reads the IIIF Collection and Manifests to produce an index showing all of the issues of a Journal and Articles if present. The metadata on the right hand panel is generated from the current issue which is shown in the central image panel.</p>
<h3 id="supporting-iiif-search-api">Supporting IIIF search API</h3>
<p>We have developed an implementation of the IIIF search API which uses the same SOLR instance as the website and allows searching within the Universal Viewer. It is also used when navigating between the results page into an item. This was a complicated development due to the way we had decided to compress the annotations in SOLR.</p>
<p>One of the issues is it is very difficult to predict the number of results per IIIF search results ‘page’ (page as in results pagination). To give a working example if you search for a common word like ‘the’, chances are you will get multiple results per page. The IIIF search implementation will search SOLR for this issue and get x pages returned which have at least one occurrence of ‘the’. When the annotations are decompressed from SOLR this will lead to x * the number of occurrences of ‘the’ on each page. It is possible to support paging of the returned SOLR records but this won’t tally with the actual amount of results per page. In the current implementation it cuts off at 100 results but we have considered whether it would be allowable in the Search API specification and supported in the Universal Viewer to have varying amounts of results per page. This would mean we couldn’t support the startIndex field in the results. The other alternative is to implement some kind of paging cache outside of SOLR which keeps track of the results to a query.</p>
<p>The second problem we came across was linking between the results in the website e.g:</p>
<p><a href="https://journals.library.wales/search?query=%22Pryse+Family%22&range%5Bmin%5D=1735&range%5Bmax%5D=2007">https://journals.library.wales/search?query=%22Pryse+Family%22&range%5Bmin%5D=1735&range%5Bmax%5D=2007</a></p>
<p>and if you click on the first result you get to the viewer which doesn’t highlight the words on the page. The reason for this is that you can pass complicated query parameters to SOLR including; OR, AND, NOT and speech marks among others (see https://wiki.apache.org/solr/SolrQuerySyntax for full details) which result in hits in the SOLR search but in the IIIF search implementation this needs to be matched with the compressed annotations. The common features of OR, AND, NOT are supported but currently speech mark phrases are unsupported.</p>
<h3 id="developments-with-universal-viewer">Developments with Universal Viewer</h3>
<p>Throughout our project we have used a standard URI structure for our document viewers of /[publicationpid]/[issuepid]/[pagenumber], for example:</p>
<ul>
<li><a href="http://newspapers.library.wales/view/3600141/3600147/64">http://newspapers.library.wales/view/3600141/3600147/64</a></li>
<li><a href="https://journals.library.wales/view/1050541/1051974/8">https://journals.library.wales/view/1050541/1051974/8</a></li>
</ul>
<p>To continue following these standards while using the UniversalViewer we had to address the problem of detecting changes in the front-end such as users navigating through issues or pages and update the URI to reflect this. JavaScript was used to process the hash parameters and to detect when either the m (issue) value or cv (page) value, and to replace the URI segments with the updated values. The issuepid was retrieved from the manifest using the publicationpid.</p>
<p>Originally published at 23:59, 11 April 2017 (BST) on the <a href="https://dev.llgc.org.uk/wiki/index.php?title=IIIF_Journals">NLW Dev Site</a>.</p>Glen RobsonNLW Journals write up from 2017. I often find that I link to this article but the original isn’t always available so I have copied it here for posterity. The original is available on the NLW Dev Site.AI and IIIF Ideas2020-09-08T12:27:22+00:002020-09-08T12:27:22+00:00/iiif,ai/2020/09/08/AI-ideas<p>I am following the <a href="https://course.fast.ai/">Fast AI course</a> and one of the suggestions was to blog as you follow the course. This blog will document some ideas for the <a href="https://course.fast.ai/videos/?lesson=2">second session</a>. In the second session they look at creating an Image classifier. In the example they use Bing to get examples of three different types of Bears; Grizzly, Black and Teddy. The build a machine learning tool that when supplied with an image of a bear will tell them the type of bear.</p>
<p>I would like to use IIIF images, but the issue is getting labeled data that I can easily use. Having worked at the National Library of Wales I know their data best. A few options I’ve been thinking about:</p>
<h2 id="lctgm-classifier">LCTGM Classifier</h2>
<p>LCTGM stands for <a href="https://www.loc.gov/rr/print/tgm1/">Library of Congress Thesaurus for Graphic Materials</a> and is a way to add subjects to graphical materials. It has the advantage of splitting out the subject heading into discreet parts namely Topic, Geographic and Temporal. I wonder if it would be possible to give the predictor an image and it will return suitable topics for that image.</p>
<h3 id="data">Data</h3>
<p>While working at the NLW there were a number of digitised image collections that were catalogued using LCTGM and these include:</p>
<ul>
<li>the <a href="https://www.library.wales/discover/digital-gallery/photographs/john-thomas">John Thomas collection</a>, which is a photographic collection but contains many pictures of people.</li>
<li>the <a href="https://www.library.wales/discover/digital-gallery/photographs/p-b-abery">P B Abery collection</a> which contains a good mix of people and places.</li>
<li>the <a href="https://www.library.wales/discover/digital-gallery/photographs/geoff-charles">Geoff Charles collection</a> which is a very large collection. Geoff Charles was a news photographer so there is a good mix of pictures but unfortunately this was catalogued at story level so any metadata applies to numerous images rather than a 1 to 1 relationship.</li>
</ul>
<p>All of the above have IIIF images associated with them. Unfortunately the metadata isn’t directly downloadable but a number have been shared with Wikidata. For example to find all of the images from P B Abery collection you can run the following query:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SELECT ?item ?itemLabel ?manifest ?subjectLabel
WHERE
{
?item wdt:P195 wd:Q74836239.
?item wdt:P6108 ?manifest
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}
</code></pre></div></div>
<p>Once you have the manifest e.g:</p>
<p><a href="https://damsssl.llgc.org.uk/iiif/2.0/1293458/manifest.json">https://damsssl.llgc.org.uk/iiif/2.0/1293458/manifest.json</a></p>
<p>you can work out the ID and get to the metadata by going to:</p>
<p><a href="http://dams.llgc.org.uk/behaviour/llgc-id:1294464/fedora-bdef:mets/mets">http://dams.llgc.org.uk/behaviour/llgc-id:1294464/fedora-bdef:mets/mets</a></p>
<p>The LCTGM headings are in the MODS section of the METS documents.</p>
<h3 id="issues-and-thoughts">Issues and thoughts</h3>
<ul>
<li>P B Abery collection seems a good match for machine learning as it has a good range of subjects and is individually catalogued.</li>
<li><strong>But</strong> it will be very time consuming to download 1,746 manifests plus images.</li>
<li>Some subjects will be more heavily populated than others… For the purposes of the demo I could restrict it to the top 3 most popular subjects</li>
<li>Test images will need to be restricted to black and white photographs probably taken in a similar era (1911 - 1948)</li>
<li>If it works it could be used to assign sensible topics to historical photographs.</li>
</ul>
<p>I think on balance the effort to download the metadata and parse the METS is putting me off this idea.</p>
<h2 id="tribunal-records-form-identification">Tribunal records form identification</h2>
<p>While at the NLW I was involved with a crowd sourcing project to transcribe the <a href="https://www.library.wales/discover/digital-gallery/archives/cardiganshire-great-war-tribunal-appeals-records#?c=&m=&s=&cv=&xywh=-2068%2C-1%2C7731%2C5641">Cardiganshire War Tribunal records</a>. This is an amazing archive of records where people applied for exemption from enlisting into the Army during WW1. One of the issues with the crowdsourcing was that we found there were different types of forms in the archive, some were the same form but a different version as new versions were released during the war. Others were appeals after an initial application. Each different form required different fields to be entered. To solve this users were asked to identify which form they were transcribing before they started filling in the fields. Now this data has been entered would it be possible to create a predictor that could tell you which type of form you were looking at?</p>
<h3 id="data-1">Data</h3>
<p>This data is available as IIIF Annotations on GitHub:</p>
<p><a href="https://github.com/NLW-paulm/Welsh-Tribunal-annotations">https://github.com/NLW-paulm/Welsh-Tribunal-annotations</a></p>
<p>There is one JSON file per district and 11 districts in total. A district is made up of all of the forms and letters that the tribunal reviewed. They are ordered so that 1 persons application, appeal and any letters are located together. The JSON files are IIIF Annotation Lists and it looks like there is one annotation per page. The text of the annotation is split into fields e.g:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"chars": "Name of Local Tribunal: Aberaeron Borough/Urban District<p>Number of Case: 1<p>Name: Dewi Trefor Jones <p>Address: Castle House Aberaeron <p>Occupation, profession or
business: Draper's Assistant <p>Attested or not attested: Attested <p>Grounds: I am 73 years of age, in ill health and can't stand any work. <p>Signature of appellant: John Hugh Jones <p>Addres
s of appellant: Castle House, Aberaeron <p>Occupation, profession or business: Draper <p>Why appellant acts for the man: Employer <p>Date: 1916-03-04T10:41:02.000Z<p>Tag: Pink R43/R44: Page 1"
</code></pre></div></div>
<p>Could be ordered as:</p>
<ul>
<li><strong>Name of Local Tribunal:</strong> Aberaeron Borough/Urban District</li>
<li><strong>Number of Case:</strong> 1</li>
<li><strong>Name:</strong> Dewi Trefor Jones</li>
<li><strong>Address:</strong> Castle House Aberaeron</li>
<li><strong>Occupation, profession or business:</strong> Draper’s Assistant</li>
<li><strong>Attested or not attested:</strong> Attested</li>
<li><strong>Grounds:</strong> I am 73 years of age, in ill health and can’t stand any work.</li>
<li><strong>Signature of appellant:</strong> John Hugh Jones</li>
<li><strong>Address of appellant:</strong> Castle House, Aberaeron</li>
<li><strong>Occupation, profession or business:</strong> Draper</li>
<li><strong>Why appellant acts for the man:</strong> Employer</li>
<li><strong>Date:</strong> 1916-03-04T10:41:02.000Z</li>
<li><strong>Tag:</strong> Pink R43/R44: Page 1</li>
</ul>
<p>The bit I am interested in is the Tag which says what type of page/document this is. Possible options are:</p>
<ul>
<li>Tag: Beige R186/187, page 1</li>
<li>Tag: Beige R186/187, page 2</li>
<li>Tag: Beige R41/42: Page 1</li>
<li>Tag: Beige R41/42: Page 2</li>
<li>Tag: Blue R52/53, page 1</li>
<li>Tag: Blue R52/53, page 2</li>
<li>Tag: Pink R43/R44: Page 1</li>
<li>Tag: Pink R43/R44: Page 2</li>
<li>Tag: Unknown document type</li>
</ul>
<p>The Unknown document types are usually letters of support. A full annotation looks as follows:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> {
"@type": "oa:Annotation",
"motivation": "sc:painting",
"on": "https://damsssl.llgc.org.uk/iiif/2.0/4001851/canvas/4001854.json#xywh=0,0,3497,4413",
"resource": {
"@type": "cnt:ContentAsText",
"chars": "Description: Letter from Fred Burris & Sons from Horse Shoes and Mule Shoes for war department of British Government.<p>Transcription: We understand from Mr John Rees, 16 Albert St, that exemption has been refused him. We however, suggest that there must be some error here, particularly as this man is badged No. L 16876, and consequently can only be taken with the permission of the Ministry of Munitions, \nWe think we have previously explained the matter and are at a loss to understand what has happened. The only thing, therefore, is for us to communicate with the War Office and inform them of the details, \n<p>Name of Tribunal: Aberaeron Borough/Urban District<p>Number of Case: Appeal Form No 4<p>Tag: Unknown document type",
"format": "text/plain"
}
},
</code></pre></div></div>
<p>The on field gives the required IDs for the IIIF Image and manifest the annotation applies to.</p>
<h3 id="issues-and-thoughts-1">Issues and thoughts</h3>
<ul>
<li>This data has now been captured for all of the digitised tribunal records, so a predictor may not be that useful</li>
<li>Could potentially be applied to other collections. Most tribunal records were destroyed although it seems there are copies in <a href="https://www.flickr.com/photos/manchesterarchiveplus/albums/72157632619308865/">Manchester Archive</a> and some from the <a href="https://discovery.nationalarchives.gov.uk/details/r/C14091136">National Archives</a></li>
</ul>Glen RobsonI am following the Fast AI course and one of the suggestions was to blog as you follow the course. This blog will document some ideas for the second session. In the second session they look at creating an Image classifier. In the example they use Bing to get examples of three different types of Bears; Grizzly, Black and Teddy. The build a machine learning tool that when supplied with an image of a bear will tell them the type of bear.IIIF Tribunal Image Classifier2020-09-08T12:27:22+00:002020-09-08T12:27:22+00:00/iiif,ai/2020/09/08/image-classifier<p>As <a href="/iiif,ai/2020/09/08/AI-ideas.html">mentioned previously</a>, I am following the <a href="https://course.fast.ai/">Fast AI course</a> and as part of the second lesson you are encouraged to develop an Image Classifier. An Image Classifier is a type of program which can look at an image and decide which bucket the image should go in. In the first lesson the example Image Classifier let you know if an image was a picture of a dog or a cat and in this weeks lesson the Image Classifier distinguished between pictures of Brown, Grizzly and Teddy Bears.</p>
<p>In the previous post I discussed a couple of ideas but decided to go with the Tribunal records identification as this seemed the easiest to get started with. As a reminder the <a href="https://www.library.wales/discover/digital-gallery/archives/cardiganshire-great-war-tribunal-appeals-records#?c=&m=&s=&cv=&xywh=-2068%2C-1%2C7731%2C5641">Cardiganshire War Tribunal records</a> are a fascinating collection of records covering the communication between the community in Ceredigion and the Military Tribunals who decided if applicants were allowed to avoid military conscription during WW1. The records were part of a National Library of Wales (NLW) crowdsourcing project working with volunteers to both transcribe the records but also to retain a link between the transcription and the field on the form. The completed transcriptions were made available by the NLW and are available on <a href="https://github.com/NLW-paulm/Welsh-Tribunal-annotations">Paul McCann’s Github Page</a> as IIIF Annotations.</p>
<p>The archive contains many different forms and supporting correspondence. My plan is to create a classifier which will identify the form type. This is now mostly an academic exercise as all of the pages have been identified and transcribed but if in theory someone else was to digitise a set of tribunal records they could use this tool to identify which type of documents they have. I can test this theory using the sample tribunal record copies in <a href="https://www.flickr.com/photos/manchesterarchiveplus/albums/72157632619308865/">Manchester Archive</a> and the <a href="https://discovery.nationalarchives.gov.uk/details/r/C14091136">National Archives</a>.</p>
<h2 id="preparing-the-data">Preparing the data</h2>
<p>To fit the data structure discussed in the course there should be a directory per category (or bucket) containing images in that set. So there should be 9 directories containing images for the following document types:</p>
<ul>
<li>Tag: Beige R186/187, page 1</li>
<li>Tag: Beige R186/187, page 2</li>
<li>Tag: Beige R41/42: Page 1</li>
<li>Tag: Beige R41/42: Page 2</li>
<li>Tag: Blue R52/53, page 1</li>
<li>Tag: Blue R52/53, page 2</li>
<li>Tag: Pink R43/R44: Page 1</li>
<li>Tag: Pink R43/R44: Page 2</li>
<li>Tag: Unknown document type</li>
</ul>
<p>The dataset from Paul, contains Annotation Lists for each of the different districts that make up the county of Cardiganshire (now called Ceredigion). The districts are:</p>
<ul>
<li>Aberaeron Borough District</li>
<li>Aberaeron Rural District</li>
<li>Aberystwyth Borough District</li>
<li>Aberystwyth Rural District</li>
<li>Cardigan Borough District</li>
<li>Cardigan Rural District</li>
<li>Lampeter Rural District</li>
<li>Lampeter Urban District</li>
<li>Llandysyl rural District</li>
<li>Newquay District</li>
<li>Tregaron District</li>
</ul>
<p>Inside these files there are lists of annotations and there is one annotation per page which looks as follows:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{
"@type": "oa:Annotation",
"motivation": "sc:painting",
"on": "https://damsssl.llgc.org.uk/iiif/2.0/4001851/canvas/4001854.json#xywh=0,0,3497,4413",
"resource": {
"@type": "cnt:ContentAsText",
"chars": "Description: Letter from Fred Burris & Sons from Horse Shoes and Mule Shoes for war department of British Government.
<p>Transcription: We understand from Mr John Rees, 16 Albert St, that exemption has been refused him. We however,
suggest that there must be some error here, particularly as this man is badged No. L 16876, and consequently can only
be taken with the permission of the Ministry of Munitions, \nWe think we have previously explained the matter and are
at a loss to understand what has happened. The only thing, therefore, is for us to communicate with the War Office and
inform them of the details, \n<p>Name of Tribunal: Aberaeron Borough/Urban District<p>Number of Case: Appeal Form No 4
<p>Tag: Unknown document type",
"format": "text/plain"
}
},
</code></pre></div></div>
<p>The first job is to find the page <code class="language-plaintext highlighter-rouge">Tag</code> and link it to the image it references. The <code class="language-plaintext highlighter-rouge">Tag</code> is buried in the <code class="language-plaintext highlighter-rouge">resource.chars</code> part of the annotation and to pick it out we need to split the string and find <code class="language-plaintext highlighter-rouge"><p>Tag: </code> and then this will be followed by the Tag. I used the following python method to do this conversion:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>def string2json(line):
data = {}
for field in line.split('<p>'):
# print (field)
name, value = field.split(':')[0], ':'.join(field.split(':')[1:])
# print("Name: {}, value: {}".format(name,value))
data[name] = value.strip()
return data
</code></pre></div></div>
<p>This will return a hash table with all of the fields in the string separated so <code class="language-plaintext highlighter-rouge">data['Tag']</code> will return the page tag.</p>
<p>The second part of the task is to identify the image this annotation points to. To start we need to find the canvas which is in the <code class="language-plaintext highlighter-rouge">on</code> field:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"on": "https://damsssl.llgc.org.uk/iiif/2.0/4001851/canvas/4001854.json#xywh=0,0,3497,4413",
</code></pre></div></div>
<p>If this was a set of images I didn’t know then I would find the manifest, look for this canvas id and then find the reference to the IIIF Image. Luckily I can take a short cut as I know the last number (<code class="language-plaintext highlighter-rouge">4001854</code>) before the .json is actually the Image Identifier. I can then use the following to get access to the Image information:</p>
<p>http://dams.llgc.org.uk/iiif/2.0/image/<strong>4001854</strong>/info.json</p>
<p>One decision that was required was the size of the image to request. The course recommends</p>
<p><em>“We don’t have a lot of data for our problem (150 pictures of each sort of bear at most), so to train our model, we’ll use RandomResizedCrop with an image size of 224 px, which is fairly standard for image classification, and default aug_transform”</em></p>
<p>(From <a href="https://github.com/fastai/fastbook/blob/master/02_production.ipynb">‘Training Your Model, and Using It to Clean your Data’</a>)</p>
<p>so I can request a IIIF Image at this size by running:</p>
<p>http://dams.llgc.org.uk/iiif/2.0/image/4001854/full/<strong>224,</strong>/0/default.jpg</p>
<p><img src="https://damsssl.llgc.org.uk/iiif/2.0/image/4001854/full/224,/0/default.jpg" alt="Example Tribunal Image" /></p>
<p>The full code for the program to extract the <code class="language-plaintext highlighter-rouge">Tags</code> and Images from the Annotation Lists is called <a href="https://github.com/glenrobson/Welsh-Tribunal-annotations/blob/master/scripts/typeImage.py">typeImage.py</a> and can be found on <a href="https://github.com/glenrobson/Welsh-Tribunal-annotations/blob/master/scripts/typeImage.py">GitHub</a>. Once this program has run you will have a directory for each Tag containing the following number of images:</p>
<ul>
<li>Beige_R186-187_page_1: 138 images</li>
<li>Beige_R186-187_page_2: 137 images</li>
<li>Beige_R41-42_Page_1: 1,331 images</li>
<li>Beige_R41-42_Page_2: 1,350 images</li>
<li>Blue_R52-53_page_1: 701 images</li>
<li>Blue_R52-53_page_2: 690 images</li>
<li>Pink_R43-R44_Page_1: 1,618 images</li>
<li>Pink_R43-R44_Page_2: 1,609 images</li>
<li>Unknown_document_type: 971 images</li>
</ul>
<p>To access it in the next steps I needed to make it public so I zipped it up and put it here: <a href="https://iiif.gdmrdigital.com/ww1-tribunal/TribunalTypeImages.zip">TribunalTypeImages.zip</a>.</p>
<h2 id="training-the-model">Training the model</h2>
<p>The next part of the task was to take this zip file of images and train a model that can identify the different forms. The course recommends doing this by creating a Jupiter Notebook. I haven’t quite got my heard around how these notebooks fit into or compares with virtual machines, Docker or Vagrance but they allow you to both run code and mix in Markdown descriptions to comment on the process. Using the Google Colab software you can run these Jupiter notepads on their virtual machine infrastructure for free. One of the main advantages of this approach is that Google Colab provides Virtual Machines with performant graphics cards which appear essential for training models. This was mentioned in the first lesson and I had a go at running the Jupiter notebook locally but even though my machine isn’t slow, it took a surprisingly long time to train the basic example models. Even though I was sorely tempted, lesson one advised against spending <em>(wasting)</em> time building your own computer with a powerful graphics card and just use the free or low cost options they link to in the course.</p>
<p>The Jupiter notebook is embedded in this blog as a read only version with the saved output when I ran it.</p>
<p>You should be able to open a version you can run yourself by clicking the Open in Colab button below. In the Colab version, when you see a block of code you should be able to run it by moving your mouse cursor to the top left part of the code block. This should then show a play button. You should run the code blocks in order and wait for them to finish before going onto the next one.</p>
<script src="https://gist.github.com/glenrobson/969a6a25b4822c7f37945bf85087b7e9.js"></script>
<h2 id="results-and-reflection">Results and reflection</h2>
<p>I was really pleased to see the results of the Image Classification. It worked on most of the images and for the ones that it didn’t there seemed to be clear reasons why not. It would be interesting to look further into the top losses to see if this could be used to identify data that needs correcting. The only real downside to this project is the lack of applicability to real world problems. Its very specific to this collection but I wonder if the techniques could be applied to identify different types of objects in a collection. One thought I’ve had is whether you could train a classifier to identify types of images e.g. Maps, Newspapers, Manuscripts etc. This maybe something I try next although finding the source data will more challenging.</p>Glen RobsonAs mentioned previously, I am following the Fast AI course and as part of the second lesson you are encouraged to develop an Image Classifier. An Image Classifier is a type of program which can look at an image and decide which bucket the image should go in. In the first lesson the example Image Classifier let you know if an image was a picture of a dog or a cat and in this weeks lesson the Image Classifier distinguished between pictures of Brown, Grizzly and Teddy Bears.IIIF from Scratch2018-01-12T12:27:22+00:002018-01-12T12:27:22+00:00/iiif/2018/01/12/iiif-from-scrtach<p>I’ve been trying to learn Welsh for a number of years but unfortunately I’m not a natural linguist. So when one of our neighbours gave our Children an old Welsh book to read I set about using it as a challenge and translating it. Being prone to technical procrastination rather than getting on with the translation I’ve had a look at how I can turn this book into a IIIF resource. I hope this will be useful for people looking to make their images available as IIIF but don’t have the time or resources to invest in a comprehensive IIIF stack.</p>
<h2 id="stage-1---digitisation">Stage 1 - Digitisation</h2>
<p>So the quality of the digitisation isn’t going to win any prizes but I used a HP Envy 5546 combination printer and Scanner:</p>
<figure>
<a href="https://support.hp.com/us-en/product/hp-envy-5540-all-in-one-printer-series/5447939/model/5447940/drivers"><img src="/assets/images/HP-Envy-5546.jpg" /></a>
<figcaption><a href="https://support.hp.com/us-en/product/hp-envy-5540-all-in-one-printer-series/5447939/model/5447940/drivers" title="HP Envy 5546">HP Envy 5546</a>.</figcaption>
</figure>
<p>The provided ‘HP Easy Scan’ software has a nice simple interface for scanning. For scanning a book like this you can click ‘return’ to capture another scan allowing you to faff with the book on the scanner trying to ensure it doesn’t fall off the table. As its a graphical book I started off with the ‘Photos, Graphics, Etc.’ setting but this was a bit too clever for its own good and cropped the most graphical part of the page. Once switching to the ‘Documents with Color’ it scanned the page as expected.</p>
<p>I exported the scanned images (14 pages) to the following formats:</p>
<ul>
<li>jp2 - I won’t use this in this blog post but in future I plan to write a post about using these images with one if the more feature full image servers. See <a href="https://github.com/IIIF/awesome-iiif#image-servers">IIIF Awesome for a list</a>.</li>
<li>tiff</li>
</ul>
<p>The images are named page001 to page014.</p>
<h2 id="stage-2---making-the-images-through-iiif">Stage 2 - Making the images through IIIF</h2>
<p>For this project I’m looking for a no server option that ideally will be hosted through this blog. The fully featured IIIF image servers require a service to be running to do the required conversions on a single source image. An alternative is to chop up the source image into tiles and store them on disk. This allows you to get all of the zoomable features of IIIF without running a server. The limitation is that you won’t get all of the functionality a IIIF image server can support, particularly custom regions of an image. I’ll demonstrate this limitation later.</p>
<p>To chop up the images I’m going to use <a href="https://github.com/zimeon/iiif/tree/master/demo-static">Simeon’s tile generator</a>. Following the install instructions I do the following:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hostname:website gmr$ cd /tmp/
hostname:tmp gmr$ git clone git://github.com/zimeon/iiif.git
Cloning into 'iiif'...
remote: Counting objects: 5514, done.
remote: Total 5514 (delta 0), reused 0 (delta 0), pack-reused 5514
Receiving objects: 100% (5514/5514), 32.25 MiB | 1.71 MiB/s, done.
Resolving deltas: 100% (1825/1825), done.
iPhone-Glen:tmp gmr$ cd iiif/
hostname:iiif gmr$ ls
CHANGES.rst MANIFEST.in demo-static iiif_static.py pypi_upload.md testimages
CONTRIBUTING.md README etc iiif_testserver.py run_tests.sh testpages
INSTALLATION.md README.rst iiif iiif_testserver.wsgi run_validate.sh tests
LICENSE.txt demo-auth iiif_cgi.py iiif_testservertest.py setup.py
hostname:iiif gmr$ sudo pip install 'Pillow<4.0.0'
Password:
The directory '/Users/gmr/Library/Caches/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
The directory '/Users/gmr/Library/Caches/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
Collecting Pillow<4.0.0
Downloading Pillow-3.4.2-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl (3.4MB)
100% |████████████████████████████████| 3.5MB 372kB/s
Installing collected packages: Pillow
Successfully installed Pillow-3.4.2
hostname:iiif gmr$
</code></pre></div></div>
<p>The next stage is to feed in the tiff images and give an output directory for the IIIF tiles. Trying the first page:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hostname:iiif gmr$ mkdir -p ../welsh-book/page001
hostname:iiif gmr$ ./iiif_static.py --write-html ../welsh-book/page001 -d ../welsh-book/page001 --api-version=2.1 ~/Documents/images/welsh_book/tiff/page001.tif
iiif_static.py: source file: /Users/gmr/Documents/images/welsh_book/tiff/page001.tif
iiif.static: ../welsh-book/page001 / page001/0,0,512,512/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/0,512,512,512/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/0,1024,512,512/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/0,1536,512,512/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/0,2048,512,286/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/512,0,512,512/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/512,512,512,512/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/512,1024,512,512/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/512,1536,512,512/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/512,2048,512,286/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/1024,0,512,512/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/1024,512,512,512/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/1024,1024,512,512/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/1024,1536,512,512/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/1024,2048,512,286/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/1536,0,160,512/160,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/1536,512,160,512/160,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/1536,1024,160,512/160,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/1536,1536,160,512/160,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/1536,2048,160,286/160,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/0,0,1024,1024/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/0,1024,1024,1024/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/0,2048,1024,286/512,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/1024,0,672,1024/336,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/1024,1024,672,1024/336,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/1024,2048,672,286/336,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/0,0,1696,2048/424,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/0,2048,1696,286/424,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/full/212,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/full/212,292 -> page001/full/212,
iiif.static: ../welsh-book/page001 / page001/full/106,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/full/106,146 -> page001/full/106,
iiif.static: ../welsh-book/page001 / page001/full/53,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/full/53,73 -> page001/full/53,
iiif.static: ../welsh-book/page001 / page001/full/27,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/full/27,36 -> page001/full/27,
iiif.static: ../welsh-book/page001 / page001/full/13,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/full/13,18 -> page001/full/13,
iiif.static: ../welsh-book/page001 / page001/full/7,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/full/7,9 -> page001/full/7,
iiif.static: ../welsh-book/page001 / page001/full/3,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/full/3,5 -> page001/full/3,
iiif.static: ../welsh-book/page001 / page001/full/2,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/full/2,2 -> page001/full/2,
iiif.static: ../welsh-book/page001 / page001/full/1,/0/default.jpg
iiif.static: ../welsh-book/page001 / page001/full/1,1 -> page001/full/1,
iiif.static: ../welsh-book/page001 / page001/info.json
iiif.static: Writing HTML to ../welsh-book/page001
iiif.static: ../welsh-book/page001 / page001.html
</code></pre></div></div>
<p>I then had a look at the webpage <code class="language-plaintext highlighter-rouge">page001.html</code> to see if it had worked. Unfortunately I noticed that it couldn’t access the OpenSeadragon script in <code class="language-plaintext highlighter-rouge">/tmp/welsh-book/page001/openseadragon200/openseadragon.min.js</code> so I symlinked the OpenSeadragon javascript file:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hostname:iiif gmr$ ln -s /tmp/iiif/iiif/third_party/openseadragon200 ../welsh-book/page001/openseadragon200
</code></pre></div></div>
<p>and hit refresh and got a working zoomable image:</p>
<p><img src="/assets/images/iiif-tiles-page001.png" alt="Working IIIF Tiles shown in OpenSeaDragon" /></p>
<p>To process all of the images I can run the following:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./iiif_static.py -d ../welsh-book --api-version=2.1 ~/Documents/images/welsh_book/tiff/*.tif
</code></pre></div></div>
<p>and this generates 14 directories in <code class="language-plaintext highlighter-rouge">/tmp/welsh_book</code>. I’ve then copied the 14 directories into <a href="https://github.com/glenrobson/glenrobson.github.io/tree/serverless_iiif/iiif/welsh_book">this github project</a> which is the code behind this blog. Now I’ve moved the images I have to update the <code class="language-plaintext highlighter-rouge">@id</code> in all of the info.json files so that it points to the correct place. Note if you forget to do this then OpenSeaDragon won’t be able to open the image.</p>
<p>I’ve written a program <a href="https://github.com/glenrobson/iiif_stuff/blob/master/standalone-iiif/updateImageId.py">updateImageId.py</a> that can be run as follows:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./standalone-iiif/updateImageId.py json_file 'https://glenrobson.github.io/iiif/welsh_book/
</code></pre></div></div>
<p>and this should prepend the correct prefix to make it work on this site. To run this on allow of the images I run:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>find ../gdmr-digital/ -name "info.json" -exec ./standalone-iiif/updateImageId.py {} 'https://glenrobson.github.io/iiif/welsh_book/' \;
</code></pre></div></div>
<p>Note if you make a mistake then have a look at the updateImageId.py README to see how you can replace a prefix.</p>
<p>It should now be possible to view the static image using Openseadragon:</p>
<div id="openseadragon1" style="width: 100%; height: 500px;"></div>
<script>
//<![CDATA[
function initOpenSeadragon() {
OpenSeadragon({
id: "openseadragon1",
minZoomImageRatio: 1,
prefixUrl: "/assets/images/openseadragon/", // OSD needs trailing slash
tileSources: "https://glenrobson.github.io/iiif/welsh_book/page002/info.json",
crossOriginPolicy: false});
}
window.onload = initOpenSeadragon;
document.addEventListener("page:load", initOpenSeadragon); // Initialize when using turbolinks
//]]>
</script>Glen RobsonI’ve been trying to learn Welsh for a number of years but unfortunately I’m not a natural linguist. So when one of our neighbours gave our Children an old Welsh book to read I set about using it as a challenge and translating it. Being prone to technical procrastination rather than getting on with the translation I’ve had a look at how I can turn this book into a IIIF resource. I hope this will be useful for people looking to make their images available as IIIF but don’t have the time or resources to invest in a comprehensive IIIF stack.MarineLives New Year Wishes2018-01-04T12:27:22+00:002018-01-04T12:27:22+00:00/iiif/wish-list/2018/01/04/marinelives-new-year-wishes<p>This post began as a discussion on <a href="https://twitter.com/MarineLivesorg/status/948365759205519360">twitter</a> on how IIIF could help the MarineLives project achieve their goals on collecting and transcribing historical content related to the manuscripts of the High Court of Admiralty 1627-1677. You can read more about their mission on the MarineLives <a href="http://www.MarineLives.org/wiki/MarineLives#About_MarineLives">wiki</a>.</p>
<p>The MarineLives 2018 New Years Wish list is as follows:</p>
<ol>
<li>
<p>A world in which we could download a single manuscript image from an archival, library or museum website; transcribe it, or add key words; then lob into the Commons. All data recorded with the image. And a Universal Search Tool would search all the content.</p>
</li>
<li>
<p>A manuscript image uploading & exchange site for PhD students to upload & share images taken as part of their research work, which would otherwise be unpublished.</p>
</li>
<li>
<p>A C17th combination of ZoomInfo & LinkedIn to create, improve & make available prosopographies by automatically aggregating historical web & archival sources.</p>
</li>
<li>
<p>A digital camera which saves each new image of a manuscript page with its archival reference number, not a number file name [e.g. TNA HCA 13/53 f.12r] - We could upload 1000 images a day to our laptops * search for them by archival reference & find instantly.</p>
</li>
</ol>
<p>Some of these wishes fall squarely into what IIIF offers and the others may be assisted by some related technologies. I will split the first wish into its parts:</p>
<h2 id="1-a-a-world-in-which-we-could-download-a-single-manuscript-image-from-an-archival-library-or-museum-website">1-A: A world in which we could download a single manuscript image from an archival, library or museum website.</h2>
<p>Starting with the first one IIIF supports the transcription of images without requiring the images to be downloaded. This can make it easier for institutions including Archives, Libraries and Museums to make their images available but will also help in linking transcriptions back to a source image. IIIF provides support for transcriptions by using the <a href="https://www.w3.org/TR/annotation-model/">Web Annotations</a> W3C specification. Web annotations allow annotation on many different types of resources including images, web pages and videos. It is an open format which allows the interoperability of annotations created by different systems.</p>
<p>Below is a video from Stanford demonstrating how to take a reference to two IIIF objects (one from Stanford and one from the Bodleian Library in Oxford) and drag them into a third viewer Mirador.</p>
<iframe width="640" height="360" src="https://www.youtube.com/embed/uih5JuQnYuo" frameborder="0" gesture="media" allow="encrypted-media" allowfullscreen=""></iframe>
<h2 id="1-b-transcribing-images">1-B: Transcribing images</h2>
<p>The <a href="http://projectmirador.org/">Mirador</a> viewer allows the comparison of images from different locations and also supports transcription of these images through its annotation interface and this is demonstrated in the following video:</p>
<iframe width="640" height="360" src="https://www.youtube.com/embed/9b1ReCZh9-E?start=151" frameborder="0" gesture="media" allow="encrypted-media" allowfullscreen=""></iframe>
<p>Mirador supports both transcription and tagging type annotations. Transcribing through Mirador does not require hosting of the images separately as you can rely on the IIIF Image and Presentation API to annotate the images while they are stored and published by the institution. There is a public demo of <a href="http://projectmirador.org/">Mirador</a> available that allows you to load remote Manifests and start transcribing them into a local browser store. For persistent annotations you would have to look at installing an annotation store and a list of options can be found on the <a href="https://github.com/IIIF/awesome-iiif#annotation-servers">IIIF Awesome</a> List.</p>
<p>There are also other options for creating annotations including various Crowdsourcing systems mentioned in the <a href="https://github.com/IIIF/awesome-iiif/issues/176">Awesome List issue</a>. All of these should allow the import of IIIF image and presentation endpoints and allow their transcription. While working at the National Library of Wales (NLW) I was involved in the development of a Crowdsourcing system with <a href="http://digirati.com">Digirati</a>. I gave a presentation in the Rome IIIF conference demonstrating the crowdsourcing of Photographs from <a href="https://d.lib.ncsu.edu/collections">North Carolina State University</a> using the NLW crowdsourcing system. A video showing the setup is available on <a href="https://www.youtube.com/playlist?list=PLMd2mmRYjSJlKs829X0z_kYueQemSfwDd">youtube</a>. This video hopefully demonstrates the idea of taking content from a third party and transcribing using IIIF tools.</p>
<h2 id="1-c-then-lob-annotations-into-the-commons-all-data-recorded-with-the-image">1-C: then lob [annotations] into the Commons. All data recorded with the image.</h2>
<p>Annotations created through Mirador or the other crowdsourcing systems will likely be in either the Web Annotations format or the precursor Open Annotations. There isn’t as far as I know a way to convert these annotations to something that could go on Wiki Commons but as the annotations are stored as JSON-LD it should be possible to convert them to other formats. An alternative to submitting the annotations to Commons is to submit the annotations back to the institution that is publishing the IIIF resource. Specifying this protocol is part of the work of the <a href="http://iiif.io/community/groups/discovery/">IIIF Discovery group</a> but there is already an early proof of concept created between Jeff Witt (Loyola University Maryland) and e-Codices detailed in <a href="http://lombardpress.org/2016/04/16/iiif-webmentions/">Jeff’s blog</a>. This and Jeff’s further work on Linked data Notifications offer an exciting option for the future where institutions can take back the work of volunteers and integrate the valuable data generated into their existing systems.</p>
<h2 id="1-d-and-a-universal-search-tool-would-search-all-the-content">1-D: And a Universal Search Tool would search all the content.</h2>
<p>There are many institutions which implement IIIF and some of these can be found on the <a href="http://iiif.io/community/#participating-institutions">IIIF website</a> but if you are working with content that isn’t IIIF accessible then there are some alternatives detailed in the next section. The <a href="http://iiif.io/community/groups/discovery/">IIIF Discovery</a> group are looking at ways to make it easier to find IIIF institutions and their images but the ‘Universal Search Tool’ mentioned is likely out of scope. The group does aim to put the protocols in place to allow someone to create this type of discovery tool particularly for annotations.</p>
<h2 id="2-image-upload-and-exchange">2. Image upload and exchange</h2>
<p>There is a little known feature with the IIIF presentation API that allows you describe non IIIF images. This could allow you to create a IIIF Manifest that links to images hosted on Wiki Commons or Flickr and then load this manifest into Mirador for transcription. This is a relatively unused feature of IIIF but is recently supported in the Universal Viewer and Mirador but may not be supported in the other crowd sourcing solutions mentioned above. Tom Crane has been pushing for this to be supported in the IIIF viewers and created <a href="https://github.com/tomcrane/wikipedia-to-iiif">an application</a> which uses static images from Wikipedia. This would allow you to transcribe content using IIIF viewers without the source institution supporting IIIF.</p>
<p>It is also possible to support more IIIF image API functions by either using static tiles which can be generated by <a href="https://github.com/zimeon/iiif/tree/master/demo-static">Simeon’s tile generator</a> or looking at hosting a full <a href="https://github.com/IIIF/awesome-iiif#image-servers">IIIF compliant image server</a>.</p>
<p>Although its possible to use non IIIF images in theses ways there are a number of reasons why it is preferable to use an institution’s IIIF image and manifest:</p>
<ul>
<li>Single identifier for an image or object</li>
</ul>
<p>Using IIIF and transcribing IIIF resources encourages the re-use of shared identifiers particularly the Canvas URI which is an identifier for a particular image and the target of most IIIF annotations. By sharing the canvas ID multiple users can transcribe the same resource and their annotations can be shared and combined. By publishing a separate manifest with new Canvas IDs it means the annotations are only associated with that instance so it may not be possible to combine then with other transcriptions or with the source content in the institution.</p>
<ul>
<li>Shared coordinate space</li>
</ul>
<p>As well as a canvas URI, the canvas also specifies the width and height of the image and this is usually the width and height of the source Tiff or JP2. It means annotations on the canvas will always be located in the correct place even when viewing the image at different sizes. If you were to transcribe a downloaded jpg or a new capture the institution and other users of the content may not have the information to transpose references to coordinates of the derivative jpg back to the source tiff or jp2. Coordinates for annotations are particularly important when implementing the <a href="http://iiif.io/api/search/1.0/">IIIF Search API</a> which allows users to search transcribed or generated text.</p>
<p>With the above points noted, it isn’t always possible to have IIIF images provided by an institution and using static images with a IIIF Manifest will allow some of the IIIF features to be used.</p>
<h2 id="3-aggregating-prosopographies">3. Aggregating prosopographies</h2>
<p>This falls out of the scope of IIIF but IIIF will allow a better aggregation of the source of some of these prosopographies. Europeana is a good example of an aggregator which harvests IIIF manifests from institutions and is able to show a rich interface using the IIIF images remotely:</p>
<figure>
<a href="http://www.europeana.eu/portal/en/record/07931/diglit_wordsworth1841.html"><img src="/assets/images/Europeana-screenshot.png" /></a>
<figcaption><a href="http://www.europeana.eu/portal/en/record/07931/diglit_wordsworth1841.html" title="IIIF Image from the Universitätsbibliothek Heidelberg shown on Europeana">IIIF Image from the Universitätsbibliothek Heidelberg shown on Europeana</a>.</figcaption>
</figure>
<p>Wikidata offers an exciting place to aggregate prosopographies but only if they meet the notoriety criteria. Other than that it is going to be difficult to create an aggregator of this type. Possibly the way to make this feasible is to make prosopographies available as Linked Open Data so they can be aggregated at a future date. The issue with aggregation is how to disambiguate different entries and ensure correctly linked entries are created. I have tried some of this type of disambiguation with the <a href="https://www.llgc.org.uk/en/collections/activities/research/nlw-data/aberystwyth-shipping-records-dataset/">NLW Shipping Records</a> and appreciate how difficult it can be.</p>
<h2 id="4-digitising-with-the-original-archival-reference-number">4. Digitising with the original archival reference number</h2>
<p>As mentioned in the Image upload and exchange section it is preferable to use an institution’s IIIF resource rather than host a separate copy of the image. This is particularly relevant with identifiers including archival reference numbers. Typically institutions maintain many identifiers for a digital image including; catalogue numbers, reference numbers, digital image filenames and repository identifiers. It can be difficult to transpose between identifiers but using the Canvas ID as mentioned previously can allow institutions to use this identifier as the master for the published image. The reference number in the example ‘TNA HCA 13/53 f.12r’ looks to be a combination of the identifier for the archival object with a page number appended. It can be difficult for a machine to split this identifier to work out which image is being referenced. With a Canvas URI there is a defined behaviour and API which allows it to be machine processed (if the machine also has a reference to the manifest it came from). Identifiers like the example in the wish list are important for users to be able to navigate the material and in a IIIF manifest the first portion of the identifier ‘TNA HCA 13/53’ would be present in the metadata section of the manifest and the ‘f.12r’ would be the canvas label. Neither the manifest metadata or canvas label would be expected in the IIIF implementation to be machine processable.</p>
<p>If its not possible to have a IIIF image from the institution then the images would likely have short filenames and new canvas Ids would be minted. In the NLW we handled the association between identifiers and digital images by using a workflow management system developed internally called Wombat. This allowed you to associate archival reference numbers with a book or file and also filenames with page labels. We relied on the public catalogue to allow users to search archival reference numbers and get access to digital objects.</p>Glen RobsonThis post began as a discussion on twitter on how IIIF could help the MarineLives project achieve their goals on collecting and transcribing historical content related to the manuscripts of the High Court of Admiralty 1627-1677. You can read more about their mission on the MarineLives wiki.