Reading Text from an image in .Net is a complex operation that requires extension image pre processing. IronOCR helps to automate processing of images and reads using an advanced OCR engine

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 };
var Results = OCR.Read("img/Screenshot.png");
Console.WriteLine(Results.Text);
Imports IronOcr
Dim OCR As AutoOcr = New AutoOcr
Dim Results As var = OCR.Read("img/Screenshot.png")
Console.WriteLine(Results.Text)
VB   C#
C# OCR of a Screenshot

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.

C# OCR application results accuracy

Advanced OCR

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,
    Strategy = IronOcr.AdvancedOcr.OcrStrategy.Advanced,
    ColorSpace = AdvancedOcr.OcrColorSpace.Color,
    DetectWhiteTextOnDarkBackgrounds = true,
    InputImageType = AdvancedOcr.InputTypes.Document,
    RotateAndStraighten = true,
    ReadBarCodes = true,
    ColorDepth = 4
};

var Results = Ocr.Read("any_image_or_pdf.pdf");
Dim Ocr As var = New AdvancedOcr
Dim Results As var = Ocr.Read("any_image_or_pdf.pdf")
VB   C#

Example: A Medium Quality Scan


C# OCR Scan From Tiff Example

In teh 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,
    Strategy = IronOcr.AdvancedOcr.OcrStrategy.Advanced,
    ColorSpace = AdvancedOcr.OcrColorSpace.Color,
    DetectWhiteTextOnDarkBackgrounds = false,
    InputImageType = AdvancedOcr.InputTypes.Document,
    RotateAndStraighten = false,
    ReadBarCodes = false,
    ColorDepth = 4
};

var Results = Ocr.Read("img/Potter.tiff");
Dim Ocr As var = New AdvancedOcr
Dim Results As var = 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


C# OCR Low Resolution Scan with Digital Noise

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,
    Strategy = IronOcr.AdvancedOcr.OcrStrategy.Advanced,
    ColorSpace = AdvancedOcr.OcrColorSpace.GrayScale,
    DetectWhiteTextOnDarkBackgrounds = false,
    InputImageType = AdvancedOcr.InputTypes.Document,
    RotateAndStraighten = true,
    ReadBarCodes = false,
    ColorDepth = 4
};

var Results = Ocr.Read("img/Potter.LowQuality.tiff");   
Dim Ocr As var = New AdvancedOcr
Dim Results As var = 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.

C# OCR Scan Accuracy

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,
    Strategy = IronOcr.AdvancedOcr.OcrStrategy.Fast,
    ColorSpace = AdvancedOcr.OcrColorSpace.GrayScale,
    DetectWhiteTextOnDarkBackgrounds = false,
    InputImageType = AdvancedOcr.InputTypes.Document,
    RotateAndStraighten = false,
    ReadBarCodes = false,
    ColorDepth = 4
};

var Results = Ocr.Read("img/300dpi.png");
Dim Ocr As var = New AdvancedOcr
Dim Results As var = 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.


C# OCR Scan From Tiff Example   C# OCR Scan From Tiff Example


var Ocr = new IronOcr.AutoOcr();

var Area = new System.Drawing.Rectangle() { X = 215, Y = 1250, Height = 280, Width = 1335 };
var Results = Ocr.Read("img/ComSci.Png", Area);

Console.WriteLine(Results.Text);
Dim Ocr As var = New IronOcr.AutoOcr
Dim Area As var = New System.Drawing.Rectangle
Dim Results As var = Ocr.Read("img/ComSci.Png", Area)
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
  • ChineseTraditional
  • 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
C# OCR in Arabic Language
var Ocr = new AutoOcr()
{
    Language = IronOcr.Languages.Arabic.OcrLanguagePack,
};

var Results = Ocr.Read("img/arabic.gif");

Console.WriteLine("{0} Characters of Arabic Read",Results.Text.Length);
// Note that the .Net Console can not yet display Arabic characters... they all print as question marks.
Dim Ocr As var = New AutoOcr
Dim Results As var = Ocr.Read("img/arabic.gif")
Console.WriteLine("{0} Characters of Arabic Read", Results.Text.Length)
' 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 As var = 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;
using System.Drawing; //Add Assembly Reference

// We can delve deep into OCR results as an object model of
// Pages, Barcodes, Paragraphs, Lines, Words and Characters
var Ocr = new AdvancedOcr()
{
    Language = IronOcr.Languages.English.OcrLanguagePack,
    ColorSpace = AdvancedOcr.OcrColorSpace.GrayScale,
    EnhanceResolution = true,
    EnhanceContrast = true,
    CleanBackgroundNoise = true,
    ColorDepth = 4,
    RotateAndStraighten = false,
    DetectWhiteTextOnDarkBackgrounds = false,
    ReadBarCodes = true,
    Strategy = AdvancedOcr.OcrStrategy.Fast,
    InputImageType = AdvancedOcr.InputTypes.Document
};
var results = Ocr.Read(@"path\to\document.png");

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
Imports System.Drawing
Dim Ocr As var = New AdvancedOcr
Dim results As var = Ocr.Read("path\to\document.png")
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
            Next
        Next
    Next
Next
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.

Source Code Download

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

Gemma brings her Microsoft expertise to the archiving software industry, implementing the leading OCR soilutiuons for archiving millkions of printed documents using OCR for C# VB .Net

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.