<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/how-to-do-optical-character-recognition-ocr-of-non-english-documents-in-r-using-tesseract/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://shiring.github.io/text_analysis/2017/07/17/ocr_tesseract"> Shirin's playgRound</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>One of the many great packages of rOpenSci has implemented <a rel="nofollow" href="https://ropensci.org/blog/blog/2016/11/16/tesseract" target="_blank">the open source engine Tesseract</a>.</p>
<p>Optical character recognition (OCR) is used to digitize written or typed documents, i.e. photos or scans of text documents are “translated” into a digital text on your computer.</p>
<p>While this might seem like a trivial task at first glance, because it is so easy for our human brains. When reading text, we make use of our built-in word and sentence “autocomplete” that we learned from experience. But the same task is really quite difficult for a computer to recognize typed words correctly, especially if the document is of low quality.</p>
<p>One of the best open-source engines today is <a rel="nofollow" href="https://github.com/tesseract-ocr" target="_blank">Tesseract</a>. You can run tesseract from the command-line or – with the help of rOpenSci’s <strong>tesseract</strong> package – run it conveniently from within R!</p>
<p>Tesseract uses language specific training data to optimize OCR based on learned context. Therefore, it is much better at recognizing words in coherent sentences than at recognizing single words or abbreviations (we can see this e.g. with address lines in documents).</p>
<p>The default language is English, and you can find numerous examples on how to run OCR with this default. But running tesseract with a different language turned out to need a few additional tweaks, which I want to present here.</p>
<p></p>
<h2>Installing tesseract</h2>
<p>Check out the <a rel="nofollow" href="https://ropensci.org/blog/blog/2016/11/16/tesseract" target="_blank">package vignette</a> for instructions on how to install the libtesseract C++ library and the <strong>tesseract</strong> R package on your computer.</p>
<div>
<pre><code><span>library</span><span>(</span><span>tesseract</span><span>)</span><span>
</span></code></pre>
</div>
<p>Because I’m German and will therefore use a German scanned document as an example, I first needed to install the German training dataset. Even though I installed it together with tesseract (the command-line tool), I still had to install it again for use with R:</p>
<p>If you happen to get an error, that it still didn’t find the correct language data where it expected (as I did), note the path that is given in the error message. This tells you where it looks for the training data and you can simply download the training data manually and copy it to the given path.</p>
<p>Here again, you need to make sure that you download training data for the correct version of tesseract. The <a rel="nofollow" href="https://github.com/tesseract-ocr/tessdata" target="_blank">link that is given in the package documentation</a> turned out to point to a different version of tesseract than I was using. If this is the case, you will get a warning (<em>Params model::Incomplete line</em>) when running <code>ocr</code>().</p>
<p>As you can see, I had Tesseract version 3 installed:</p>
<div>
<pre><code>system(&quot;tesseract --version&quot;)
tesseract 3.05.01
 leptonica-1.74.1
  libjpeg 8d : libpng 1.6.29 : libtiff 4.0.8 : zlib 1.2.8
</code></pre>
</div>
<p>So, I also needed to download the training data for version 3 (the default is for version 4), which you can <a rel="nofollow" href="https://github.com/tesseract-ocr/tessdata/tree/3.04.00" target="_blank">find here</a> and copy it to tesseracts language folder.</p>
<p></p>
<h2>Image processing</h2>
<p>Image quality is essential for good OCR! Tesseract performs different image processing steps internally with the Leptonica library but it is still a good idea to <a rel="nofollow" href="https://github.com/tesseract-ocr/tesseract/wiki/ImproveQuality" target="_blank">improve the image manually before running tesseract</a>.</p>
<p>Here, I am using two random images from the internet:</p>
<ol>
<li>
<p>a <a rel="nofollow" href="http://www.manualsdir.eu/manuals/375646/brother-dcp-115c-dcp-120c-mfc-820cw-mfc-640cw-mfc-215c-dcp-315cn-mfc-425cn-dcp-340cw.html" target="_blank">manual for a printer</a> and</p>
</li>
<li>
<p>a <a rel="nofollow" href="http://spiele.j-crew.de/wiki/Scan:9q_r%C3%A4t.pdf/4" target="_blank">description of a game</a></p>
</li>
</ol>
<p>Image nr. 1 is machine-generated and should therefore yield much better results than image nr. 2, which looks like it was typewriter-written and moreover, is skewed.</p>
<p>This, we can also do from within R, making use of another one of rOpenSci’s packages: <a rel="nofollow" href="https://cran.r-project.org/web/packages/magick/vignettes/intro.html" target="_blank"><strong>magick</strong></a>.</p>
<p>However, it seems that <strong>magick</strong> doesn’t have a function that converts an image to black and white, so I am using <strong>EBImage</strong> first. Because <strong>magick</strong> wants an magick image object for input, I saved the black-and-white image first and then read it in again with <code>image_read()</code>. This isn’t exactly an elegant solution, so if someone knows of a better way to do this, please let me know!</p>
<div>
<pre><code><span>library</span><span>(</span><span>EBImage</span><span>)</span><span> </span><span># install from Bioconductor!
</span></code></pre>
</div>
<div>
<pre><code><span>color.image</span><span> </span><span>&lt;-</span><span> </span><span>readImage</span><span>(</span><span>&quot;/Users/shiringlander/Documents/Github/Blog_posts_prep/ocr/beispiel_scan.png&quot;</span><span>)</span><span>
</span><span>bw.image</span><span> </span><span>&lt;-</span><span> </span><span>channel</span><span>(</span><span>color.image</span><span>,</span><span>&quot;gray&quot;</span><span>)</span><span>
</span><span>writeImage</span><span>(</span><span>bw.image</span><span>,</span><span>file</span><span>=</span><span>&quot;/Users/shiringlander/Documents/Github/Blog_posts_prep/ocr/beispiel_scan_bw.png&quot;</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>color.image</span><span> </span><span>&lt;-</span><span> </span><span>readImage</span><span>(</span><span>&quot;/Users/shiringlander/Documents/Github/Blog_posts_prep/ocr/beispiel_scan_2.jpg&quot;</span><span>)</span><span>
</span><span>bw.image</span><span> </span><span>&lt;-</span><span> </span><span>channel</span><span>(</span><span>color.image</span><span>,</span><span>&quot;gray&quot;</span><span>)</span><span>
</span><span>writeImage</span><span>(</span><span>bw.image</span><span>,</span><span>file</span><span>=</span><span>&quot;/Users/shiringlander/Documents/Github/Blog_posts_prep/ocr/beispiel_scan_2_bw.jpg&quot;</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>library</span><span>(</span><span>magick</span><span>)</span><span>
</span><span>image1</span><span> </span><span>&lt;-</span><span> </span><span>image_read</span><span>(</span><span>&quot;/Users/shiringlander/Documents/Github/Blog_posts_prep/ocr/beispiel_scan_bw.png&quot;</span><span>)</span><span>
</span><span>image2</span><span> </span><span>&lt;-</span><span> </span><span>image_read</span><span>(</span><span>&quot;/Users/shiringlander/Documents/Github/Blog_posts_prep/ocr/beispiel_scan_2_bw.jpg&quot;</span><span>)</span><span>
</span></code></pre>
</div>
<p>Now, we can follow <a rel="nofollow" href="https://github.com/tesseract-ocr/tesseract/wiki/ImproveQuality" target="_blank">Tesseract’s guidelines on how to improve image quality</a>:</p>
<div>
<pre><code><span>library</span><span>(</span><span>tidyverse</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>image_bearb1</span><span> </span><span>&lt;-</span><span> </span><span>image1</span><span> </span><span>%>%</span><span>
</span><span>image_scale</span><span>(</span><span>&quot;x2000&quot;</span><span>)</span><span> </span><span>%>%</span><span> </span><span># rescale
</span><span> </span><span>image_background</span><span>(</span><span>&quot;white&quot;</span><span>,</span><span> </span><span>flatten</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span> </span><span>%>%</span><span> </span><span># set background to white
</span><span> </span><span>image_trim</span><span>()</span><span> </span><span>%>%</span><span> </span><span># Trim edges that are the background color from the image.
</span><span> </span><span>image_noise</span><span>()</span><span> </span><span>%>%</span><span> </span><span># Reduce noise in image using a noise peak elimination filter
</span><span> </span><span>image_enhance</span><span>()</span><span> </span><span>%>%</span><span> </span><span># Enhance image (minimize noise)
</span><span> </span><span>image_normalize</span><span>()</span><span> </span><span>%>%</span><span> </span><span># Normalize image (increase contrast by normalizing the pixel values to span the full range of color values).
</span><span> </span><span>image_contrast</span><span>(</span><span>sharpen</span><span> </span><span>=</span><span> </span><span>1</span><span>)</span><span> </span><span>%>%</span><span> </span><span># increase contrast
</span><span> </span><span>image_deskew</span><span>(</span><span>treshold</span><span> </span><span>=</span><span> </span><span>40</span><span>)</span><span> </span><span># deskew image -> creates negative offset in some scans
</span></code></pre>
</div>
<div>
<pre><code><span>image_bearb2</span><span> </span><span>&lt;-</span><span> </span><span>image2</span><span> </span><span>%>%</span><span>
</span><span>image_scale</span><span>(</span><span>&quot;x2000&quot;</span><span>)</span><span> </span><span>%>%</span><span> </span><span># rescale
</span><span> </span><span>image_background</span><span>(</span><span>&quot;white&quot;</span><span>,</span><span> </span><span>flatten</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span> </span><span>%>%</span><span> </span><span># set background to white
</span><span> </span><span>image_trim</span><span>()</span><span> </span><span>%>%</span><span> </span><span># Trim edges that are the background color from the image.
</span><span> </span><span>image_noise</span><span>()</span><span> </span><span>%>%</span><span> </span><span># Reduce noise in image using a noise peak elimination filter
</span><span> </span><span>image_enhance</span><span>()</span><span> </span><span>%>%</span><span> </span><span># Enhance image (minimize noise)
</span><span> </span><span>image_normalize</span><span>()</span><span> </span><span>%>%</span><span> </span><span># Normalize image (increase contrast by normalizing the pixel values to span the full range of color values).
</span><span> </span><span>image_contrast</span><span>(</span><span>sharpen</span><span> </span><span>=</span><span> </span><span>1</span><span>)</span><span> </span><span>%>%</span><span> </span><span># increase contrast
</span><span> </span><span>image_deskew</span><span>(</span><span>treshold</span><span> </span><span>=</span><span> </span><span>40</span><span>)</span><span> </span><span># deskew image -> creates negative offset in some scans
</span></code></pre>
</div>
<p>If we want to inspect our images from within R, we can use <strong>magick</strong>’s <code>image_browse()</code> function.</p>
<div>
<pre><code><span>image_browse</span><span>(</span><span>image_bearb2</span><span>)</span><span>
</span></code></pre>
</div>
<p></p>
<h2>OCR</h2>
<p>Tesseract’s central function is called <code>ocr()</code>.</p>
<p>For some reason, I couldn’t solve the error message I got when directly pointing the processed images to the <code>ocr()</code> function: <code>Magick: TIFF: negative image positions unsupported</code>. This error results from <code>image_deskew()</code> but all potential solutions don’t seem to be implemented with the R package of ImageMagick, so I had to resort to a work-around: I saved the images first and then pointed <code>ocr()</code> to the images. This worked without a hitch!</p>
<div>
<pre><code><span>image_write</span><span>(</span><span>image_bearb1</span><span>,</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>&quot;/Users/shiringlander/Documents/Github/Blog_posts_prep/ocr/beispiel_scan_bearb.png&quot;</span><span>,</span><span> </span><span>format</span><span> </span><span>=</span><span> </span><span>&quot;png&quot;</span><span>)</span><span>
</span><span>image_write</span><span>(</span><span>image_bearb2</span><span>,</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>&quot;/Users/shiringlander/Documents/Github/Blog_posts_prep/ocr/beispiel_scan_2_bearb.jpg&quot;</span><span>,</span><span> </span><span>format</span><span> </span><span>=</span><span> </span><span>&quot;jpg&quot;</span><span>)</span><span>
</span></code></pre>
</div>
<p>When we are not working with an English document, we can specify the language with the <code>engine = tesseract(language = &quot;deu&quot;)</code> option. We can also set a whole <a rel="nofollow" href="http://www.sk-spell.sk.cx/tesseract-ocr-parameters-in-302-version" target="_blank">range of parameters</a> but for now, I will only show how to use a whitelist: by specifying characters in a whitelist, tesseract will only look for these in the document. You can e.g. use this if you only expect numbers in you document. Here I am not being very restrictive, though…</p>
<div>
<pre><code><span>whitelist</span><span> </span><span>&lt;-</span><span> </span><span>&quot;1234567890-.,;:qwertzuiopüasdfghjklöäyxcvbnmQWERTZUIOPÜASDFGHJKLÖÄYXCVBNM@ß€!$%&amp;/()=?+&quot;</span><span>
</span><span>text1</span><span> </span><span>&lt;-</span><span> </span><span>ocr</span><span>(</span><span>&quot;/Users/shiringlander/Documents/Github/Blog_posts_prep/ocr/beispiel_scan_bearb.png&quot;</span><span>,</span><span>
</span><span>engine</span><span> </span><span>=</span><span> </span><span>tesseract</span><span>(</span><span>language</span><span> </span><span>=</span><span> </span><span>&quot;deu&quot;</span><span>,</span><span>
</span><span>options</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>tessedit_char_whitelist</span><span> </span><span>=</span><span> </span><span>whitelist</span><span>)))</span><span>
</span><span>text2</span><span> </span><span>&lt;-</span><span> </span><span>ocr</span><span>(</span><span>&quot;/Users/shiringlander/Documents/Github/Blog_posts_prep/ocr/beispiel_scan_2_bearb.jpg&quot;</span><span>,</span><span>
</span><span>engine</span><span> </span><span>=</span><span> </span><span>tesseract</span><span>(</span><span>language</span><span> </span><span>=</span><span> </span><span>&quot;deu&quot;</span><span>,</span><span>
</span><span>options</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>tessedit_char_whitelist</span><span> </span><span>=</span><span> </span><span>whitelist</span><span>)))</span><span>
</span></code></pre>
</div>
<p></p>
<h2>Performance evaluation</h2>
<p>Evaluating how good our model performed isn’t trivial either. While we as humans can very easily judge the accuracy of our digitzed text just by looking at it, we need a standardized and automated way to evaluate model performance.</p>
<p>One way would be to manually transcribe your document and check it against the text that tesseract extracted. However, this is very labor-intensive and time-consuming, especially when you’re working with a large number of documents!</p>
<p>Another, slightly less arduous way would be to create a list of relevant words that we want to have recognized. This could be adapted to include any list of given words that are important for you to be recognized (if you wanted to be able to search for them among your documents, for example).</p>
<p>Or, as I am going to do here, we can go a much easier way and compare the words that tesseract recognized to a list of words from a dictionary to get an idea about how many of them are actual words. This is of course not without problems: Some words may not be in our dictionary or they are borrowed from another language, they might be names of people or places, addresses, abbreviations, etc. Also, because we don’t have a benchmark for our document, we will only get an estimation of how many words were correctly recognized. But we can really only compare different tesseract models against each other with this method.</p>
<p>Because we use different grammatical forms of words, we also want to stem both our recognized words and the dictionary before comparing them!</p>
<p>Here, I am using the <a rel="nofollow" href="https://www.openthesaurus.de/about/download" target="_blank">German Open Thesaurus</a>.</p>
<p>To separate the text and the dictionary into distinct words, I am using the <strong>tidytext</strong> package together with <strong>SnowballC</strong> for word stemming. Finally, I am going to remove duplicate entries.</p>
<div>
<pre><code><span>library</span><span>(</span><span>tidytext</span><span>)</span><span>
</span><span>library</span><span>(</span><span>SnowballC</span><span>)</span><span>
</span><span>openthes</span><span> </span><span>&lt;-</span><span> </span><span>data.frame</span><span>(</span><span>words</span><span> </span><span>=</span><span> </span><span>read_lines</span><span>(</span><span>&quot;/Users/shiringlander/Documents/Projekte/OCR_Provinzial/German_dict/OpenThesaurus-Textversion/openthesaurus.txt&quot;</span><span>,</span><span> </span><span>skip</span><span> </span><span>=</span><span> </span><span>18</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>words</span><span> </span><span>=</span><span> </span><span>as.character</span><span>(</span><span>words</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>unnest_tokens</span><span>(</span><span>word</span><span>,</span><span> </span><span>words</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>word</span><span> </span><span>=</span><span> </span><span>wordStem</span><span>(</span><span>word</span><span>,</span><span> </span><span>language</span><span> </span><span>=</span><span> </span><span>&quot;deu&quot;</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>distinct</span><span>()</span><span>
</span></code></pre>
</div>
<p>This leaves us with 77453 German reference words.</p>
<p>Now, we can do the same with our tesseract output.</p>
<div>
<pre><code><span>text_1_df</span><span> </span><span>&lt;-</span><span> </span><span>data.frame</span><span>(</span><span>text</span><span> </span><span>=</span><span> </span><span>read.delim</span><span>(</span><span>textConnection</span><span>(</span><span>text1</span><span>),</span><span> </span><span># make text into dataframe
</span><span> </span><span>header</span><span> </span><span>=</span><span> </span><span>FALSE</span><span>,</span><span> </span><span>sep</span><span> </span><span>=</span><span> </span><span>&quot;\n&quot;</span><span>,</span><span> </span><span>strip.white</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>text</span><span> </span><span>=</span><span> </span><span>as.character</span><span>(</span><span>V</span><span>1</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>unnest_tokens</span><span>(</span><span>word</span><span>,</span><span> </span><span>text</span><span>)</span><span> </span><span>%>%</span><span> </span><span># separate words
</span><span> </span><span>mutate</span><span>(</span><span>word</span><span> </span><span>=</span><span> </span><span>wordStem</span><span>(</span><span>word</span><span>,</span><span> </span><span>language</span><span> </span><span>=</span><span> </span><span>&quot;deu&quot;</span><span>))</span><span> </span><span># use word stem
</span><span>
</span><span>text_2_df</span><span> </span><span>&lt;-</span><span> </span><span>data.frame</span><span>(</span><span>text</span><span> </span><span>=</span><span> </span><span>read.delim</span><span>(</span><span>textConnection</span><span>(</span><span>text2</span><span>),</span><span> </span><span># make text into dataframe
</span><span> </span><span>header</span><span> </span><span>=</span><span> </span><span>FALSE</span><span>,</span><span> </span><span>sep</span><span> </span><span>=</span><span> </span><span>&quot;\n&quot;</span><span>,</span><span> </span><span>strip.white</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>text</span><span> </span><span>=</span><span> </span><span>as.character</span><span>(</span><span>V</span><span>1</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>unnest_tokens</span><span>(</span><span>word</span><span>,</span><span> </span><span>text</span><span>)</span><span> </span><span>%>%</span><span> </span><span># separate words
</span><span> </span><span>mutate</span><span>(</span><span>word</span><span> </span><span>=</span><span> </span><span>wordStem</span><span>(</span><span>word</span><span>,</span><span> </span><span>language</span><span> </span><span>=</span><span> </span><span>&quot;deu&quot;</span><span>))</span><span> </span><span># use word stem
</span></code></pre>
</div>
<p>To get an estimate about model performance, I am then counting how many of the words that were recognized in each document are also part of the German dictionary (and therefore likely to be real words) and plot the results.</p>
<div>
<pre><code><span>res1</span><span> </span><span>&lt;-</span><span> </span><span>text_1_df</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>in_dict</span><span> </span><span>=</span><span> </span><span>ifelse</span><span>(</span><span>word</span><span> </span><span>%in%</span><span> </span><span>openthes</span><span>$</span><span>word</span><span>,</span><span> </span><span>TRUE</span><span>,</span><span> </span><span>FALSE</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>count</span><span>(</span><span>in_dict</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>percent</span><span> </span><span>=</span><span> </span><span>n</span><span> </span><span>/</span><span> </span><span>nrow</span><span>(</span><span>text_1_df</span><span>)</span><span> </span><span>*</span><span> </span><span>100</span><span>,</span><span>
</span><span>image</span><span> </span><span>=</span><span> </span><span>&quot;image 1&quot;</span><span>)</span><span>
</span><span>res2</span><span> </span><span>&lt;-</span><span> </span><span>text_2_df</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>in_dict</span><span> </span><span>=</span><span> </span><span>ifelse</span><span>(</span><span>word</span><span> </span><span>%in%</span><span> </span><span>openthes</span><span>$</span><span>word</span><span>,</span><span> </span><span>TRUE</span><span>,</span><span> </span><span>FALSE</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>count</span><span>(</span><span>in_dict</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>percent</span><span> </span><span>=</span><span> </span><span>n</span><span> </span><span>/</span><span> </span><span>nrow</span><span>(</span><span>text_2_df</span><span>)</span><span> </span><span>*</span><span> </span><span>100</span><span>,</span><span>
</span><span>image</span><span> </span><span>=</span><span> </span><span>&quot;image 2&quot;</span><span>)</span><span>
</span></code></pre>
</div>
<p><img alt="" src="https://i0.wp.com/shiring.github.io/text_analysis/2017/07/17/ocr_tesseract_files/figure-markdown_github/unnamed-chunk-16-1.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p>Between 80 and 90% of recognized words seem to be actual words!</p>
<p>Of course, the less “standard” a document is, the more difficult it will be to extract text correctly but I’d say this isn’t bad for a first attempt!</p>
<hr>
<p></p>
<div>
<pre><code><span>sessionInfo</span><span>()</span><span>
</span></code></pre>
</div>
<div>
<pre><code>## R version 3.4.0 (2017-04-21)
## Platform: x86_64-apple-darwin15.6.0 (64-bit)
## Running under: macOS Sierra 10.12.5
## 
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRlapack.dylib
## 
## locale:
## [1] de_DE.UTF-8/de_DE.UTF-8/de_DE.UTF-8/C/de_DE.UTF-8/de_DE.UTF-8
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] bindrcpp_0.2    SnowballC_0.5.1 tidytext_0.1.3  dplyr_0.7.1    
##  [5] purrr_0.2.2.2   readr_1.1.1     tidyr_0.6.3     tibble_1.3.3   
##  [9] ggplot2_2.2.1   tidyverse_1.1.1 magick_0.4      EBImage_4.18.0 
## [13] tesseract_1.4  
## 
## loaded via a namespace (and not attached):
##  [1] locfit_1.5-9.1      reshape2_1.4.2      haven_1.1.0        
##  [4] lattice_0.20-35     colorspace_1.3-2    htmltools_0.3.6    
##  [7] yaml_2.1.14         rlang_0.1.1         foreign_0.8-69     
## [10] glue_1.1.1          RColorBrewer_1.1-2  BiocGenerics_0.22.0
## [13] modelr_0.1.0        readxl_1.0.0        jpeg_0.1-8         
## [16] bindr_0.1           plyr_1.8.4          stringr_1.2.0      
## [19] cellranger_1.1.0    munsell_0.4.3       gtable_0.2.0       
## [22] rvest_0.3.2         psych_1.7.5         evaluate_0.10.1    
## [25] labeling_0.3        knitr_1.16          forcats_0.2.0      
## [28] parallel_3.4.0      tokenizers_0.1.4    broom_0.4.2        
## [31] Rcpp_0.12.11        backports_1.1.0     scales_0.4.1       
## [34] jsonlite_1.5        abind_1.4-5         mnormt_1.5-5       
## [37] hms_0.3             png_0.1-7           digest_0.6.12      
## [40] stringi_1.1.5       tiff_0.1-5          grid_3.4.0         
## [43] rprojroot_1.2       tools_3.4.0         magrittr_1.5       
## [46] lazyeval_0.2.0      janeaustenr_0.1.5   pkgconfig_2.0.1    
## [49] Matrix_1.2-10       xml2_1.1.1          lubridate_1.6.0    
## [52] assertthat_0.2.0    rmarkdown_1.6       httr_1.2.1         
## [55] R6_2.2.2            fftwtools_0.9-8     nlme_3.1-131       
## [58] compiler_3.4.0
</code></pre>
</div>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://shiring.github.io/text_analysis/2017/07/17/ocr_tesseract"> Shirin's playgRound</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/kKhiouKWpnw" height="1"></a></div>