Java OMR Library

Do you need a simple yet feature-rich Java OMR library? Do you want to recognize optical marks in scanned images? Try Aspose.OMR for Java - A Java class library to perform the Optical Mark Recognition (OMR) operations in Java-based applications. Let’s have a quick walk through the features of the said Java API to see how to recognize optical marks in a variety of image formats and capture human-marked data from surveys, questionnaires or tests containing MCQs.

Dynamically Create OMR Template using Java OMR Library

Aspose.OMR for Java provides a complete set of features from creating the OMR template to recognizing the optical marks to capture the data. The API supports generating the OMR template file or the image from simple text markups. You can simply pass the template’s text markup to the API and it will generate the template for you. The following is a sample text markup for an OMR template.

?text=Name__________________________________ Date____________

?grid=ID
sections_count=8
#What is Aspose.OMR main function?
() OCR () Capture human-marked data
() There is no main function () Enhance images
#Can Aspose.OMR process photos as well?
() Yes, indeed! () No
#Aspose.OMR is available on any platform, because it is:
() Cross-platform code () Cloud service
#Aspose.OMR works with any kind of OMR forms: tests, exams, questionnaires, surveys, etc.
() Yes, indeed! () No
#Excellent recognition results can be achieved only for filled bubbles at least for:
() 40% () 60% () 75% () 98%
#Do you have to mark up every question on the page?
(Yes) Yes, that will help a lot! (No) No
#Rate your preference from 0 to 9 with "0" being preference towards performance
and "9" being preference towards flexibility.
(0) (1) (2) (3) (4) (5) (6) (7) (8) (9)
#I found aspose omr to be a useful tool. (5 - strongly agree, 1 - strongly disagree)
(5) (4) (3) (2) (1)

?text= Answer sheet section
?answer_sheet=MainQuestions
elements_count=10
columns_count=5

?text=Sign________________________________

You can simply save the text markup in a text file with .txt extension. Once done, you can generate the template using the following steps:

The following code sample shows how to generate the OMR template from text markup using Java.

String outputDirectory = "GenerationResult";
String[] GenerationMarkups = new String[] { "Sheet.txt", "Grid.txt", "AsposeTest.txt" };
String[] GenerationMarkupsNoExt = new String[] { "Sheet", "Grid", "AsposeTest" };
OmrEngine engine = new OmrEngine();
for (int i = 0; i < GenerationMarkups.length; i++)
{
// call template generation providing path to the txt file with markup
GenerationResult res = engine.generateTemplate(GenerationMarkups[i]);
// check in case of errors
if (res.getErrorCode() != 0)
{
System.out.println("ERROR CODE: " + res.getErrorCode());
}
// save generation result: image and .omr template
res.save(outputDirectory, GenerationMarkupsNoExt[i]);
}

Output

Java OMR Library

Optical Mark Recognition (OMR) in Images using Java

In order to perform OMR in images, you just need two things - the prepared OMR template (.omr) and the images (user-filled forms/sheets) to perform OMR on. The API supports the OMR for the following image formats:

The following are the steps to perform OMR in images:

The following code sample shows how to recognize optical marks in images using Java.

String[] UserImages = new String[] { "Sheet1.jpg", "Sheet2.jpg" };
String[] UserImagesNoExt = new String[] { "Sheet1", "Sheet2" };
String outputDirectory = "Result";
String templatePath = "Sheet.omr";
// initialize engine and get template processor providing path to the .omr file
OmrEngine engine = new OmrEngine();
TemplateProcessor templateProcessor = engine.getTemplateProcessor(templatePath);
System.out.println("Template loaded.");
// images loop
for (int i = 0; i < UserImages.length; i++) {
// path to the image to be recognized
String imagePath = UserImages[i];
System.out.println("Processing image: " + imagePath);
// recognize image and receive result
RecognitionResult result = templateProcessor.recognizeImage(imagePath);
// export results as csv string
String csvResult = result.getCsv();
String json = result.getJson();
// save csv to the output folder
PrintWriter wr = new PrintWriter(new FileOutputStream(UserImagesNoExt[i] + ".csv"), true);
wr.println(csvResult);
}

Using a Custom Recognition Threshold for OMR

You can also fine-tune the OMR results by defining a custom threshold between 0 to 100. Increasing the threshold makes the API more strict in recognizing the answers. The threshold values can be set in TemplateProcessor.recognizeImage() method as the second parameter as shown in the following Java code sample.

String[] UserImages = new String[] { "Sheet1.jpg", "Sheet2.jpg" };
String[] UserImagesNoExt = new String[] { "Sheet1", "Sheet2" };
String outputDirectory = "Result";
String templatePath = "Sheet.omr";
int customThreshold = 40;
// initialize engine and get template processor providing path to the .omr file
OmrEngine engine = new OmrEngine();
TemplateProcessor templateProcessor = engine.getTemplateProcessor(templatePath);
System.out.println("Template loaded.");
// images loop
for (int i = 0; i < UserImages.length; i++) {
// path to the image to be recognized
String imagePath = UserImages[i];
System.out.println("Processing image: " + imagePath);
// recognize image and receive result
RecognitionResult result = templateProcessor.recognizeImage(imagePath, customThreshold);
// export results as csv string
String csvResult = result.getCsv();
String json = result.getJson();
// save csv to the output folder
PrintWriter wr = new PrintWriter(new FileOutputStream(UserImagesNoExt[i] + ".csv"), true);
wr.println(csvResult);
}

Recalculating the OMR Results

In some cases, you may want to recalculate the OMR results with different threshold values. Instead of calling TemplateProcessor.recognizeImage() again and again in such cases, you can configure the API for automatic recalculation using TemplateProcessor.recalculate() method to improve image processing efficiency. The following code sample shows how to implement the recalculation of the OMR results.

String[] UserImages = new String[] { "Sheet1.jpg", "Sheet2.jpg" };
String[] UserImagesNoExt = new String[] { "Sheet1", "Sheet2" };
String outputDirectory = "Result";
String templatePath = "Sheet.omr";
// init engine and get template processor
OmrEngine engine = new OmrEngine();
TemplateProcessor templateProcessor = engine.getTemplateProcessor(templatePath);
System.out.println("Template loaded.");
// Set custom threshold to use in recalculation
// this value is in range (0 to 100)
// represents the percentage of required black pixels on bubble image to be recognized
// i.e. the lower the value - the less black pixels required for bubble to be counted as filled and vice versa
int CustomThreshold = 40;
// images loop
for (int i = 0; i < UserImages.length; i++)
{
String image = UserImages[i];
String imagePath = image;
System.out.println("Processing image: " + imagePath);
// recognize image
RecognitionResult result = templateProcessor.recognizeImage(imagePath);
// get export csv string
String stringRes = result.getCsv();
// save csv to output folder
String outputName = UserImagesNoExt[i] + ".csv";
PrintWriter wr = new PrintWriter(new FileOutputStream(outputName), true);
wr.println(stringRes);
System.out.println("Export done. Path: " + outputName);
// recalculate recognition results with custom threshold
templateProcessor.recalculate(result, CustomThreshold);
// get export csv string
stringRes = result.getCsv();
// save recalculated results
outputName = UserImagesNoExt[i] + "_recalculated.csv";
wr = new PrintWriter(new FileOutputStream(outputName), true);
wr.println(stringRes);
System.out.println("Recalculated result export done. Path: " + outputName);
System.out.println();
}

In case you would have any questions or queries related to our Java OMR library, contact us via our forum for any questions or queries.

See also