Click here to Skip to main content
13,596,190 members
Click here to Skip to main content
Add your own
alternative version


52 bookmarked
Posted 23 Jan 2018
Licenced CPOL

C# - Optical Marks Recognition (OMR) Engine 2.1a (Mar, 2016)

, 23 Jan 2018
Rate this:
Please Sign up or sign in to vote.
This is an API for creating, detecting and analyzing Optical Marks Sheets (Also known as bubble sheets). Its upgrade of version of C# OMR Engine 1.0 i wrote back in 2012. It can be found at ""Version V2.1 Also has

Download Source Here!


OMR (wiki) are answer sheets that are not intended to be read by a human being. This project eliminates the need to buy OMR reading machines and even a photo scanner for a computer. Any >3MP mobile phone camera with autofocus will do the job.

[Important Notice]

I receive emails on routine basis reporting/asking me about the possible issues and future of this project. It is a poignant situation when I don't find any time to reply to all these messages. I wrote it in 2016 and have since been involved in more important research. Kindly, don't mind if I take more than usual to answer your messages about this article.

Who should read?

  • Desktop, .Net and Asp.Net developers finding a solution to integrate OMR recognition in their own applications
  • Those finding a solution to implement in their academic institutes to automate Bubble Sheet Checking.
  • Student learning Image processing related to OMRs
  • Those who are new to AForge.Net and want to learn some basics.

The first kind of followers should keep an eye on these tags: OMR Engine, OMR Console, and OMR Reader

The second kind should look for an executable called, OMR Tools

The third and fourth kind of followers should pay more attention to OMR Reader and image Utils.


This article discusses another update in the 2nd version of OMR engine I originally wrote in 2012. It is highly recommended for the readers to experience the first version of engine first which is located at C# - Optical Marks Recognition (OMR) Engine 1.0

I might have given up a long ago on this project because the world has very less time left to waste on such old-age projects. We have moved to Kinect 2 in Xbox One which is an image processing marvel. But the support and update request I get from developers and students has given me enough push to write the latest release and this article as well.

I'm sorry for those followers of the article who were disappointed earlier because I eliminated the source code but I had my reasons. Its here now and I've tried to make it even more understandable through line-by-line comments.

Some of the people may ask, "Why reinvent the wheel?" because there are numerous OMR engines and even embedded systems available in the market. But this project is open source and written in high-level language. So, integration with other .Net application is not an issue. This is the main reason I've been devoting time since it started.

Whats new?

V2.1 Update (December 2015) "Let's make it open for C# and start making it cross-platform"

  • Added source code in the Codeproject Article
  • Added ToolTip Texts to Help you through the GUI interfaces
  • Removed Many Bugs Including registry related exceptions
  • Added a new tool for creating Answer sheets supporting Random answer keys.
  • Added a Command Line tool for those who don't want to be bothered by the .Net Environment or want to access the engine from other desktop applications
  • Added Comments for each line of OMR Engine Class, the most used class of the Solution
  • Added inbuilt support for answer scores calculation
  • And many small improvements to avoid exceptions and failures
  • Added a better Event Driven approach to keep an eye on whats going on during a process. Those will love this who cannot bear with a process that doesn't give visual progress update (Like Me)
  • Small Improvements, tweaks, and optimizations in the OMR sheet extraction code (Algorithm remains the same)

V2 is equipped with many tweaks, updates, additions, and removals. Unfortunately, it removes altogether, the backward compatibility of OMR sheets.

  1. Image detection and analysis is now more precise, much reliable and faster.
  2. Added a whole class to manage OMR sheet in more like Object-oriented approach.
  3. Image color correction method changed from hit-and-trial to absolute.
  4. Ability to process images in async threads.
  5. XML sheet storage changed to access 2007 database
  6. added OMR.helpers.dbOps class for managing all database operations in one place
  7. Improved image detection algorithm to consume less memory
  8. Parameter-based output quality and performance adjustment
  9. I nice GUI to create your own OMR sheets.

[FAQ] Terms used and basic concepts

This section contains answers to most asked questions. I recommend everyone to read this section before proceeding any step further.

Most of us know that OMR sheets look like this:

The black markings on this sheet are used for page alignment detection (mostly).

However, this engine DOES NOT use such sheets. Sheets used in this engine look like:

Source images taken from the camera may look as rough as:

The four square blocks on the corners are used to extract OMR sheet from a camera image.

Sheet definitions are saved in an Access Database for portability. Structure of this database is very simple and self-explanatory. However, you don't need to understand it unless you want to make some concept level changes in the engine.

Creating an OMR Sheet

You don't need to know how to create these sheets because there is a class in the solution named, "OMR.forms.asnwerSheetDesigner".

Alternatively, you could simply choose to run the OMR Tools executable to quickly access this window.

The form looks like this:

OMR Sheet Designer

This is the simplest and most comprehensive GUI to create OMR sheets of your own choice. For this understand these terms:

  • Number Block: Can be used to take registration or roll number of students as well as randomization code of answer sheet. This block can be placed anywhere on the invisible grid. The number of digits can be changed. Just hover over the lower border of a block. The visual style of these blocks can also be changed.
  • Answer Block: Can be used to take answers to Multiple-choice questions (MCQ) or True/False statements. Handling is similar to Registration block. The visual style of these blocks can also be changed.
  • Empty Block/Text Input Region: Some institutes use hand signatures/handwriting marks as record keeping practice and other reasons. This block can be used to identify an empty region on the sheet which requires such input.

One of the most practical features is the background image. You can use any PDF file to make the background of the sheet. This feature can be used typically to add customized text and graphics on the sheet which might and might not be a part of OMR results. Just see above in the sample image for an idea.

Once you are done with the editing, select a sheet name. And save the database. This will generate three files. One Database, one high-resolution rasterized image, and one PDF printable file. Unfortunately, I have forgotten to move the printables to output directory selected, they are copied in the project directory. Kindly don't take it hard.

Answer Key Maker

To automate the process of creating OMR Answer keys, OMR Answer key Maker has been developed. The GUI contains Tooltips for help and doesn't need explanation.

Answer Key Designer

OMR Console

For those who don't want any C# codes and want to use the engine from other applications, may choose to use OMR console. Type "Help" in the command line to read about the usage. The console can also accept command-line start-up parameters and won't need any manual inputs from users. OMR Console

Code Organisation

I've tried my best to simplify the things from previous versions. Download and extract the source code or the relevant release from above attachments and get to know the code.

After you have set everything up, you will find that there is one main namespace, which contains the engine. Here is what everything is for:

  • OMR >> Name Space which contains the engine
  • OMR.helpers >> contains some classes which act as helping classes like database reading, image utilities, and PDFconversion wrappers
  • OMR.OMRReader >> Core class of engine which actually performs the sheet detection and analysis algorithms.
  • OMR.OMREngine >> Unlike its name, this call is actually a wrapper for OMR.OMRReader. For easiest usage of the namespace, this is the most preferred class.
  • Everything else does something obviously but is irrelevant to you when you start working with OMR.OMREngine.

Setting up everything

There is no need to download any external libraries. The only thing missing is Ghost script DLL which will be downloaded automatically when it is needed. Just extract the source and compile it. Use the sample files provided to get you started,

Using the code

Unless you want to plumb deeper and play in lower layers of the engine, which I find interesting, you will be playing with only one class, "OMR.OMREngine".

Here is how you declare an engine and use it.

You need:

  1. *.jpg file containing the camera/scanner image.
  2. Address of database containing the OMR sheet definitions. You don't need to know the structure of DB. (I will discuss it later.)
  3. Name of OMR sheet from DB. (I will discuss it later.)
OMR.OMREngine engine = new OMREngine(filenamet.Text, "omrSheet1.accdb", "A4_sq_1");
           engine.onAsyncCompletion += new OMR.AsyncCompletionEventHandler(engine_onAsyncCompletion);
           engine.onAsyncProgressUpdated += new OMR.AsyncProgressEventHandler(engine_onAsyncProgressUpdated);

Simple enough? yeah. Event declaration is not compulsory. You can use the synchronous methods or get the status of async processes from engine.Progress and engine.ResultReady properties.

If the process exits with ResultReady set to true, it means that there was one sheet detected and analysed as well.

Results are organized in properties of "engine" member. I will discuss later the structure of sheet, but, according to the definitions sought from DB, results will be compiled.

Following might be what you are looking for:

  • engine.NumberBlocks[index]
    • >RecognisedImage
    • >BinaryMaskedOMs
    • >BlockID
    • >NumberOfLines
    • >Options
    • >StartOfInd
  • engine.AnswerBlock[index]
    • >RecognisedImage
    • >BinaryMaskedOMs
    • >BlockID
    • >Digits
  • engine.EmptyBlock[index]
    • >RecognisedImage
    • >BlockID

All these blocks also contain ToString overload which converts the result and score into human readable string.

There are many other useful properties and functions in this class. All have text descriptions written within. Just use Visual Studio to read those details.

The concept of this engine is to give you an API. This is the most fundamental and organized information which needs analysis and image processing. Everything else is on developers concerns. Like:

  • Transforming BinaryMaskedOMs into obtained marks of an answer sheet.
  • Getting registration number of students/randomization code of answer sheet from RegistrationBlocks
  • Organizing results into MS Excel or word format or even emailing them to authorities automatically.

History and Future of Project

This release is termed alpha Just because I haven't put every code branch in the test, neither have I put all the quality control checks we usually do. However, I've tested it for very basic usage and it worked like a charm. I'm the only member of my company, can't do so many things voluntarily without getting paid. In coming releases, following things will be done, so keep connected:

  • 100 percent code coverage
  • Removal of all redundant/auxiliary codes
  • Image processing Done in MATLAB for more robust image recognition
  • Removal of debugging helper code
  • Optimisation of performance for multithreading
  • Ability to acquire and convert directly from Webcam Image/scanner Image


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Engineer techCREATIONS
Pakistan Pakistan
Developer, Programmer, Beta Tester; technically, i'm none of these. I'm a mechanical engineer, programming is my passion, my hobby and my amateur non profit profession. I program when ii need and innovate whenever, wherever i want.


C#+Applied Mathematicss-Robotics+C++

C# OMR Reader
Monopoly (Urdu language)
HybridAutomation Framework
SMS Bomber (Windows Mobile 6 Professional)
Hard disk watch tower
Farmville Super Clicker
Games Profile selector
Windows mobile salat reminder
Windows mobile SMS Pole Host
and alot of other small apps

You may also be interested in...


Comments and Discussions

QuestionErrors and Warnings Pin
Member 1381676310-Jun-18 23:06
memberMember 1381676310-Jun-18 23:06 
BugMy opinion Pin
Member 1378479927-Apr-18 17:34
memberMember 1378479927-Apr-18 17:34 
GeneralMy vote of 5 Pin
Sohail Zaheer9-Apr-18 2:44
memberSohail Zaheer9-Apr-18 2:44 
GeneralRe: My vote of 5 Pin
umar.techBOY11-Apr-18 1:54
memberumar.techBOY11-Apr-18 1:54 
QuestionHow Can I read Sheets with IOS and Android to OMR Pin
halile5-Apr-18 9:16
memberhalile5-Apr-18 9:16 
QuestionVertical reading Pin
Ali Alshihry18-Mar-18 11:27
memberAli Alshihry18-Mar-18 11:27 
AnswerRe: Vertical reading Pin
Ali Alshihry22-Mar-18 6:29
memberAli Alshihry22-Mar-18 6:29 
Questionerror code: 02080315 Pin
Ali Alshihry14-Mar-18 10:31
memberAli Alshihry14-Mar-18 10:31 
AnswerRe: error code: 02080315 Pin
umar.techBOY14-Mar-18 22:46
memberumar.techBOY14-Mar-18 22:46 
BugIs it possible to process multiple image using multi threading? Pin
Narayan N28-Feb-18 4:06
memberNarayan N28-Feb-18 4:06 
GeneralRe: Is it possible to process multiple image using multi threading? Pin
umar.techBOY4-Mar-18 21:21
memberumar.techBOY4-Mar-18 21:21 
QuestionPlease explain - why 14, 16.5 and 15.24 Pin
Member 873149119-Dec-17 22:18
memberMember 873149119-Dec-17 22:18 
AnswerRe: Please explain - why 14, 16.5 and 15.24 Pin
umar.techBOY23-Jan-18 21:20
memberumar.techBOY23-Jan-18 21:20 
QuestionCan't save database using Sheet Designer Pin
Member 1293425729-Sep-17 10:46
memberMember 1293425729-Sep-17 10:46 
AnswerRe: Can't save database using Sheet Designer Pin
umar.techBOY23-Jan-18 21:23
memberumar.techBOY23-Jan-18 21:23 
QuestionAbout using your code in my application Pin
Member 1224142323-Jun-17 7:57
memberMember 1224142323-Jun-17 7:57 
AnswerRe: About using your code in my application Pin
umar.techBOY23-Jan-18 21:24
memberumar.techBOY23-Jan-18 21:24 
QuestionError : 02080315 and Access Database Pin
violinist_tr9-Jun-17 23:29
memberviolinist_tr9-Jun-17 23:29 
AnswerRe: Error : 02080315 and Access Database Pin
umar.techBOY23-Jan-18 21:29
memberumar.techBOY23-Jan-18 21:29 
Questionumar did not display the sample picture I.0 Engine Pin
Member 1286987429-Nov-16 23:22
memberMember 1286987429-Nov-16 23:22 
QuestionDB file is missing Pin
Member 1285081916-Nov-16 20:08
memberMember 1285081916-Nov-16 20:08 
QuestionException is occurred when i am executing program and clicking on any button. Pin
siya_patel7-Sep-16 19:42
membersiya_patel7-Sep-16 19:42 
AnswerRe: Exception is occurred when i am executing program and clicking on any button. Pin
umar.techBOY14-Oct-16 2:34
memberumar.techBOY14-Oct-16 2:34 
Questiona different type of sheet Pin
azeezlko15-Jun-16 2:31
memberazeezlko15-Jun-16 2:31 
AnswerRe: a different type of sheet Pin
umar.techBOY13-Jul-16 23:11
memberumar.techBOY13-Jul-16 23:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web04-2016 | 2.8.180621.3 | Last Updated 24 Jan 2018
Article Copyright 2018 by umar.techBOY
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid