How to implement OCR (Optical Character Recognition) in C#

In this article you will find all the needed information to satisfy your curiosity on the subject of optical character recognition. OCR is a technology, which makes possible to recover data from a printed document, a PDF file or a picture captured. This means that you can convert documents into a searchable and editable data. After reading this manual you will be able to implement OCR succesfully with your C# camera application. To succeed, Ozeki Camera SDK has to be installed and a reference to OzekiSDK.dll has to be added to your Visual Studio project.

detected characters in c#
Figure 1 - Detected characters on a can

Important: you should study this article in order to find out how to setup your Windows Forms Application correctly.

Getting started

To get started it is recomended to Download and Install the latest version of Ozeki Camera SDK. After installation you can find the example code discussed in this page with full source code in the following location on your harddisk:

Download Ozeki Camera SDK: https://www.camera-sdk.com/https://camera-sdk.com/p_6513-download-onvif-ozeki-camera-sdk-for-c-sharp.html
Windows forms version: C:\Users\user\Documents\Ozeki\Ozeki SDK\Examples\Camera\04_ComputerVision\08_OCR

To compile this example you will need Microsoft Visual Studio installed on your computer.

Corporate use of Optical Character Recognition

Optical character recognition is used when people wish to recover data from a printed form for example: business cards, invoices, bank statesments, receipts and passport documents. With this function you can digitize printed text so they will be editable and storable. What is more, you will be able to publish these digitized texts on online surfaces and you can use them in computer vision applications, in text-to-speech or translation.

The Optical Character Recognition function can be efficiently used in many fields. For example: converting written version of documents into textual version, making electronic documents reachable and searchable. Furthermore, OCR can be a supportive technology for visually impaired people.

Implement Optical Character Recognition in C#

Namespace: Ozeki.Vision

Property:

  • DrawColor: It is a value which helps us to determine the color of the detected characters.
  • DrawThickness: It is an int value which helps us to determine the thickness of the detected characters.

Constructor:

ICharacterDetector _characterDetector =
ImageProcesserFactory.CreateCharacterDetector(@"", "eng", OcrEngineMode.FASTEST);

  • First parameter: It is a string value which is the path of the language file.
  • Second parameter:It is a string value which is the language that you wish to use.
  • Third parameter: It is an enum value, set to better or faster recognition.

Event:

  • DetectionOccured: This is an event which is called when a text is detected.
  • The found texts have two available properties:

    Content: A string value, it is the found appropiate text itself.

    Characters: A character block which stores the information about the detected characters.

  • Text: This is a string value, the character itself.
  • Cost: This is a float value, the lower it is, the more confident the result is.
  • Region: This is a rectangle value, the region where the character is detected.

Method:

void SetVariable(CharacterFilterMode variableName, String value, bool
isBetterAccuracy);

With this method you can put the characters to White or Black lists which helps you to set the list of characters which you wish to display. This can be used to specify a white list for OCR. For example: specify "0123456789" to recognize digits only.

  • First parameter: An enum value, here you can set the WhiteList or BlackList.
  • Second parameter: A string value, here you should provide the characters which you would like to put on the lists.
  • Third parameter: A bool value, if it is true it can make a better accuracy processing.

C# code example for OCR

MainForm.cs

using System;
using System.Windows.Forms;
using Ozeki.Camera;
using Ozeki.Media;
using Ozeki.Vision;

namespace OCR_WF
{
    public partial class MainForm : Form
    {
        private OzekiCamera _camera;
        private MediaConnector _connector;
        private CameraURLBuilderWF _myCameraUrlBuilder;
        private ImageProcesserHandler _imageProcesserHandler;
        private ILicensePlateRecognizer _licensePlateRecognizer;
        private ICharacterDetector _characterDetector;
        //private FrameCapture _frameCapture;
        private DrawingImageProvider _originalImageProvider;
        private DrawingImageProvider _processedImageProvider;

        public MainForm()
        {
            InitializeComponent();
        }

        void MainForm_Load(object sender, EventArgs e)
        {
            Init();

            SetVideoViewers();

            InitDetectorFields();

        }

        void Init()
        {
           // _frameCapture = new FrameCapture();
           // _frameCapture.SetInterval(5);
            _myCameraUrlBuilder = new CameraURLBuilderWF();
            _connector = new MediaConnector();
            _originalImageProvider = new DrawingImageProvider();
            _processedImageProvider = new DrawingImageProvider();

            _characterDetector = ImageProcesserFactory.CreateCharacterDetector(OCRDetectionMode.FASTEST);
            _characterDetector.DetectionOccurred += _characterDetector_DetectionOccurred;

            _imageProcesserHandler = new ImageProcesserHandler();
            _imageProcesserHandler.AddProcesser(_characterDetector);

        }

        void SetVideoViewers()
        {
            OriginalViewer.SetImageProvider(_originalImageProvider);
            ProcessedViewer.SetImageProvider(_processedImageProvider);
        }

        void InitDetectorFields()
        {
            InvokeGuiThread(() =>
            {

            });
        }

        void ConnectCam()
        {
            _connector.Connect(_camera.VideoChannel, _originalImageProvider);

           // _connector.Connect(_camera.VideoChannel, _frameCapture);
           // _connector.Connect(_frameCapture, _imageProcesserHandler);
            _connector.Connect(_camera.VideoChannel, _imageProcesserHandler);
            _connector.Connect(_imageProcesserHandler, _processedImageProvider);

        }

        void Start()
        {
            OriginalViewer.Start();
            ProcessedViewer.Start();

         //   _frameCapture.Start();
            _camera.Start();
            _imageProcesserHandler.Start();
        }

        void btn_HighlightSet_Click(object sender, EventArgs e)
        {
            InvokeGuiThread(() =>
            {

            });
        }

        void _characterDetector_DetectionOccurred(object sender, TextDetectedEventArgs e)
        {
            InvokeGuiThread(() =>
                textBoxDetectedText.Text = e.DetectedText.Content
            );
        }

        void InvokeGuiThread(Action action)
        {
            BeginInvoke(action);
        }

        private void button_Compose_Click(object sender, EventArgs e)
        {
            var result = _myCameraUrlBuilder.ShowDialog();

            if (result != DialogResult.OK) return;

            tb_cameraUrl.Text = _myCameraUrlBuilder.CameraURL;

            button_Connect.Enabled = true;
        }

        private void button_Connect_Click(object sender, EventArgs e)
        {
            if (_camera != null)
            {
                _camera.CameraStateChanged -= _camera_CameraStateChanged;
                _camera.Disconnect();
                _connector.Disconnect(_camera.VideoChannel, _processedImageProvider);
                _connector.Disconnect(_camera.VideoChannel, _originalImageProvider);
                _camera.Dispose();
                _camera = null;
            }

            _camera = new OzekiCamera(_myCameraUrlBuilder.CameraURL);
            _camera.CameraStateChanged += _camera_CameraStateChanged;

            button_Connect.Enabled = false;

            ConnectCam();

            Start();
        }

        private void _camera_CameraStateChanged(object sender, CameraStateEventArgs e)
        {
            InvokeGuiThread(() =>
            {
                if (e.State == CameraState.Connecting)
                    button_Connect.Enabled = false;
                if (e.State == CameraState.Streaming)
                    button_Disconnect.Enabled = true;
                if (e.State == CameraState.Disconnected)
                {
                    button_Disconnect.Enabled = false;
                    button_Connect.Enabled = true;
                }
            });

            InvokeGuiThread(() =>
            {
                stateLabel.Text = e.State.ToString();
            });
        }

        private void button_Disconnect_Click(object sender, EventArgs e)
        {
            if (_camera == null) return;

            _camera.Disconnect();
            _connector.Disconnect(_camera.VideoChannel, _processedImageProvider);
            _connector.Disconnect(_camera.VideoChannel, _originalImageProvider);

            _camera = null;
        }

        void Filter_Changed(object sender, EventArgs e)
        {
            if (radioButtonBlack.Checked)
                _characterDetector.SetVariable(CharacterFilterMode.BlackList, "", true);
            else
                _characterDetector.SetVariable(CharacterFilterMode.WhiteList, "", true);
        }

    }
}


	

Code 1 - Optical Character Recognition example in C#

GUI

gui of an application for barcode scanning/qr code detecting from the video stream of an ip camera in c#
Figure 2 - The graphical user interface of your application

Below you can find the code that belongs to the interface of the previously presented application. With the help of this section your Windows Forms Application will be able to work properly.

MainForm.Designer.cs

namespace OCR_WF
{
    partial class MainForm
    {
        private System.ComponentModel.IContainer components = null;

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        private void InitializeComponent()
        {
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.radioButtonBlack = new System.Windows.Forms.RadioButton();
            this.radioButtonWhite = new System.Windows.Forms.RadioButton();
            this.groupBox5 = new System.Windows.Forms.GroupBox();
            this.stateLabel = new System.Windows.Forms.Label();
            this.label14 = new System.Windows.Forms.Label();
            this.button_Connect = new System.Windows.Forms.Button();
            this.button_Disconnect = new System.Windows.Forms.Button();
            this.tb_cameraUrl = new System.Windows.Forms.TextBox();
            this.label13 = new System.Windows.Forms.Label();
            this.button_Compose = new System.Windows.Forms.Button();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.textBoxDetectedText = new System.Windows.Forms.TextBox();
            this.OriginalViewer = new Ozeki.Media.VideoViewerWF();
            this.ProcessedViewer = new Ozeki.Media.VideoViewerWF();
            this.label2 = new System.Windows.Forms.Label();
            this.label1 = new System.Windows.Forms.Label();
            this.label12 = new System.Windows.Forms.Label();
            this.groupBox2.SuspendLayout();
            this.groupBox5.SuspendLayout();
            this.groupBox1.SuspendLayout();
            this.SuspendLayout();
 
            this.groupBox2.Controls.Add(this.radioButtonBlack);
            this.groupBox2.Controls.Add(this.radioButtonWhite);
            this.groupBox2.Location = new System.Drawing.Point(359, 12);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Size = new System.Drawing.Size(320, 89);
            this.groupBox2.TabIndex = 13;
            this.groupBox2.TabStop = false;
            this.groupBox2.Text = "Settings";

            this.radioButtonBlack.AutoSize = true;
            this.radioButtonBlack.Location = new System.Drawing.Point(180, 20);
            this.radioButtonBlack.Name = "radioButtonBlack";
            this.radioButtonBlack.Size = new System.Drawing.Size(71, 17);
            this.radioButtonBlack.TabIndex = 1;
            this.radioButtonBlack.TabStop = true;
            this.radioButtonBlack.Text = "Black List";
            this.radioButtonBlack.UseVisualStyleBackColor = true;
            this.radioButtonBlack.CheckedChanged += new System.EventHandler(this.Filter_Changed);

            this.radioButtonWhite.AutoSize = true;
            this.radioButtonWhite.Location = new System.Drawing.Point(42, 20);
            this.radioButtonWhite.Name = "radioButtonWhite";
            this.radioButtonWhite.Size = new System.Drawing.Size(72, 17);
            this.radioButtonWhite.TabIndex = 0;
            this.radioButtonWhite.TabStop = true;
            this.radioButtonWhite.Text = "White List";
            this.radioButtonWhite.UseVisualStyleBackColor = true;
            this.radioButtonWhite.CheckedChanged += new System.EventHandler(this.Filter_Changed);

            this.groupBox5.Controls.Add(this.stateLabel);
            this.groupBox5.Controls.Add(this.label14);
            this.groupBox5.Controls.Add(this.button_Connect);
            this.groupBox5.Controls.Add(this.button_Disconnect);
            this.groupBox5.Controls.Add(this.tb_cameraUrl);
            this.groupBox5.Controls.Add(this.label13);
            this.groupBox5.Controls.Add(this.button_Compose);
            this.groupBox5.Location = new System.Drawing.Point(12, 12);
            this.groupBox5.Name = "groupBox5";
            this.groupBox5.Size = new System.Drawing.Size(325, 89);
            this.groupBox5.TabIndex = 21;
            this.groupBox5.TabStop = false;
            this.groupBox5.Text = "Connect";

            this.stateLabel.AutoSize = true;
            this.stateLabel.Location = new System.Drawing.Point(80, 72);
            this.stateLabel.Name = "stateLabel";
            this.stateLabel.Size = new System.Drawing.Size(0, 13);
            this.stateLabel.TabIndex = 24;

            this.label14.AutoSize = true;
            this.label14.Location = new System.Drawing.Point(39, 72);
            this.label14.Name = "label14";
            this.label14.Size = new System.Drawing.Size(35, 13);
            this.label14.TabIndex = 23;
            this.label14.Text = "State:";

            this.button_Connect.Enabled = false;
            this.button_Connect.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
            this.button_Connect.ForeColor = System.Drawing.Color.Black;
            this.button_Connect.Location = new System.Drawing.Point(83, 39);
            this.button_Connect.Name = "button_Connect";
            this.button_Connect.Size = new System.Drawing.Size(69, 23);
            this.button_Connect.TabIndex = 18;
            this.button_Connect.Text = "Connect";
            this.button_Connect.UseVisualStyleBackColor = true;
            this.button_Connect.Click += new System.EventHandler(this.button_Connect_Click);
 
            this.button_Disconnect.Enabled = false;
            this.button_Disconnect.Location = new System.Drawing.Point(180, 39);
            this.button_Disconnect.Name = "button_Disconnect";
            this.button_Disconnect.Size = new System.Drawing.Size(69, 23);
            this.button_Disconnect.TabIndex = 22;
            this.button_Disconnect.Text = "Disconnect";
            this.button_Disconnect.UseVisualStyleBackColor = true;
            this.button_Disconnect.Click += new System.EventHandler(this.button_Disconnect_Click);

            this.tb_cameraUrl.Location = new System.Drawing.Point(83, 13);
            this.tb_cameraUrl.Name = "tb_cameraUrl";
            this.tb_cameraUrl.ReadOnly = true;
            this.tb_cameraUrl.Size = new System.Drawing.Size(166, 20);
            this.tb_cameraUrl.TabIndex = 21;

            this.label13.AutoSize = true;
            this.label13.Location = new System.Drawing.Point(6, 16);
            this.label13.Name = "label13";
            this.label13.Size = new System.Drawing.Size(71, 13);
            this.label13.TabIndex = 20;
            this.label13.Text = "Camera URL:";

            this.button_Compose.Location = new System.Drawing.Point(253, 11);
            this.button_Compose.Name = "button_Compose";
            this.button_Compose.Size = new System.Drawing.Size(69, 23);
            this.button_Compose.TabIndex = 19;
            this.button_Compose.Text = "Compose";
            this.button_Compose.UseVisualStyleBackColor = true;
            this.button_Compose.Click += new System.EventHandler(this.button_Compose_Click);

            this.groupBox1.Controls.Add(this.textBoxDetectedText);
            this.groupBox1.Location = new System.Drawing.Point(12, 398);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(667, 147);
            this.groupBox1.TabIndex = 22;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "Detected text";

            this.textBoxDetectedText.Location = new System.Drawing.Point(3, 19);
            this.textBoxDetectedText.Multiline = true;
            this.textBoxDetectedText.Name = "textBoxDetectedText";
            this.textBoxDetectedText.Size = new System.Drawing.Size(662, 122);
            this.textBoxDetectedText.TabIndex = 1;

            this.OriginalViewer.BackColor = System.Drawing.Color.Black;
            this.OriginalViewer.FlipMode =Ozeki.Media.FlipMode.None;
            this.OriginalViewer.FrameStretch = Ozeki.Media.FrameStretch.Uniform;
            this.OriginalViewer.FullScreenEnabled = true;
            this.OriginalViewer.Location = new System.Drawing.Point(12, 120);
            this.OriginalViewer.Name = "OriginalViewer";
            this.OriginalViewer.RotateAngle = 0;
            this.OriginalViewer.Size = new System.Drawing.Size(325, 239);
            this.OriginalViewer.TabIndex = 23;
            this.OriginalViewer.Text = "videoViewerWF1";

            this.ProcessedViewer.BackColor = System.Drawing.Color.Black;
            this.ProcessedViewer.FlipMode = Ozeki.Media.FlipMode.None;
            this.ProcessedViewer.FrameStretch = Ozeki.Media.FrameStretch.Uniform;
            this.ProcessedViewer.FullScreenEnabled = true;
            this.ProcessedViewer.Location = new System.Drawing.Point(359, 119);
            this.ProcessedViewer.Name = "ProcessedViewer";
            this.ProcessedViewer.RotateAngle = 0;
            this.ProcessedViewer.Size = new System.Drawing.Size(320, 240);
            this.ProcessedViewer.TabIndex = 24;
            this.ProcessedViewer.Text = "videoViewerWF2";

            this.label2.AutoSize = true;
            this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
            this.label2.Location = new System.Drawing.Point(356, 363);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(103, 13);
            this.label2.TabIndex = 25;
            this.label2.Text = "Processed image";

            this.label1.AutoSize = true;
            this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
            this.label1.Location = new System.Drawing.Point(12, 363);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(87, 13);
            this.label1.TabIndex = 26;
            this.label1.Text = "Original image";

            this.label12.AutoSize = true;
            this.label12.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
            this.label12.Location = new System.Drawing.Point(12, 382);
            this.label12.Name = "label12";
            this.label12.Size = new System.Drawing.Size(91, 13);
            this.label12.TabIndex = 27;
            this.label12.Text = "Detection info:";
 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(685, 557);
            this.Controls.Add(this.label12);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.ProcessedViewer);
            this.Controls.Add(this.OriginalViewer);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.groupBox5);
            this.Controls.Add(this.groupBox2);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.MaximizeBox = false;
            this.Name = "MainForm";
            this.Text = "Optical Character Detection";
            this.Load += new System.EventHandler(this.MainForm_Load);
            this.groupBox2.ResumeLayout(false);
            this.groupBox2.PerformLayout();
            this.groupBox5.ResumeLayout(false);
            this.groupBox5.PerformLayout();
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.GroupBox groupBox2;
        private System.Windows.Forms.GroupBox groupBox5;
        private System.Windows.Forms.Button button_Connect;
        private System.Windows.Forms.Button button_Disconnect;
        private System.Windows.Forms.TextBox tb_cameraUrl;
        private System.Windows.Forms.Label label13;
        private System.Windows.Forms.Button button_Compose;
        private System.Windows.Forms.Label stateLabel;
        private System.Windows.Forms.Label label14;
        private System.Windows.Forms.RadioButton radioButtonBlack;
        private System.Windows.Forms.RadioButton radioButtonWhite;
        private System.Windows.Forms.GroupBox groupBox1;
        private System.Windows.Forms.TextBox textBoxDetectedText;
        private Ozeki.Media.VideoViewerWF OriginalViewer;
        private Ozeki.Media.VideoViewerWF ProcessedViewer;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Label label12;
    }
}


	

Code 2 - GUI example in C#

Conclusion

This guide provides you detailed information on how to implement optical character recognition in C# using the Ozeki Camera SDK. With the help of the examples and information provided on this webpage you will be able to edit and store your digitized texts or even create an application which can recognize a prohibited trademark before entering a concert.

Related pages

FAQ

  1. What kind of developer environment is needed?

    • Microsoft Visual Studio 2010
    • Microsoft .Net Framework 4.0
    • Internet connection
  2. How can I get the URL of the camera?

    You can get the URL from the producer of the camera.

  3. I have not managed to build the solution. How to solve it?

    • Please set the Target framework property of the project to .NET 4.0.
    • You should add the OzekiSDK.dll to the references of the solution.
    • Please import the missing classes.

More information