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.
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.
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.
- Image detection and analysis is now more precise, much reliable and faster.
- Added a whole class to manage OMR sheet in more like Object-oriented approach.
- Image color correction method changed from hit-and-trial to absolute.
- Ability to process images in async threads.
- XML sheet storage changed to access 2007 database
- added OMR.helpers.dbOps class for managing all database operations in one place
- Improved image detection algorithm to consume less memory
- Parameter-based output quality and performance adjustment
- 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:
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.
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.
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.
- *.jpg file containing the camera/scanner image.
- Address of database containing the OMR sheet definitions. You don't need to know the structure of DB. (I will discuss it later.)
- 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:
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