{"id":3134,"date":"2020-05-11T13:11:09","date_gmt":"2020-05-11T20:11:09","guid":{"rendered":"https:\/\/tolstoy.ai\/?p=3134"},"modified":"2020-05-11T13:11:09","modified_gmt":"2020-05-11T20:11:09","slug":"machine-vision-and-nlp-parsing-century-old-newspapers-with-the-wall-st-journal","status":"publish","type":"post","link":"https:\/\/staging.tolstoy-ai.com\/?p=3134","title":{"rendered":"Transcribing Century-Old Newspapers at The Wall Street Journal"},"content":{"rendered":"<p data-selectable-paragraph=\"\">By Rahul Hayaran, Yi-Lin Chen, and Rosa Lin<\/p>\n<p id=\"ae92\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\" data-selectable-paragraph=\"\"><em class=\"hy\">The Wall Street Journal wanted to do something special for their 130th Anniversary: create a special edition, digitized broadsheet of stories from their entire history. While their archives had been well preserved and imaged, extracting the text from old \u2014 in some cases century-old \u2014 pages proved tricky. The newspaper approached\u00a0<\/em><em class=\"hy\">Tolstoy<\/em><em class=\"hy\">\u00a0to help them extract the text accurately \u2014 and on deadline for their 130th anniversary.<\/em><\/p>\n<p id=\"5795\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\" data-selectable-paragraph=\"\">This article covers how we used the latest techniques in image processing and optical character recognition to digitize and extract the text from the newspaper broadsheets.<\/p>\n<h3 id=\"3733\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\">Primer on OCR<\/h3>\n<p id=\"1e81\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\" data-selectable-paragraph=\"\">Optical character recognition, more commonly known as OCR, is among the foundational computer vision tasks. Basically, it is the technology that converts images of typed or handwritten text into machine-encoded text (i.e. strings).<\/p>\n<p data-selectable-paragraph=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-3044 size-full\" src=\"http:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.27.09-PM.png\" alt=\"\" width=\"712\" height=\"301\" srcset=\"https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.27.09-PM.png 712w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.27.09-PM-300x127.png 300w\" sizes=\"auto, (max-width: 712px) 100vw, 712px\" \/><\/p>\n<p data-selectable-paragraph=\"\">It was one of the first big machine learning problems to be tackled by researchers \u2014 chiefly because it didn\u2019t require deep learning to achieve good performance. These days OCR is largely seen as a solved problem, especially in \u201cdomestic\u201d settings like PDFs and scanned documents. But, there is a very long tail of cases where even paid\/state-of-the-art options, such as Google Cloud Vision and Amazon Textract (not to mention the very good open-source Tesseract), fail.<\/p>\n<p data-selectable-paragraph=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-3081 size-large\" src=\"https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.32.34-PM-1024x369.png\" alt=\"\" width=\"800\" height=\"288\" srcset=\"https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.32.34-PM-1024x369.png 1024w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.32.34-PM-300x108.png 300w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.32.34-PM-768x277.png 768w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.32.34-PM.png 1239w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/p>\n<p id=\"6e2c\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\" data-selectable-paragraph=\"\">You see, most OCR, by default, reads text from left-to-right and top-to-bottom \u2014 in that order. While this is well suited to most essays, novels, contracts, and official documents (what largely comprised the training sets of early OCR), it isn\u2019t so conducive to a lot of other real world documents (newspapers, journal articles, reports, advertisements, posters, etc.), which may have text all over the place. As we can see in the above example, even columns, which intuitively seem like they are regular enough to be picked up, can confound the best OCR models.<\/p>\n<h3 id=\"eb8f\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\">Can we do better \u2014 and if so, how?<\/h3>\n<p id=\"7555\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\" data-selectable-paragraph=\"\">The issue all these models have is not in the accuracy of the text \u2014 rather, it is in determining an accurate reading order. Thus, what we have to do is to define a set of pre-processing operations that create and arrange image blocks in a way that returns the correct order when fed through any OCR model.<\/p>\n<h3 id=\"a03c\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\">Grouping text blocks<\/h3>\n<p id=\"2f21\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\" data-selectable-paragraph=\"\">The first step is to recognize groups of text. Remember, since we only need \u201cblobs\u201d (encoded as bounding boxes) likely to contain text, we need not worry so much about readability, merely distinguishability. We can always pipe the generated coordinates back over the original image for the engine.<\/p>\n<p id=\"e859\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\" data-selectable-paragraph=\"\">To this end, we take advantage of known image manipulation and text segmentation techniques as well as a pinch of graph theory.<\/p>\n<p id=\"7bfc\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\" data-selectable-paragraph=\"\">Our process starts by grayscaling and binarizing the image. We do this to transform the image such that all content is black and everything else is white. This is achieved with Otsu\u2019s thresholding, which finds the optimal pixel color decision boundary.<\/p>\n<p data-selectable-paragraph=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-3083\" src=\"http:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.33.56-PM.png\" alt=\"\" width=\"750\" height=\"443\" srcset=\"https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.33.56-PM.png 1006w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.33.56-PM-300x177.png 300w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.33.56-PM-768x453.png 768w\" sizes=\"auto, (max-width: 750px) 100vw, 750px\" \/><\/p>\n<p data-selectable-paragraph=\"\">Next, we run the Run-Length Smoothing Algorithm (RLSA) to convert words into \u201cmini-blobs\u201d. We then invert the image and dilate it (add pixels to each mini-blob\u2019s boundaries) until all the mini-blobs sufficiently overlap. From there, we recursively merge together overlapping blobs until no blobs overlap. This ensures each blob represents a distinct content area.<\/p>\n<p data-selectable-paragraph=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-3084 size-large\" src=\"https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.34.52-PM-1024x411.png\" alt=\"\" width=\"800\" height=\"321\" srcset=\"https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.34.52-PM-1024x411.png 1024w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.34.52-PM-300x121.png 300w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.34.52-PM-768x309.png 768w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.34.52-PM.png 1461w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/p>\n<p data-selectable-paragraph=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-3085 aligncenter\" src=\"https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.35.38-PM-1024x435.png\" alt=\"\" width=\"800\" height=\"340\" srcset=\"https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.35.38-PM-1024x435.png 1024w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.35.38-PM-300x127.png 300w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.35.38-PM-768x326.png 768w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.35.38-PM.png 1431w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/p>\n<h3 id=\"c4d6\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\">Handling non-text elements<\/h3>\n<p id=\"8abb\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\" data-selectable-paragraph=\"\">We aren\u2019t done yet, however, because if our document initially had pictures, tables, or graphics, these would be encoded as blobs as well. Thus, we use a classifier, which, when fed in with coordinates of the blob (as applied to the original image), can determine whether it contains text or not. We achieved good results with (at the time) state-of-the-art VGG Net, though any modern architecture will do.<\/p>\n<p data-selectable-paragraph=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-3086 aligncenter\" src=\"https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.36.18-PM-1024x320.png\" alt=\"\" width=\"800\" height=\"250\" srcset=\"https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.36.18-PM-1024x320.png 1024w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.36.18-PM-300x94.png 300w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.36.18-PM-768x240.png 768w, https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/Screen-Shot-2020-05-11-at-2.36.18-PM.png 1273w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/p>\n<p id=\"c352\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\" data-selectable-paragraph=\"\">Finally, we have a list of text blobs. Now we must determine their order. To accomplish this, we turn to topological sort, a way of arranging a set of spatially related elements in a reading order. Concretely, we did this by placing blob A before blob B if either 1) they overlap horizontally and A is above B or 2) A is entirely to the left of B and there doesn\u2019t exist a blob C that overlaps both A and B horizontally and vertically.<\/p>\n<h3 id=\"3c95\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\">Finished product<\/h3>\n<p id=\"ae47\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\" data-selectable-paragraph=\"\">At last, we\u2019re done. We have a list of blobs of text in the order they\u2019d be read. These can be fed into any OCR model of choice to yield a better extraction.<\/p>\n<p id=\"8c9d\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\" data-selectable-paragraph=\"\">On Google Cloud Vision, this process improved Levenshtein similarity (a measure of how closely two strings match) by 20% on average. It was also fairly fast, only adding a few seconds to the total time spent.<\/p>\n<p id=\"2f04\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\" data-selectable-paragraph=\"\">All in all, Tolstoy was able to accurately extract the text from The Wall St. Journal\u2019s historical articles well in time for their 130th Anniversary Special Edition \u2014 saving them weeks of tedious manual transcription work, as well as making the text fully digitized and searchable.<\/p>\n<p id=\"b428\" class=\"he hs ap by hg b hh hi ht hj hk hu hl hm hv hn ho hw hp hq hx hr ej\" data-selectable-paragraph=\"\"><em>Here\u2019s the link to the final published product:\u00a0<a class=\"cn dj hz ia ib ic\" href=\"https:\/\/www.wsj.com\/articles\/130-years-of-history-as-seen-in-the-pages-of-the-wall-street-journal-11562544331\" target=\"_blank\" rel=\"noopener nofollow noreferrer\">https:\/\/www.wsj.com\/articles\/130-years-of-history-as-seen-in-the-pages-of-the-wall-street-journal-11562544331.<\/a><\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>By Rahul Hayaran, Yi-Lin Chen, and Rosa Lin The Wall Street Journal wanted to do something special for their 130th Anniversary: create a special edition, digitized broadsheet of stories from.<\/p>\n","protected":false},"author":1,"featured_media":3095,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[14,16],"tags":[],"class_list":["post-3134","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-machine-vision","category-ocr"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/staging.tolstoy-ai.com\/wp-content\/uploads\/2020\/06\/pages-1237059-1920x1440-1.jpg","_links":{"self":[{"href":"https:\/\/staging.tolstoy-ai.com\/index.php?rest_route=\/wp\/v2\/posts\/3134","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/staging.tolstoy-ai.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/staging.tolstoy-ai.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/staging.tolstoy-ai.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/staging.tolstoy-ai.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3134"}],"version-history":[{"count":0,"href":"https:\/\/staging.tolstoy-ai.com\/index.php?rest_route=\/wp\/v2\/posts\/3134\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/staging.tolstoy-ai.com\/index.php?rest_route=\/wp\/v2\/media\/3095"}],"wp:attachment":[{"href":"https:\/\/staging.tolstoy-ai.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3134"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/staging.tolstoy-ai.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3134"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/staging.tolstoy-ai.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3134"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}