Introduction

Wow! The most desired library is now supported for Windows Phone 8.1. Many developers have been waiting for this library, and finally it was released by Microsoft in the last "Preview Program". The Optical Character Recognition (OCR) library is helpful to read text from images and it returns the text and layout information.

OCR library features

OCR Limitations

An inaccurate reading may be caused by the following:

The following describes how to build the sample:

Download and install the OCR Library

This library is not included in the Windows Software Development Kit (SDK) and it is distributed as a NuGet package, so to install this library right-click on your project then click on "Manage NuGet Packages" then seelct "Online" then search for "Microsoft.Windows.Ocr.". Then click on the "Install" button. See the following image for your reference.



"Any CPU" problem

This library does not work on an "AnyCPU" target platform. To change the build configuration of your project from AnyCPU to x86, x64, or ARM right-click on the solution then click on Configuration Properties -> Configuration Manager and change the active solution platform to x86 (If you are using an emulator) or ARM (if you are using a Windows Phone device).

After you install the OCR library into your project, the "OcrResources" folder will be added to your project that has the "MsOcrRes.orp" file.

When you install the package, the file <solution_name>\packages\Microsoft.Windows.Ocr.1.0.0\OcrResources \MsOcrRes.orp is copied and injected into your project in the location <solution_name>\<project_name>\OcrResources\MsOcrRes.orp. This file is consumed by the OcrEngine object for text recognition in a specific language.

OCR supported languages

There are 21 supported languages. Based on recognition accuracy and performance, supported languages are divided into the following three groups:

Note: By default English language resources are included in the target project. If you want to use a custom group of languages in your app, use the OCR Resources Generator tool to generate a new OCR resources file and replace the resources that were injected into your project when you installed the package.

To generate OCR resource files:

How to extract text from an image

Step 1

In the page constructor, create and initialize a global instance of the OcrEngine. Also declare two unsigned integer variables to store the width and height of the image.

Step 2

Load the image, convert it to WriteableBitmap to get image pixels height and width.

Step 3

Check the image dimensions, it should be > 40*40 pixels and < 2600*2600 pixels.

Step 4

Call the RecognizeAsync method of the OcrEngine class. This method returns an OcrResult object that contains the recognized text and its size and position. The result is split into lines and the lines are split into words.

Step 5

After the preceding procedure your code is like this for extracting the text from an image.

C# language

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Runtime.InteropServices.WindowsRuntime;
  6. using System.Threading.Tasks;
  7. using Windows.Foundation;
  8. using Windows.Foundation.Collections;
  9. using Windows.Storage;
  10. using Windows.Storage.FileProperties;
  11. using Windows.UI;
  12. using Windows.UI.Xaml;
  13. using Windows.UI.Xaml.Controls;
  14. using Windows.UI.Xaml.Controls.Primitives;
  15. using Windows.UI.Xaml.Data;
  16. using Windows.UI.Xaml.Input;
  17. using Windows.UI.Xaml.Media;
  18. using Windows.UI.Xaml.Media.Imaging;
  19. using Windows.UI.Xaml.Navigation;
  20. using WindowsPreview.Media.Ocr;

  21. namespace OCRImgReadText
  22. {
  23. public sealed partial class MainPage : Page
  24. {
  25. // Bitmap holder of currently loaded image.
  26. private WriteableBitmap bitmap;
  27. // OCR engine instance used to extract text from images.
  28. private OcrEngine ocrEngine;
  29. public MainPage()
  30. {
  31. this.InitializeComponent();
  32. ocrEngine = new OcrEngine(OcrLanguage.English);
  33. TextOverlay.Children.Clear();
  34. }
  35. protected override async void OnNavigatedTo(NavigationEventArgs e)
  36. { //Get local image
  37. var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync("TestImages\\SQuotes.jpg");
  38. await LoadImage(file);
  39. }
  40. private async Task LoadImage(StorageFile file)
  41. {
  42. ImageProperties imgProp = await file.Properties.GetImagePropertiesAsync();
  43. using (var imgStream = await file.OpenAsync(FileAccessMode.Read))
  44. {
  45. bitmap = new WriteableBitmap((int)imgProp.Width, (int)imgProp.Height);
  46. bitmap.SetSource(imgStream);
  47. PreviewImage.Source = bitmap;
  48. }
  49. }
  50. private async void ExtractText_Click(object sender, RoutedEventArgs e)
  51. {
  52. //// Prevent another OCR request, since only image can be processed at the time at same OCR engine instance.
  53. //ExtractTextButton.IsEnabled = false;
  54. // Check whether is loaded image supported for processing.
  55. // Supported image dimensions are between 40 and 2600 pixels.
  56. if (bitmap.PixelHeight < 40 ||
  57. bitmap.PixelHeight > 2600 ||
  58. bitmap.PixelWidth < 40 ||
  59. bitmap.PixelWidth > 2600)
  60. {
  61. ImageText.Text = "Image size is not supported." +
  62. Environment.NewLine +
  63. "Loaded image size is " + bitmap.PixelWidth + "x" + bitmap.PixelHeight + "." +
  64. Environment.NewLine +
  65. "Supported image dimensions are between 40 and 2600 pixels.";
  66. //ImageText.Style = (Style)Application.Current.Resources["RedTextStyle"];
  67. return;
  68. }
  69. // This main API call to extract text from image.
  70. var ocrResult = await ocrEngine.RecognizeAsync((uint)bitmap.PixelHeight, (uint)bitmap.PixelWidth, bitmap.PixelBuffer.ToArray());
  71. // OCR result does not contain any lines, no text was recognized.
  72. if (ocrResult.Lines != null)
  73. {
  74. // Used for text overlay.
  75. // Prepare scale transform for words since image is not displayed in original format.
  76. var scaleTrasform = new ScaleTransform
  77. {
  78. CenterX = 0,
  79. CenterY = 0,
  80. ScaleX = PreviewImage.ActualWidth / bitmap.PixelWidth,
  81. ScaleY = PreviewImage.ActualHeight / bitmap.PixelHeight,
  82. };
  83. if (ocrResult.TextAngle != null)
  84. {
  85. PreviewImage.RenderTransform = new RotateTransform
  86. {
  87. Angle = (double)ocrResult.TextAngle,
  88. CenterX = PreviewImage.ActualWidth / 2,
  89. CenterY = PreviewImage.ActualHeight / 2
  90. };
  91. }
  92. string extractedText = "";
  93. // Iterate over recognized lines of text.
  94. foreach (var line in ocrResult.Lines)
  95. {
  96. // Iterate over words in line.
  97. foreach (var word in line.Words)
  98. {
  99. var originalRect = new Rect(word.Left, word.Top, word.Width, word.Height);
  100. var overlayRect = scaleTrasform.TransformBounds(originalRect);
  101. var wordTextBlock = new TextBlock()
  102. {
  103. Height = overlayRect.Height,
  104. Width = overlayRect.Width,
  105. FontSize = overlayRect.Height * 0.8,
  106. Text = word.Text,
  107. };
  108. // Define position, background, etc.
  109. var border = new Border()
  110. {
  111. Margin = new Thickness(overlayRect.Left, overlayRect.Top, 0, 0),
  112. Height = overlayRect.Height,
  113. Width = overlayRect.Width,
  114. Background = new SolidColorBrush(Colors.Orange),
  115. Opacity = 0.5,
  116. HorizontalAlignment = HorizontalAlignment.Left,
  117. VerticalAlignment = VerticalAlignment.Top,
  118. Child = wordTextBlock,
  119. };
  120. OverlayTextButton.IsEnabled = true;
  121. // Put the filled textblock in the results grid.
  122. TextOverlay.Children.Add(border);
  123. extractedText += word.Text + " ";
  124. }
  125. extractedText += Environment.NewLine;
  126. }
  127. ImageText.Text = extractedText;
  128. }
  129. else
  130. {
  131. ImageText.Text = "No text.";
  132. }
  133. }
  134. private void OverlayText_Click(object sender, RoutedEventArgs e)
  135. {
  136. if (TextOverlay.Visibility == Visibility.Visible)
  137. {
  138. TextOverlay.Visibility = Visibility.Collapsed;
  139. }
  140. else
  141. {
  142. TextOverlay.Visibility = Visibility.Visible;
  143. }
  144. }
  145. }
  146. }

Step 6

And your UI might be like the following.

XAML code

  1. <Grid>
  2. <Grid.RowDefinitions>
  3. <RowDefinition Height="Auto"/>
  4. <RowDefinition Height="Auto"/>
  5. <RowDefinition Height="*"/>
  6. </Grid.RowDefinitions>
  7. <StackPanel Grid.Row="1" x:Name="ControlPanel" Orientation="Vertical">
  8. <StackPanel Orientation="Horizontal" Margin="10,0,10,0" >
  9. <Button x:Name="ExtractTextButton" Content="Extract Image Text" FontSize="15" MinWidth="90" Click="ExtractText_Click" Margin="0,0,5,0"/>
  10. <Button x:Name="OverlayTextButton" IsEnabled="False" Content="Overlay Image Text" FontSize="15" MinWidth="90" Click="OverlayText_Click" Margin="0,0,5,0"/>
  11. </StackPanel>
  12. <StackPanel Grid.Row="1" Orientation="Horizontal"/>
  13. </StackPanel>
  14. <ScrollViewer Grid.Row="2" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto" Margin="0, 10, 0, 0">
  15. <!-- This StackPanel changes its Orientation depending on the available width of the window. -->
  16. <StackPanel x:Name="Output" Margin="10,0,10,0" Orientation="Vertical" Visibility="Visible">
  17. <StackPanel x:Name="Content" Orientation="Vertical" Visibility="Visible">
  18. <Grid x:Name="Image">
  19. <Image x:Name="PreviewImage" Margin="0,0,10,10" Source="" Stretch="Uniform" Width="300" HorizontalAlignment="Left" VerticalAlignment="Top"/>
  20. <Grid x:Name="TextOverlay" Visibility="Collapsed" Margin="0,0,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
  21. </Grid>
  22. <!-- This StackPanel contains all of the image properties output. -->
  23. <Grid x:Name="Result" HorizontalAlignment="Left" VerticalAlignment="Top">
  24. <Grid.RowDefinitions>
  25. <RowDefinition Height="Auto"/>
  26. <RowDefinition Height="Auto"/>
  27. </Grid.RowDefinitions>
  28. <TextBlock Grid.Row="0" FontSize="25" Text="Extracted image text:" />
  29. <TextBlock Name="ImageText" Grid.Row="1" Foreground="#FF1CD399" FontSize="25" Text="Text not yet extracted."/>
  30. </Grid>
  31. </StackPanel>
  32. </StackPanel>
  33. </ScrollViewer>
  34. </Grid>
Output





Note:
When you download and run this code then you will get an error since you must install the OCR library from "Manage NuGet Packages".


Summary

In this article we have learned how the OCR library has made it easy to read text from images in Windows Phone 8.1.