{"id":5064,"date":"2022-06-22T11:07:24","date_gmt":"2022-06-22T09:07:24","guid":{"rendered":"https:\/\/gini.net\/?p=5064"},"modified":"2024-02-29T14:37:29","modified_gmt":"2024-02-29T13:37:29","slug":"how-we-do-ocr-with-deep-learning","status":"publish","type":"post","link":"https:\/\/gini.net\/en\/blog\/how-we-do-ocr-with-deep-learning\/","title":{"rendered":"How we do OCR with deep learning"},"content":{"rendered":"<p>The information extraction strongly relies on both text and the coordinates of text in the 2-dimensional document layout.<\/p>\n<p>In native PDF files, text and layout information can be easily parsed from the file. However, the majority of the incoming documents that our Gini system processes are images. More precisely, these are the photos taken with all kinds of smartphones or scanned PDFs created by various scanners. In order to retrieve text and layout data from such files for downstream information extraction tasks, custom Optical Character Recognition (OCR) was implemented.<\/p>\n<div id=\"attachment_5068\" style=\"width: 1210px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" aria-describedby=\"caption-attachment-5068\" class=\"lazyload wp-image-5068 size-fusion-1200\" src=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-1-1200x466.png\" data-orig-src=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-1-1200x466.png\" alt=\"\" width=\"1200\" height=\"466\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%271200%27%20height%3D%27466%27%20viewBox%3D%270%200%201200%20466%27%3E%3Crect%20width%3D%271200%27%20height%3D%27466%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-srcset=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-1-200x78.png 200w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-1-300x117.png 300w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-1-400x155.png 400w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-1-600x233.png 600w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-1-768x298.png 768w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-1-800x311.png 800w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-1-1024x398.png 1024w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-1-1200x466.png 1200w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-1-1536x597.png 1536w\" data-sizes=\"auto\" data-orig-sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><p id=\"caption-attachment-5068\" class=\"wp-caption-text\">Figure 1. An example image processing and OCR pipeline in Gini. Left: an example input image. Middle: an ideal preprocessed image. Right: OCR results in JSON format.<\/p><\/div>\n<p>&nbsp;<\/p>\n<h2>Image Processing<\/h2>\n<p>The performance of OCR strongly relies on image quality. Therefore, in order to enhance the quality of images, we first implemented a series of convolutional neural network-based models that perform the following data transformations:<\/p>\n<ul>\n<li>Orientation detection and rotation.<\/li>\n<li>Homography detection, cropping, and perspective warping.<\/li>\n<li>Region of interest detection, e.g. tables, QR codes, or remittance slips (\u201c\u00dcberweisungstr\u00e4ger\u201d in German, a widely used bank transfer form in Germany and Austria).<\/li>\n<li>Binarization and de-noising of certain regions of interest (ROIs).<\/li>\n<\/ul>\n<p>The images obtained after a series of such transformations have corrected orientation, restored perspective, and improved overall quality (Figure 1).<\/p>\n<h2>Text Detection<\/h2>\n<p>The improved images are now ready for our OCR, and the first step is text detection. It is important to note that modern OCR no longer works on character level but rather utilizes the recent advances in NLP and computer vision deep learning techniques to predict at sequence level (Figure 2). Instead of characters, we extract the snippets of words or even phrases from document images.<\/p>\n<div id=\"attachment_5070\" style=\"width: 571px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" aria-describedby=\"caption-attachment-5070\" class=\"lazyload size-full wp-image-5070\" src=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-2.png\" data-orig-src=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-2.png\" alt=\"\" width=\"561\" height=\"527\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27561%27%20height%3D%27527%27%20viewBox%3D%270%200%20561%20527%27%3E%3Crect%20width%3D%27561%27%20height%3D%27527%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-srcset=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-2-200x188.png 200w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-2-300x282.png 300w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-2-400x376.png 400w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-2.png 561w\" data-sizes=\"auto\" data-orig-sizes=\"(max-width: 561px) 100vw, 561px\" \/><p id=\"caption-attachment-5070\" class=\"wp-caption-text\">Figure 2. An example of a common text detection model (EAST, Zhou et al., https:\/\/arxiv.org\/abs\/1704.03155).<\/p><\/div>\n<p>After the text detection, the full invoice image is split into a batch of snippets, each consisting of 1 or more words closely connected horizontally (Figure 3). It enables the text recognition step to handle them as a sequential word prediction task (a well-studied problem in the NLP domain).<\/p>\n<div id=\"attachment_5072\" style=\"width: 1210px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" aria-describedby=\"caption-attachment-5072\" class=\"lazyload size-fusion-1200 wp-image-5072\" src=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-3-1200x732.png\" data-orig-src=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-3-1200x732.png\" alt=\"\" width=\"1200\" height=\"732\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%271200%27%20height%3D%27732%27%20viewBox%3D%270%200%201200%20732%27%3E%3Crect%20width%3D%271200%27%20height%3D%27732%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-srcset=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-3-200x122.png 200w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-3-300x183.png 300w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-3-400x244.png 400w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-3-600x366.png 600w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-3-768x468.png 768w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-3-800x488.png 800w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-3-1024x624.png 1024w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-3-1200x732.png 1200w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-3-1536x936.png 1536w\" data-sizes=\"auto\" data-orig-sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><p id=\"caption-attachment-5072\" class=\"wp-caption-text\">Figure 3. Left: preprocessed image. Right: detected image snippets.<\/p><\/div>\n<h2>Text Recognition<\/h2>\n<p>Once we have batches of image snippets of single-line words or phrases from the text detection step, it is time to transform them into actual text (Figure 5).<\/p>\n<div id=\"attachment_5074\" style=\"width: 1165px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" aria-describedby=\"caption-attachment-5074\" class=\"lazyload size-full wp-image-5074\" src=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-4.png\" data-orig-src=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-4.png\" alt=\"\" width=\"1155\" height=\"151\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%271155%27%20height%3D%27151%27%20viewBox%3D%270%200%201155%20151%27%3E%3Crect%20width%3D%271155%27%20height%3D%27151%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-srcset=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-4-200x26.png 200w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-4-300x39.png 300w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-4-400x52.png 400w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-4-600x78.png 600w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-4-768x100.png 768w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-4-800x105.png 800w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-4-1024x134.png 1024w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-4.png 1155w\" data-sizes=\"auto\" data-orig-sizes=\"(max-width: 1155px) 100vw, 1155px\" \/><p id=\"caption-attachment-5074\" class=\"wp-caption-text\">Figure 4. The flow of 4-stage scene text recognition (Baek et al., https:\/\/arxiv.org\/abs\/1904.01906).<\/p><\/div>\n<p>A typical state-of-the-art text recognition model (Figure 4) consists of the following components:<\/p>\n<ul>\n<li>Transformation: changing an irregular-shaped text image into a normalized, straight single-line snippet using a certain spatial transformation network.<\/li>\n<li>Feature extraction: converting the input images into convoluted feature maps using a common convolutional neural network (e.g. VGG, ResNet, RCNN). The feature maps contain important visual features emphasized and irrelevant visual features suppressed.<\/li>\n<li>Sequence Modeling: capturing contextual information via a recurrent neural network (e.g. BiLSTM).<br \/>\nPrediction: predicting text using sequences of feature vectors from the previous step.<\/li>\n<\/ul>\n<p>After our image preprocessing, the invoice text should be fairly well-structured, not curved or distorted. This allows us to skip the above transformation step and reduce some computational costs. In other words, we are using only 3 out of 4 text recognition steps.<\/p>\n<div id=\"attachment_5076\" style=\"width: 1210px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" aria-describedby=\"caption-attachment-5076\" class=\"lazyload size-fusion-1200 wp-image-5076\" src=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-5-1200x538.png\" data-orig-src=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-5-1200x538.png\" alt=\"\" width=\"1200\" height=\"538\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%271200%27%20height%3D%27538%27%20viewBox%3D%270%200%201200%20538%27%3E%3Crect%20width%3D%271200%27%20height%3D%27538%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-srcset=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-5-200x90.png 200w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-5-300x135.png 300w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-5-400x179.png 400w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-5-600x269.png 600w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-5-768x344.png 768w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-5-800x359.png 800w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-5-1024x459.png 1024w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-5-1200x538.png 1200w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-5-1536x689.png 1536w\" data-sizes=\"auto\" data-orig-sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><p id=\"caption-attachment-5076\" class=\"wp-caption-text\">Figure 5. Left: image snippets after the text detection. Right: text recognition results.<\/p><\/div>\n<h2>Post Processing<\/h2>\n<p>With the text predicted via the model described above, bounding boxes calculated via the coordinates of the image snippets, we are only one step away from the information extraction step.<\/p>\n<p>To help our text extractors achieve higher accuracy, we need to perform some post-processing corrections.<\/p>\n<ul>\n<li>Post-OCR text correction: since the text recognition process already involves a sequence prediction model, there is no need for a lot of correction \u2013 the model learns enough information about the language. We only perform some extra corrections with the help of dictionaries. Additionally, we are planning to look into using the pre-trained language models to improve the prediction quality further.<\/li>\n<li>Reading order correction: despite the fact that we use coordinates in our downstream extraction tasks, the reading order still influences the extraction accuracy. To mitigate this, we implement some reading order correction methods which help us to reconstruct the intended order as close to the original as possible. In the future, we may also implement a pre-trained order detection model (e.g. https:\/\/arxiv.org\/abs\/2108.11591).<\/li>\n<li>JSON\/XML output creation: finally, we put the results into a structured, deserializable output format for both internal downstream information extraction services and API used by our clients\/users. We support both JSON and XML formats.<\/li>\n<\/ul>\n<div id=\"attachment_5078\" style=\"width: 1210px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" aria-describedby=\"caption-attachment-5078\" class=\"lazyload size-fusion-1200 wp-image-5078\" src=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-6-1200x600.png\" data-orig-src=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-6-1200x600.png\" alt=\"\" width=\"1200\" height=\"600\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%271200%27%20height%3D%27600%27%20viewBox%3D%270%200%201200%20600%27%3E%3Crect%20width%3D%271200%27%20height%3D%27600%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-srcset=\"https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-6-200x100.png 200w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-6-300x150.png 300w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-6-400x200.png 400w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-6-600x300.png 600w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-6-768x384.png 768w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-6-800x400.png 800w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-6-1024x512.png 1024w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-6-1200x600.png 1200w, https:\/\/gini.net\/wp-content\/uploads\/Gini-OCR-Figure-6-1536x768.png 1536w\" data-sizes=\"auto\" data-orig-sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><p id=\"caption-attachment-5078\" class=\"wp-caption-text\">Figure 6. Left: text recognition results. Middle: text after reading order correction. Right: final OCR output in JSON format.<\/p><\/div>\n<p>In the end, the structured layout in XML format is passed to downstream information extraction tasks.<\/p>\n<h2>Summary<\/h2>\n<p>Using a complete, in-house developed pipeline of deep learning-based image processing, OCR, and information extraction, we provide a fast and accurate solution that is specialized for mobile input. It helps banks and insurance to gather the best possible quality from mobile phone input in a decent amount of time to drive great user experiences and stickiness of the features like <a href=\"https:\/\/gini.net\/en\/products\/payment\/photopayment\/\">Photo Payment<\/a> or <a href=\"https:\/\/gini.net\/en\/products\/payment\/pay-connect\/\">Pay Connect<\/a>.<\/p>\n<p style=\"text-align: center;\">.\u00a0 \u00a0 \u00a0 \u00a0 .\u00a0 \u00a0 \u00a0 \u00a0 .<\/p>\n<p>&nbsp;<\/p>\n<p><em>If you enjoy mastering challenges of machine learning like this one, you should probably check out our <a href=\"https:\/\/gini.net\/en\/about-gini\/#jobs\">open positions<\/a>. We are always looking for excellent developers to join us!<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>From image detection to text detection to the recognition of text and post-processing, we created our specialized high-performance OCR to make the best out of mobile images.<\/p>\n","protected":false},"author":16,"featured_media":12954,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[60],"tags":[],"class_list":["post-5064","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tech"],"_links":{"self":[{"href":"https:\/\/gini.net\/en\/wp-json\/wp\/v2\/posts\/5064","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gini.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gini.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gini.net\/en\/wp-json\/wp\/v2\/users\/16"}],"replies":[{"embeddable":true,"href":"https:\/\/gini.net\/en\/wp-json\/wp\/v2\/comments?post=5064"}],"version-history":[{"count":7,"href":"https:\/\/gini.net\/en\/wp-json\/wp\/v2\/posts\/5064\/revisions"}],"predecessor-version":[{"id":13502,"href":"https:\/\/gini.net\/en\/wp-json\/wp\/v2\/posts\/5064\/revisions\/13502"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/gini.net\/en\/wp-json\/wp\/v2\/media\/12954"}],"wp:attachment":[{"href":"https:\/\/gini.net\/en\/wp-json\/wp\/v2\/media?parent=5064"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gini.net\/en\/wp-json\/wp\/v2\/categories?post=5064"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gini.net\/en\/wp-json\/wp\/v2\/tags?post=5064"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}