C# OCR Images

17th January 2018 by Gemma Beckford

# How to Read Text from an Image in C#

## C# Image to Text using Iron OCR

In this tutorial, we will learn how to convert images to text in C# and other .NET languages. We will use the Iron OCR library to recognize text within images and look at the nuances of how to use Iron OCR to get the highest performance in terms of accuracy and speed when reading text from images in .NET Hello World.

To achive Image to Text we will install the IcronOCR OCR library into a Visual Studio project. To do this, we Download the IronOcr DLL or use Nuget.

 PM > Install-Package IronOcr

## AutoOCR

In this simple example, you can see we use the IronOcr.AutoOcr class to read the text from an image and automatically return its value as a string.

using IronOcr;

AutoOcr OCR = new AutoOcr() { ReadBarCodes = false };
Console.WriteLine(Results.Text);
Imports IronOcr

Dim OCR As New AutoOcr() With {.ReadBarCodes = False}
Console.WriteLine(Results.Text)
VB   C#

Although this may seem simplistic, there is sophisticated behavior going on 'under the surface': scanning the image for alignment, quality and resolution, looking at its properties, optimizing the OCR engine, and using a trained artificial intelligence network to then read the text as a human would.

OCR is not a simple process for a computer to achieve, and reading speeds may be similar to those of a human. In other words, OCR is not an instantaneous process. In this case though, it is 100% accurate.

In most real world use cases, developers are going to want the best performance possible for their project. In this case, we recommend that you move forward from the Auto OCR example and look at the AdvancedOCR class within the Iron OCR namespace.

This gives you the facility to set the specific characteristics of an OCR job, such as:

• cleaning background noise;
• enhancing contrast;
• enhancing resolution;
• choosing a specific language;
• choosing particular OCR strategies (balance speed against performance);
• specifying color spaces;
• working with negative images where there is dark text on white backgrounds;
• specifying a document type whether we are looking at a screenshot, a snippet, or an entire document;
• specifying whether or not we wish to spend time correcting for skew, rotation, and perspective within the original scanned image;
• specifying if IronOCR read barcodes when we are performing OCR;
• and choosing the number of bits per pixel within our color depth.

### Example: Safe Defaults

This all may seem daunting, but in the example below you will see the default settings which we would recommend you start with, which will work with almost any image you input to Iron OCR.

var Ocr = new AdvancedOcr()
{
CleanBackgroundNoise = true,
EnhanceContrast = true,
EnhanceResolution = true,
Language = IronOcr.Languages.English.OcrLanguagePack,
DetectWhiteTextOnDarkBackgrounds = true,
RotateAndStraighten = true,
ColorDepth = 4
};

var Results = Ocr.Read("any_image_or_pdf.pdf");
Dim Ocr = New AdvancedOcr() With {
.CleanBackgroundNoise = True,
.EnhanceContrast = True,
.EnhanceResolution = True,
.Language = IronOcr.Languages.English.OcrLanguagePack,
.DetectWhiteTextOnDarkBackgrounds = True,
.RotateAndStraighten = True,
.ColorDepth = 4
}

Dim Results = Ocr.Read("any_image_or_pdf.pdf")
VB   C#

### Example: A Medium Quality Scan

In the following example we will perform OCR on a medium quality TIFF scan of a page from Harry Potter and the Chamber of Secrets.

var Ocr = new AdvancedOcr()
{
CleanBackgroundNoise = false,
EnhanceContrast = true,
EnhanceResolution = false,
Language = IronOcr.Languages.English.OcrLanguagePack,
DetectWhiteTextOnDarkBackgrounds = false,
RotateAndStraighten = false,
ColorDepth = 4
};

var Results = Ocr.Read("img/Potter.tiff");
Dim Ocr = New AdvancedOcr() With {
.CleanBackgroundNoise = False,
.EnhanceContrast = True,
.EnhanceResolution = False,
.Language = IronOcr.Languages.English.OcrLanguagePack,
.DetectWhiteTextOnDarkBackgrounds = False,
.RotateAndStraighten = False,
.ColorDepth = 4
}

Dim Results = Ocr.Read("img/Potter.tiff")
VB   C#

As you can see, reading the text (and optionally barcodes) from a scanned image such as a TIFF was rather easy. This OCR job yields an accuracy of 96.5%. OCR is not a perfect science when it comes to real world documents.

You will also note that Iron OCR can automatically read multipage documents, such as TIFFs and even PDF documents, automatically with these settings.

### Example: A Low Quality Scan

Now we will try a much lower quality scan of the same page, at a low DPI, which has lots of distortion and digital noise and damage to the original paper.

This is where IronOCR truly shines against other OCR libraries such as Tesseract, and we will find alternative OCR projects shy away from discussing. OCR on real world scanned images rather than unrealistically 'perfect' test cases created digitally to give a 100% OCR accuracy.

var Ocr = new AdvancedOcr()
{
CleanBackgroundNoise = true,
EnhanceContrast = true,
EnhanceResolution = true,
Language = IronOcr.Languages.English.OcrLanguagePack,
DetectWhiteTextOnDarkBackgrounds = false,
RotateAndStraighten = true,
ColorDepth = 4
};

var Results = Ocr.Read("img/Potter.LowQuality.tiff");   
Dim Ocr = New AdvancedOcr() With {
.CleanBackgroundNoise = True,
.EnhanceContrast = True,
.EnhanceResolution = True,
.Language = IronOcr.Languages.English.OcrLanguagePack,
.DetectWhiteTextOnDarkBackgrounds = False,
.RotateAndStraighten = True,
.ColorDepth = 4
}

Dim Results = Ocr.Read("img/Potter.LowQuality.tiff")
VB   C#

This OCR job yields an accuracy of 95.6% which is almost as accurate as the OCR of a high quality scan, although it may take a little longer to run.

## Performance Tuning

The most important factor in the speed of an OCR job is in fact the quality of the input image. The less background noise that is present and the higher the dpi, with a perfect target dpi at about 300 dpi, will cause the fastest and most accurate OCR results.

This is not, however, necessary, as Iron OCR shines at correcting imperfect documents (though this is time-consuming and will cause your OCR jobs to use more CPU cycles).

If possible, choosing input image formats with less digital noise such as TIFF or PNG can also yield faster results than lossy image formats such as JPEG.

### Example: Setup for Speed

Using AdvancedOCR, we may wish to disable some of the more time-consuming features, such as clean background noise, enhance contrast, enhance resolution, rotate & straighten, if we do not believe that these features are necessary for our specific input documents. This will save up to 50% of the OCR time.

If optimizing for speed we might start at this position and then turn features back on until the prefect balance is found.

var Ocr = new AdvancedOcr()
{
CleanBackgroundNoise = false,
EnhanceContrast = false,
EnhanceResolution = false,
Language = IronOcr.Languages.English.OcrLanguagePack,
DetectWhiteTextOnDarkBackgrounds = false,
RotateAndStraighten = false,
ColorDepth = 4
};

var Results = Ocr.Read("img/300dpi.png");
Dim Ocr = New AdvancedOcr() With {
.CleanBackgroundNoise = False,
.EnhanceContrast = False,
.EnhanceResolution = False,
.Language = IronOcr.Languages.English.OcrLanguagePack,
.DetectWhiteTextOnDarkBackgrounds = False,
.RotateAndStraighten = False,
.ColorDepth = 4
}

Dim Results = Ocr.Read("img/300dpi.png")
VB   C#

## Reading Cropped Regions of Images

As you can see from the following code sample, Iron OCR is adept at reading specific areas of images. We may use a System.Drawing.Rectangle to specify, in pixels, the exact area of an image to read.

This can be incredibly useful when we are dealing with a standardized form which is filled out, where only a certain area has text which changes from case to case.

### Example: Scanning an Area of a Page

We can use a System.Drawing.Rectangle to specify a region in which we will read a document. The unit of measurement is always pixels.

We will see that this provides speed improvements as well as avoiding reading unnecessary text. In this example we will read a students name from a central area of a standardized document.

var Ocr = new IronOcr.AutoOcr();

var Area = new System.Drawing.Rectangle() { X = 215, Y = 1250, Height = 280, Width = 1335 };

Console.WriteLine(Results.Text);
Dim Ocr = New IronOcr.AutoOcr()

Dim Area = New System.Drawing.Rectangle() With {
.X = 215,
.Y = 1250,
.Height = 280,
.Width = 1335
}

Console.WriteLine(Results.Text)
VB   C#

## International Languages

Iron OCR supports 22 international languages via language packs which are distributed as DLLs, which can be downloaded from this website, or also from the NuGet Package Manager for Visual Studio.

We can install them by browsing NuGet (search for "IronOcr Languages") or from the OCR language packs page.

Supported languages Include:

• English
• Arabic
• ChineseSimplified
• Czech
• Danish
• Finnish
• French
• German
• Greek
• Hebrew
• Hungarian
• Italian
• Japanese
• Korean
• Norwegian
• Polish
• Portuguese
• Russian
• Spanish
• Swedish
• Thai
• Turkish

### Example: OCR in Arabic (+ many more)

In the following example, we will show how we can scan an Arabic document.

PM> Install-Package IronOcr.Languages.Arabic
var Ocr = new AutoOcr()
{
Language = IronOcr.Languages.Arabic.OcrLanguagePack,
};

// Note that the .Net Console can not yet display Arabic characters... they all print as question marks.
Dim Ocr = New AutoOcr() With {.Language = IronOcr.Languages.Arabic.OcrLanguagePack}

' Note that the .Net Console can not yet display Arabic characters... they all print as question marks.
VB   C#

### Example: OCR in more than one languge in the same document.

In the following example, we will show how to OCR scan multiple languages to the same document.

This is actually very common, where for example a Chinese document way contain English words and Urls.

PM> Install-Package IronOcr.Languages.ChineseSimplified
var Ocr = new AdvancedOcr();

Ocr.Language = new IronOcr.Languages.MultiLanguage(IronOcr.Languages.ChineseSimplified.OcrLanguagePack, IronOcr.Languages.English.OcrLanguagePack)
Dim Ocr = New AdvancedOcr()

Ocr.Language = New IronOcr.Languages.MultiLanguage(IronOcr.Languages.ChineseSimplified.OcrLanguagePack, IronOcr.Languages.English.OcrLanguagePack)
VB   C#

## A Detailed Look at Image to Text OCR Results

The last thing we will look at in this tutorial is the OCR results object. When we read OCR, we normally only want the text out, but Iron OCR actually contains a huge amount of information which may be of use to advanced developers.

Within an OCR results object, we have a collection of pages which can be iterated. Within each page, we may find barcodes, power graphs, lines of text, words, and characters.

Each of these objects in fact contains: a location; an X coordinate; a Y coordinate; a width and a height; an image associated with it which can be inspected; a font name; the font size; the direction in which the text is written; the rotation of the text; and the statistical confidence that Iron OCR has for that specific word, line, or paragraph.

In short, this allows developers to create advanced OCR applications and to find out and deal with scenarios where they have less than 100% confidence in their input content.

using IronOcr;
using System;
using System.Collections.Generic;

// We can delve deep into OCR results as an object model of
// Pages, Barcodes, Paragraphs, Lines, Words and Characters
{
Language = IronOcr.Languages.English.OcrLanguagePack,
EnhanceResolution = true,
EnhanceContrast = true,
CleanBackgroundNoise = true,
ColorDepth = 4,
RotateAndStraighten = false,
DetectWhiteTextOnDarkBackgrounds = false,
};

foreach (var page in results.Pages)
{
// page object
int page_number = page.PageNumber;
String page_text = page.Text;
int page_wordcount = page.WordCount;
List<OcrResult.OcrBarcode> barcodes = page.Barcodes;
System.Drawing.Image page_image = page.Image;
int page_width_px = page.Width;
int page_height_px = page.Height;
foreach (var paragraph in page.Paragraphs)
{
// pages -> paragraphs
int paragraph_number = paragraph.ParagraphNumber;
String paragraph_text = paragraph.Text;
System.Drawing.Image paragraph_image = paragraph.Image;
int paragraph_x_location = paragraph.X;
int paragraph_y_location = paragraph.Y;
int paragraph_width = paragraph.Width;
int paragraph_height = paragraph.Height;
double paragraph_ocr_accuracy = paragraph.Confidence;
string paragraph_font_name = paragraph.FontName;
double paragraph_font_size = paragraph.FontSize;
OcrResult.TextFlow paragrapth_text_direction = paragraph.TextDirection;
double paragrapth_rotation_degrees = paragraph.TextOrientation;
foreach (var line in paragraph.Lines)
{
// pages -> paragraphs -> lines
int line_number = line.LineNumber;
String line_text = line.Text;
System.Drawing.Image line_image = line.Image;
int line_x_location = line.X;
int line_y_location = line.Y;
int line_width = line.Width;
int line_height = line.Height;
double line_ocr_accuracy = line.Confidence;
double line_skew = line.BaselineAngle;
double line_offset = line.BaselineOffset;
foreach (var word in line.Words)
{
// pages -> paragraphs -> lines -> words
int word_number = word.WordNumber;
String word_text = word.Text;
System.Drawing.Image word_image = word.Image;
int word_x_location = word.X;
int word_y_location = word.Y;
int word_width = word.Width;
int word_height = word.Height;
double word_ocr_accuracy = word.Confidence;
String word_font_name = word.FontName;
double word_font_size = word.FontSize;
bool word_is_bold = word.FontIsBold;
bool word_is_fixed_width_font = word.FontIsFixedWidth;
bool word_is_italic = word.FontIsItalic;
bool word_is_serif_font = word.FontIsSerif;
bool word_is_underlined = word.FontIsUnderlined;
foreach (var character in word.Characters)
{
// pages -> paragraphs -> lines -> words -> characters
int character_number = character.CharacterNumber;
String character_text = character.Text;
System.Drawing.Image character_image = character.Image;
int character_x_location = character.X;
int character_y_location = character.Y;
int character_width = character.Width;
int character_height = character.Height;
double character_ocr_accuracy = character.Confidence;
}
}
}
}
}
Imports IronOcr
Imports System
Imports System.Collections.Generic

' We can delve deep into OCR results as an object model of
' Pages, Barcodes, Paragraphs, Lines, Words and Characters

Dim Ocr = New AdvancedOcr() With {
.Language = IronOcr.Languages.English.OcrLanguagePack,
.EnhanceResolution = True,
.EnhanceContrast = True,
.CleanBackgroundNoise = True,
.ColorDepth = 4,
.RotateAndStraighten = False,
.DetectWhiteTextOnDarkBackgrounds = False,
}

For Each page In results.Pages
' page object
Dim page_number As Integer = page.PageNumber
Dim page_text As String = page.Text
Dim page_wordcount As Integer = page.WordCount
Dim barcodes As List(Of OcrResult.OcrBarcode) = page.Barcodes
Dim page_image As System.Drawing.Image = page.Image
Dim page_width_px As Integer = page.Width
Dim page_height_px As Integer = page.Height
For Each paragraph In page.Paragraphs
' pages -> paragraphs
Dim paragraph_number As Integer = paragraph.ParagraphNumber
Dim paragraph_text As String = paragraph.Text
Dim paragraph_image As System.Drawing.Image = paragraph.Image
Dim paragraph_x_location As Integer = paragraph.X
Dim paragraph_y_location As Integer = paragraph.Y
Dim paragraph_width As Integer = paragraph.Width
Dim paragraph_height As Integer = paragraph.Height
Dim paragraph_ocr_accuracy As Double = paragraph.Confidence
Dim paragraph_font_name As String = paragraph.FontName
Dim paragraph_font_size As Double = paragraph.FontSize
Dim paragrapth_text_direction As OcrResult.TextFlow = paragraph.TextDirection
Dim paragrapth_rotation_degrees As Double = paragraph.TextOrientation
For Each line In paragraph.Lines
' pages -> paragraphs -> lines
Dim line_number As Integer = line.LineNumber
Dim line_text As String = line.Text
Dim line_image As System.Drawing.Image = line.Image
Dim line_x_location As Integer = line.X
Dim line_y_location As Integer = line.Y
Dim line_width As Integer = line.Width
Dim line_height As Integer = line.Height
Dim line_ocr_accuracy As Double = line.Confidence
Dim line_skew As Double = line.BaselineAngle
Dim line_offset As Double = line.BaselineOffset
For Each word In line.Words
' pages -> paragraphs -> lines -> words
Dim word_number As Integer = word.WordNumber
Dim word_text As String = word.Text
Dim word_image As System.Drawing.Image = word.Image
Dim word_x_location As Integer = word.X
Dim word_y_location As Integer = word.Y
Dim word_width As Integer = word.Width
Dim word_height As Integer = word.Height
Dim word_ocr_accuracy As Double = word.Confidence
Dim word_font_name As String = word.FontName
Dim word_font_size As Double = word.FontSize
Dim word_is_bold As Boolean = word.FontIsBold
Dim word_is_fixed_width_font As Boolean = word.FontIsFixedWidth
Dim word_is_italic As Boolean = word.FontIsItalic
Dim word_is_serif_font As Boolean = word.FontIsSerif
Dim word_is_underlined As Boolean = word.FontIsUnderlined
For Each character In word.Characters
' pages -> paragraphs -> lines -> words -> characters
Dim character_number As Integer = character.CharacterNumber
Dim character_text As String = character.Text
Dim character_image As System.Drawing.Image = character.Image
Dim character_x_location As Integer = character.X
Dim character_y_location As Integer = character.Y
Dim character_width As Integer = character.Width
Dim character_height As Integer = character.Height
Dim character_ocr_accuracy As Double = character.Confidence
Next character
Next word
Next line
Next paragraph
Next page
VB   C#

Putting this all together, we can see that if we input even an imperfect document [insert document] to Iron OCR, it can accurately read its content to a statistical accuracy of about 98% to 99%, even though the document was badly formatted, skewed, and had a lot of digital noise. This is unique to Iron OCR and is a feature you will not find in standard OCR libraries.

## Moving Forward

To continue to learn more about Iron OCR, we recommend you try the code samples on the IronOCR homepage, visit us on GitHub, or read the in-depth MSDN-style Object Reference.

You may also enjoy the other .Net OCR tutorials in this section.

### Gemma Beckford

#### Microsoft Solution Engineer

Gemma has been leading the Content Archiving Solution Team at a large Document Archive Software Company for over 5 years. IronOCR has allowed her team to improve the accuracy or their machine read documentation since implementation in 2017. Gemma uses IronOCR to read from banks of thousands of images produced on a weekly basis.