Tutorial: Implementing Form Recognition with SDK

Learning Objectives

In this tutorial, you’ll learn how to:

  • Set up and configure the Aspose.OMR Cloud SDK in your application
  • Authenticate and establish connections to the cloud service
  • Submit forms for recognition using native code instead of REST calls
  • Process and utilize recognition results efficiently
  • Implement robust error handling and retry logic

Prerequisites

Before starting this tutorial, make sure you have:

  1. Completed the previous tutorials in this series
  2. A development environment for your preferred programming language (.NET, Java, Python, etc.)
  3. Your Aspose Cloud API credentials (Client ID and Client Secret)
  4. Basic understanding of your programming language and package managers
  5. A sample filled OMR form and its corresponding recognition pattern

Understanding SDK Benefits

While you can directly use the Aspose.OMR Cloud REST API, the SDKs offer significant advantages:

  • Simplified Integration: Native methods instead of complex HTTP requests
  • Type Safety: Language-specific object models instead of raw JSON
  • Efficiency: Automatic handling of authentication, connections, and serialization
  • Reliability: Built-in error handling and best practices
  • Updates: Regular maintenance to support new features and improvements

Step 1: Setting Up the SDK

Let’s start by installing the Aspose.OMR Cloud SDK for your preferred programming language:

For .NET (using NuGet)

# Using .NET CLI
dotnet add package Aspose.OMR-Cloud

# Using Package Manager Console
Install-Package Aspose.OMR-Cloud

Project Setup

Create a new project and add the required imports:

using Aspose.Omr.Cloud.Sdk.Api;
using Aspose.Omr.Cloud.Sdk.Model;
using System.IO;
using System.Collections.Generic;

Step 2: Configuring Authentication

The first step in any SDK implementation is to configure authentication with your Aspose Cloud credentials:

// Initialize the API with your credentials
RecognizeTemplateApi api = new RecognizeTemplateApi();
api.Configuration.ClientID = "YOUR_CLIENT_ID";
api.Configuration.ClientSecret = "YOUR_CLIENT_SECRET";

The SDK handles the token acquisition, renewal, and proper authorization headers automatically, saving you from writing this code yourself.

Step 3: Loading Form Resources

Next, let’s load the filled form image and its recognition pattern:

// Load the completed form
byte[] formImage = File.ReadAllBytes("completed_form.jpg");

// Load recognition pattern (previously generated .omr file)
byte[] pattern = File.ReadAllBytes("form_template.omr");

Step 4: Creating and Submitting the Recognition Task

Now, let’s create a recognition task and submit it to the Aspose.OMR Cloud service:

// Create recognition task with threshold and output format
OmrRecognizeTask task = new OmrRecognizeTask(
    new List<byte[]> { formImage },  // Form images
    pattern,                         // Recognition pattern
    35,                              // Recognition threshold
    S3DataType.Csv                   // Result format
);

// Submit the form for recognition
string taskId = api.PostRecognizeTemplate(task);

Console.WriteLine($"Form submitted successfully. Task ID: {taskId}");

In this example:

  • We’re processing a single form image
  • Setting the recognition threshold to 35%
  • Requesting CSV output format
  • The API returns a task ID for tracking

Step 5: Retrieving and Processing Results

After submitting the form, we need to fetch the results:

// Fetch recognition results
OMRRecognitionResponse result = api.GetRecognizeTemplate(taskId);

// Check for successful processing
if (result.ResponseStatusCode == "Ok" && result.Results.Count > 0)
{
    // Save result to file
    File.WriteAllBytes("recognition_results.csv", result.Results[0].Data);
    Console.WriteLine("Results saved to recognition_results.csv");
    
    // For demonstration, display the CSV content
    string csvContent = System.Text.Encoding.UTF8.GetString(result.Results[0].Data);
    Console.WriteLine("\nCSV Content Preview:");
    Console.WriteLine(csvContent.Substring(0, Math.Min(csvContent.Length, 500)));
}
else
{
    // Handle errors
    if (result.Error != null && result.Error.Messages.Count > 0)
    {
        Console.WriteLine($"Recognition failed: {string.Join(", ", result.Error.Messages)}");
    }
    else
    {
        Console.WriteLine("Recognition failed with unknown error");
    }
}

The SDK handles the base64 decoding of results automatically, returning the raw data that you can save or process directly.

Step 6: Complete Working Example

Let’s put it all together into a complete working example:

using Aspose.Omr.Cloud.Sdk.Api;
using Aspose.Omr.Cloud.Sdk.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;

namespace AsposePomrRecognitionDemo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            try
            {
                // 1. Configure the API client
                RecognizeTemplateApi api = new RecognizeTemplateApi();
                api.Configuration.ClientID = "YOUR_CLIENT_ID";
                api.Configuration.ClientSecret = "YOUR_CLIENT_SECRET";

                Console.WriteLine("Authentication configured");

                // 2. Load resources
                byte[] formImage = File.ReadAllBytes("completed_form.jpg");
                byte[] pattern = File.ReadAllBytes("form_template.omr");

                Console.WriteLine("Resources loaded");

                // 3. Submit form for recognition with 35% accuracy threshold
                OmrRecognizeTask task = new OmrRecognizeTask(
                    new List<byte[]> { formImage }, 
                    pattern, 
                    35, 
                    S3DataType.Csv
                );

                string taskId = api.PostRecognizeTemplate(task);
                Console.WriteLine($"Form submitted successfully. Task ID: {taskId}");

                // 4. Wait a moment for processing (in production, implement proper polling)
                Console.WriteLine("Waiting for processing to complete...");
                Thread.Sleep(3000); // Wait 3 seconds

                // 5. Fetch and process results
                OMRRecognitionResponse result = api.GetRecognizeTemplate(taskId);

                if (result.ResponseStatusCode == "Ok" && result.Results.Count > 0)
                {
                    // Save result to file
                    File.WriteAllBytes("recognition_results.csv", result.Results[0].Data);
                    Console.WriteLine("Results saved to recognition_results.csv");
                    
                    // Display CSV content
                    string csvContent = System.Text.Encoding.UTF8.GetString(result.Results[0].Data);
                    Console.WriteLine("\nCSV Content Preview:");
                    Console.WriteLine(csvContent.Substring(0, Math.Min(csvContent.Length, 500)));
                    
                    // Process the CSV data (example: count filled answers)
                    string[] lines = csvContent.Split('\n');
                    int filledAnswers = 0;
                    
                    for (int i = 1; i < lines.Length; i++) // Skip header row
                    {
                        string line = lines[i];
                        if (!string.IsNullOrEmpty(line) && line.Contains("\"selected\""))
                        {
                            filledAnswers++;
                        }
                    }
                    
                    Console.WriteLine($"\nTotal marked answers: {filledAnswers}");
                }
                else if (result.ResponseStatusCode == "Processing")
                {
                    Console.WriteLine("Form is still being processed. Try again later.");
                }
                else
                {
                    // Handle errors
                    if (result.Error != null && result.Error.Messages.Count > 0)
                    {
                        Console.WriteLine($"Recognition failed: {string.Join(", ", result.Error.Messages)}");
                    }
                    else
                    {
                        Console.WriteLine("Recognition failed with unknown error");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Exception: {ex.Message}");
                if (ex.InnerException != null)
                {
                    Console.WriteLine($"Inner exception: {ex.InnerException.Message}");
                }
            }

            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }
}

Step 7: Implementing Production-Ready Features

For real-world applications, you’ll want to add these production-ready features:

Retry Logic

private static OMRRecognitionResponse FetchResultsWithRetry(
    RecognizeTemplateApi api, 
    string taskId, 
    int maxRetries = 10, 
    int retryIntervalMs = 2000)
{
    int attempts = 0;
    while (attempts < maxRetries)
    {
        attempts++;
        Console.WriteLine($"Attempt {attempts} to fetch results...");
        
        OMRRecognitionResponse result = api.GetRecognizeTemplate(taskId);
        
        if (result.ResponseStatusCode == "Ok" && result.Results.Count > 0)
        {
            return result;
        }
        else if (result.ResponseStatusCode == "Processing")
        {
            Console.WriteLine($"Processing in progress. Waiting {retryIntervalMs/1000} seconds...");
            Thread.Sleep(retryIntervalMs);
            continue;
        }
        else
        {
            // Return error result immediately
            return result;
        }
    }
    
    throw new TimeoutException($"Recognition timed out after {maxRetries} attempts");
}

Batch Processing

private static void ProcessBatchOfForms(RecognizeTemplateApi api, string directoryPath, string patternPath)
{
    // Load pattern once
    byte[] pattern = File.ReadAllBytes(patternPath);
    
    // Process all JPEG and PNG files in directory
    foreach (string filePath in Directory.GetFiles(directoryPath, "*.*")
        .Where(f => f.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) || 
                   f.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase) || 
                   f.EndsWith(".png", StringComparison.OrdinalIgnoreCase)))
    {
        Console.WriteLine($"Processing {Path.GetFileName(filePath)}...");
        
        try
        {
            byte[] formImage = File.ReadAllBytes(filePath);
            
            OmrRecognizeTask task = new OmrRecognizeTask(
                new List<byte[]> { formImage }, 
                pattern, 
                35, 
                S3DataType.Csv
            );
            
            string taskId = api.PostRecognizeTemplate(task);
            
            // Save results with filename based on original image
            string resultPath = Path.Combine(
                Path.GetDirectoryName(filePath), 
                Path.GetFileNameWithoutExtension(filePath) + "_results.csv"
            );
            
            // Fetch with retry logic
            OMRRecognitionResponse result = FetchResultsWithRetry(api, taskId);
            
            if (result.ResponseStatusCode == "Ok" && result.Results.Count > 0)
            {
                File.WriteAllBytes(resultPath, result.Results[0].Data);
                Console.WriteLine($"Results saved to {resultPath}");
            }
            else
            {
                Console.WriteLine($"Failed to process {filePath}");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error processing {filePath}: {ex.Message}");
        }
    }
}

Working with Other Programming Languages

Java Example

import com.aspose.omr.cloud.sdk.api.RecognizeTemplateApi;
import com.aspose.omr.cloud.sdk.model.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;

public class OmrRecognitionExample {
    public static void main(String[] args) {
        try {
            // Initialize API with credentials
            RecognizeTemplateApi api = new RecognizeTemplateApi();
            api.getConfig().setClientId("YOUR_CLIENT_ID");
            api.getConfig().setClientSecret("YOUR_CLIENT_SECRET");
            
            // Load resources
            byte[] formImage = Files.readAllBytes(new File("completed_form.jpg").toPath());
            byte[] pattern = Files.readAllBytes(new File("form_template.omr").toPath());
            
            // Create recognition task
            OmrRecognizeTask task = new OmrRecognizeTask();
            task.setImages(Arrays.asList(formImage));
            task.setOmrFile(pattern);
            task.setRecognitionThreshold(35);
            task.setOutputFormat(S3DataType.CSV);
            
            // Submit for recognition
            String taskId = api.postRecognizeTemplate(task);
            System.out.println("Task ID: " + taskId);
            
            // Wait for processing
            Thread.sleep(3000);
            
            // Fetch results
            OMRRecognitionResponse result = api.getRecognizeTemplate(taskId);
            
            // Process results
            if ("Ok".equals(result.getResponseStatusCode()) && !result.getResults().isEmpty()) {
                Files.write(new File("recognition_results.csv").toPath(), 
                           result.getResults().get(0).getData());
                System.out.println("Results saved to recognition_results.csv");
            } else {
                System.out.println("Recognition failed");
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Python Example

import os
import time
import asposeocrcloud
from asposeocrcloud.apis.recognize_template_api import RecognizeTemplateApi
from asposeocrcloud.models.omr_recognize_task import OmrRecognizeTask
from asposeocrcloud.models.s3_data_type import S3DataType

# Configure API client
configuration = asposeocrcloud.Configuration(
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET"
)

# Initialize API
api = RecognizeTemplateApi(configuration)

# Load resources
with open("completed_form.jpg", "rb") as image_file:
    form_image = image_file.read()

with open("form_template.omr", "rb") as pattern_file:
    pattern = pattern_file.read()

# Create and submit recognition task
task = OmrRecognizeTask(
    images=[form_image],
    omr_file=pattern,
    recognition_threshold=35,
    output_format=S3DataType.CSV
)

task_id = api.post_recognize_template(task)
print(f"Task ID: {task_id}")

# Wait for processing
time.sleep(3)

# Fetch results
response = api.get_recognize_template(task_id)

# Process results
if response.response_status_code == "Ok" and response.results:
    with open("recognition_results.csv", "wb") as result_file:
        result_file.write(response.results[0].data)
    print("Results saved to recognition_results.csv")
else:
    print("Recognition failed")

What You’ve Learned

In this tutorial, you’ve learned how to:

  • Set up and configure the Aspose.OMR Cloud SDK for your preferred language
  • Submit forms for recognition using native code and SDK methods
  • Retrieve and process recognition results
  • Implement production-ready features like retry logic and batch processing
  • Build a complete working application for OMR form recognition

Next Steps

Now that you’ve completed this tutorial series, consider exploring these advanced topics:

  • Creating multi-service applications that combine form generation and recognition
  • Implementing a complete workflow from form design to data analysis
  • Integrating OMR recognition with database storage and reporting systems
  • Building web interfaces for form upload and result visualization

Further Practice

To reinforce your learning:

  1. Implement a complete form processing pipeline using the SDK
  2. Add result visualization and reporting features
  3. Create a web service that exposes form recognition capabilities to other applications
  4. Experiment with different output formats and post-processing strategies

Helpful Resources

Have questions about this tutorial? Visit our support forum for assistance.