A configurable Optical Mark Recognition pipeline for grading fixed-layout multiple-choice answer sheets.
This project aligns scanned forms, locates answer bubbles from reusable templates, scores marks, classifies ambiguous responses, supports PDF input, and produces human-review artifacts for calibration and debugging.
- Marker-based sheet alignment
- Template-driven bubble localization
- Detection of
single,blank,multiple, anduncertainresponses - Contrast enhancement for faint or low-quality scans
- Configurable scoring and classification thresholds
- PDF rasterization and batch processing
- Optional grading against matching answer keys
- Debug overlays, masks, CSV scores, and review JSON
- CLI-first workflow with JSON/YAML configuration
Python · Computer Vision · Image Processing · PDF Processing · NumPy · CLI · JSON/YAML · pytest
Image or PDF
│
▼
Rasterization and preprocessing
│
▼
Corner-marker alignment
│
▼
Template-based bubble extraction
│
▼
Ink and darkness scoring
│
▼
Answer classification
│
├── single
├── blank
├── multiple
└── uncertain
│
▼
Analysis, grading, and debug artifacts
| Command | Purpose |
|---|---|
build-template |
Create a reusable template from a reference form |
analyze |
Process one image or PDF and produce analysis JSON |
batch |
Process a directory of answer sheets |
python3 -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'Python 3.10+ is supported.
python -m omr_reader build-template \
--reference samples/scans/202512061032_Page_01.png \
--out templates/answer_sheet_template.json \
--questions 8 \
--columns 3 \
--options 4 \
--column-question-counts 3,3,2Templates store the expected geometry and reading order, allowing the same form layout to be reused across many scans.
python -m omr_reader analyze \
--image samples/scans/202512061032_Page_01.png \
--template templates/answer_sheet_template.json \
--out outputs/result.json \
--debug-dir outputs/debugGenerated artifacts can include:
analysis.jsonaligned.pngink_mask.pngbubbles_overlay.pngbubbles_scores.csvquestions_review.json
python -m omr_reader batch \
--input-dir samples/scans \
--template templates/answer_sheet_template.json \
--output-dir outputs/batch_resultsEach input receives an isolated result directory, and the batch root contains a summary file.
The CLI accepts PDF files. The first page is rasterized with pdftoppm and then processed through the normal image pipeline.
Important controls include:
- marked and faint thresholds
- dark-pixel and strong-dark thresholds
- CLAHE contrast enhancement
- sharpening strength
- uncertain-score margin
- multiple-mark handling
- alignment confidence
- PDF rendering DPI
Configuration may be supplied through JSON or YAML.
classification:
faint_threshold: 0.10
marked_threshold: 0.13
uncertain_margin: 0.07
allow_multiple_marks: false
preprocess:
clahe_clip_limit: 3.5
sharpen_amount: 0.35
pdf_dpi: 200
alignment:
min_confidence: 0.75- input and alignment metadata
- thresholds and warnings
- per-question answer classification
- aggregate response counts
- human-review flags
When an answer key matches the template exactly, the pipeline reports per-question correctness and aggregate accuracy.
- Architecture
- CLI reference
- Template and ordering
- Grading
- Batch processing
- Debug outputs
- JSON outputs
- Testing
pytest -q
python -m omr_reader --helpFor practical validation, use scans with rotation, weak marks, erased answers, multiple marks, empty questions, and different image formats.
- Templates are tied to a specific form layout.
- Grading requires an answer key with the same question count and ordering as the template.
- Severe perspective distortion or missing alignment markers may require manual review.
- Real-world accuracy depends on scan quality and calibration thresholds.
Answer Sheet OMR demonstrates practical computer-vision engineering, configurable data pipelines, batch processing, debugging workflows, and explainable handling of uncertain predictions.