Spaces:
Paused
Paused
Deploy OCR/OMR backend to HF Spaces
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .dockerignore +6 -0
- .env.example +10 -0
- .gitattributes +44 -35
- .gitignore +188 -0
- Dockerfile +30 -0
- Images/GK_Question_Paper_A4.pdf +0 -0
- Images/OCR2.jpg +0 -0
- Images/OCRSheet.jpg +3 -0
- Images/OCRTest.pdf +0 -0
- Images/OMRSheet.jpg +3 -0
- Images/OMRSheet2.jpg +3 -0
- Images/OMRSheet3.jpg +3 -0
- Images/OMRTest.jpg +3 -0
- Images/OcrSheetMarked.jpg +3 -0
- Images/omr_answer_key.pdf +3 -0
- Images/omr_answer_key.png +3 -0
- Images/question.png +0 -0
- Images/question_paper.pdf +0 -0
- Images/question_paper.png +3 -0
- Images/test.jpg +3 -0
- OMRChecker/.pre-commit-config.yaml +59 -0
- OMRChecker/.pylintrc +43 -0
- OMRChecker/CODE_OF_CONDUCT.md +133 -0
- OMRChecker/CONTRIBUTING.md +32 -0
- OMRChecker/Contributors.md +22 -0
- OMRChecker/LICENSE +22 -0
- OMRChecker/README.md +359 -0
- OMRChecker/docs/assets/colored_output.jpg +0 -0
- OMRChecker/inputs/OMRImage.jpg +3 -0
- OMRChecker/inputs/template.json +37 -0
- OMRChecker/main.py +99 -0
- OMRChecker/outputs/AdrianSample/Manual/ErrorFiles.csv +1 -0
- OMRChecker/outputs/AdrianSample/Manual/MultiMarkedFiles.csv +1 -0
- OMRChecker/outputs/AdrianSample/Results/Results_07PM.csv +1 -0
- OMRChecker/outputs/CheckedOMRs/OMRImage.jpg +3 -0
- OMRChecker/outputs/CheckedOMRs/OMRSheet.jpg +3 -0
- OMRChecker/outputs/CheckedOMRs/OcrSheetMarked.jpg +3 -0
- OMRChecker/outputs/Images/CheckedOMRs/OMRSheet.jpg +3 -0
- OMRChecker/outputs/Images/Manual/ErrorFiles.csv +1 -0
- OMRChecker/outputs/Images/Manual/MultiMarkedFiles.csv +1 -0
- OMRChecker/outputs/Images/Results/Results_10PM.csv +2 -0
- OMRChecker/outputs/Manual/ErrorFiles.csv +3 -0
- OMRChecker/outputs/Manual/MultiMarkedFiles.csv +1 -0
- OMRChecker/outputs/MobileCamera/Manual/ErrorFiles.csv +1 -0
- OMRChecker/outputs/MobileCamera/Manual/MultiMarkedFiles.csv +1 -0
- OMRChecker/outputs/MobileCamera/Results/Results_09PM.csv +1 -0
- OMRChecker/pyproject.toml +18 -0
- OMRChecker/pytest.ini +6 -0
- OMRChecker/requirements.dev.txt +7 -0
- OMRChecker/requirements.txt +8 -0
.dockerignore
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.git
|
| 2 |
+
.env
|
| 3 |
+
.claude
|
| 4 |
+
__pycache__
|
| 5 |
+
*.pyc
|
| 6 |
+
outputs/
|
.env.example
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Required
|
| 2 |
+
GEMINI_API_KEY=your_gemini_api_key
|
| 3 |
+
SUPABASE_URL=your_supabase_project_url
|
| 4 |
+
SUPABASE_ANON_KEY=your_supabase_anon_key
|
| 5 |
+
|
| 6 |
+
# Optional (auto-detected on Linux, only needed for custom installs)
|
| 7 |
+
# TESSERACT_CMD=/usr/bin/tesseract
|
| 8 |
+
# POPPLER_PATH=/usr/bin
|
| 9 |
+
# PORT=7860
|
| 10 |
+
# FLASK_DEBUG=false
|
.gitattributes
CHANGED
|
@@ -1,35 +1,44 @@
|
|
| 1 |
-
|
| 2 |
-
*
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Auto detect text files and perform LF normalization
|
| 2 |
+
* text=auto
|
| 3 |
+
Images/OCRSheet.jpg filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
Images/OcrSheetMarked.jpg filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
Images/omr_answer_key.pdf filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
Images/omr_answer_key.png filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
Images/OMRSheet.jpg filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
Images/OMRSheet2.jpg filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
Images/OMRSheet3.jpg filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
Images/OMRTest.jpg filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
Images/question_paper.png filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
Images/test.jpg filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
OMRChecker/inputs/OMRImage.jpg filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
OMRChecker/outputs/CheckedOMRs/OcrSheetMarked.jpg filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
OMRChecker/outputs/CheckedOMRs/OMRImage.jpg filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
OMRChecker/outputs/CheckedOMRs/OMRSheet.jpg filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
OMRChecker/outputs/Images/CheckedOMRs/OMRSheet.jpg filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
OMRChecker/samples/answer-key/weighted-answers/images/adrian_omr.png filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
OMRChecker/samples/community/Sandeep-1507/omr-1.png filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
OMRChecker/samples/community/Sandeep-1507/omr-2.png filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
OMRChecker/samples/community/Sandeep-1507/omr-3.png filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
OMRChecker/samples/community/Shamanth/omr_sheet_01.png filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
OMRChecker/samples/community/UmarFarootAPS/scans/scan-type-1.jpg filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
OMRChecker/samples/community/UmarFarootAPS/scans/scan-type-2.jpg filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
OMRChecker/samples/community/UPSC-mock/answer_key.jpg filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
OMRChecker/samples/community/UPSC-mock/scan-angles/angle-1.jpg filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
OMRChecker/samples/community/UPSC-mock/scan-angles/angle-2.jpg filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
OMRChecker/samples/community/UPSC-mock/scan-angles/angle-3.jpg filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
OMRChecker/samples/sample1/MobileCamera/sheet1.jpg filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
OMRChecker/samples/sample2/AdrianSample/adrian_omr.png filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
OMRChecker/samples/sample3/colored-thick-sheet/rgb-100-gsm.jpg filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
OMRChecker/samples/sample3/xeroxed-thin-sheet/grayscale-80-gsm.jpg filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
OMRChecker/samples/sample4/IMG_20201116_143512.jpg filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
OMRChecker/samples/sample4/IMG_20201116_150717658.jpg filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
OMRChecker/samples/sample4/IMG_20201116_150750830.jpg filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
OMRChecker/samples/sample5/ScanBatch1/camscanner-1.jpg filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
OMRChecker/samples/sample5/ScanBatch2/camscanner-2.jpg filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
OMRChecker/samples/sample6/doc-scans/sample_roll_01.jpg filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
OMRChecker/samples/sample6/doc-scans/sample_roll_02.jpg filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
OMRChecker/samples/sample6/doc-scans/sample_roll_03.jpg filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
OMRChecker/samples/sample6/reference.png filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
OMRChecker/src/tests/test_samples/sample2/sample.jpg filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
output/test_ocr_res_img.jpg filter=lfs diff=lfs merge=lfs -text
|
| 44 |
+
output/test_preprocessed_img.jpg filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Byte-compiled / optimized / DLL files
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[cod]
|
| 4 |
+
*$py.class
|
| 5 |
+
|
| 6 |
+
# C extensions
|
| 7 |
+
*.so
|
| 8 |
+
|
| 9 |
+
# Distribution / packaging
|
| 10 |
+
.Python
|
| 11 |
+
build/
|
| 12 |
+
develop-eggs/
|
| 13 |
+
dist/
|
| 14 |
+
downloads/
|
| 15 |
+
eggs/
|
| 16 |
+
.eggs/
|
| 17 |
+
lib/
|
| 18 |
+
lib64/
|
| 19 |
+
parts/
|
| 20 |
+
sdist/
|
| 21 |
+
var/
|
| 22 |
+
wheels/
|
| 23 |
+
share/python-wheels/
|
| 24 |
+
*.egg-info/
|
| 25 |
+
.installed.cfg
|
| 26 |
+
*.egg
|
| 27 |
+
MANIFEST
|
| 28 |
+
|
| 29 |
+
# PyInstaller
|
| 30 |
+
# Usually these files are written by a python script from a template
|
| 31 |
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
| 32 |
+
*.manifest
|
| 33 |
+
*.spec
|
| 34 |
+
|
| 35 |
+
# Installer logs
|
| 36 |
+
pip-log.txt
|
| 37 |
+
pip-delete-this-directory.txt
|
| 38 |
+
|
| 39 |
+
# Unit test / coverage reports
|
| 40 |
+
htmlcov/
|
| 41 |
+
.tox/
|
| 42 |
+
.nox/
|
| 43 |
+
.coverage
|
| 44 |
+
.coverage.*
|
| 45 |
+
.cache
|
| 46 |
+
nosetests.xml
|
| 47 |
+
coverage.xml
|
| 48 |
+
*.cover
|
| 49 |
+
*.py,cover
|
| 50 |
+
.hypothesis/
|
| 51 |
+
.pytest_cache/
|
| 52 |
+
cover/
|
| 53 |
+
|
| 54 |
+
# Translations
|
| 55 |
+
*.mo
|
| 56 |
+
*.pot
|
| 57 |
+
|
| 58 |
+
# Django stuff:
|
| 59 |
+
*.log
|
| 60 |
+
local_settings.py
|
| 61 |
+
db.sqlite3
|
| 62 |
+
db.sqlite3-journal
|
| 63 |
+
|
| 64 |
+
# Flask stuff:
|
| 65 |
+
instance/
|
| 66 |
+
.webassets-cache
|
| 67 |
+
|
| 68 |
+
# Scrapy stuff:
|
| 69 |
+
.scrapy
|
| 70 |
+
|
| 71 |
+
# Sphinx documentation
|
| 72 |
+
docs/_build/
|
| 73 |
+
|
| 74 |
+
# PyBuilder
|
| 75 |
+
.pybuilder/
|
| 76 |
+
target/
|
| 77 |
+
|
| 78 |
+
# Jupyter Notebook
|
| 79 |
+
.ipynb_checkpoints
|
| 80 |
+
|
| 81 |
+
# IPython
|
| 82 |
+
profile_default/
|
| 83 |
+
ipython_config.py
|
| 84 |
+
|
| 85 |
+
# pyenv
|
| 86 |
+
# For a library or package, you might want to ignore these files since the code is
|
| 87 |
+
# intended to run in multiple environments; otherwise, check them in:
|
| 88 |
+
# .python-version
|
| 89 |
+
|
| 90 |
+
# pipenv
|
| 91 |
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
| 92 |
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
| 93 |
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
| 94 |
+
# install all needed dependencies.
|
| 95 |
+
#Pipfile.lock
|
| 96 |
+
|
| 97 |
+
# UV
|
| 98 |
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
| 99 |
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
| 100 |
+
# commonly ignored for libraries.
|
| 101 |
+
#uv.lock
|
| 102 |
+
|
| 103 |
+
# poetry
|
| 104 |
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
| 105 |
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
| 106 |
+
# commonly ignored for libraries.
|
| 107 |
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
| 108 |
+
#poetry.lock
|
| 109 |
+
|
| 110 |
+
# pdm
|
| 111 |
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
| 112 |
+
#pdm.lock
|
| 113 |
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
| 114 |
+
# in version control.
|
| 115 |
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
| 116 |
+
.pdm.toml
|
| 117 |
+
.pdm-python
|
| 118 |
+
.pdm-build/
|
| 119 |
+
|
| 120 |
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
| 121 |
+
__pypackages__/
|
| 122 |
+
|
| 123 |
+
# Celery stuff
|
| 124 |
+
celerybeat-schedule
|
| 125 |
+
celerybeat.pid
|
| 126 |
+
|
| 127 |
+
# SageMath parsed files
|
| 128 |
+
*.sage.py
|
| 129 |
+
|
| 130 |
+
# Environments
|
| 131 |
+
.env
|
| 132 |
+
.venv
|
| 133 |
+
env/
|
| 134 |
+
venv/
|
| 135 |
+
ENV/
|
| 136 |
+
env.bak/
|
| 137 |
+
venv.bak/
|
| 138 |
+
|
| 139 |
+
# Spyder project settings
|
| 140 |
+
.spyderproject
|
| 141 |
+
.spyproject
|
| 142 |
+
|
| 143 |
+
# Rope project settings
|
| 144 |
+
.ropeproject
|
| 145 |
+
|
| 146 |
+
# mkdocs documentation
|
| 147 |
+
/site
|
| 148 |
+
|
| 149 |
+
# mypy
|
| 150 |
+
.mypy_cache/
|
| 151 |
+
.dmypy.json
|
| 152 |
+
dmypy.json
|
| 153 |
+
|
| 154 |
+
# Pyre type checker
|
| 155 |
+
.pyre/
|
| 156 |
+
|
| 157 |
+
# pytype static type analyzer
|
| 158 |
+
.pytype/
|
| 159 |
+
|
| 160 |
+
# Cython debug symbols
|
| 161 |
+
cython_debug/
|
| 162 |
+
|
| 163 |
+
# PyCharm
|
| 164 |
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
| 165 |
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
| 166 |
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
| 167 |
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
| 168 |
+
#.idea/
|
| 169 |
+
|
| 170 |
+
# App outputs
|
| 171 |
+
outputs/
|
| 172 |
+
.claude/
|
| 173 |
+
|
| 174 |
+
# Temp/debug images
|
| 175 |
+
Images/debug_*.png
|
| 176 |
+
|
| 177 |
+
# Ruff stuff:
|
| 178 |
+
.ruff_cache/
|
| 179 |
+
|
| 180 |
+
# PyPI configuration file
|
| 181 |
+
.pypirc
|
| 182 |
+
|
| 183 |
+
# Cursor
|
| 184 |
+
# Cursor is an AI-powered code editor.`.cursorignore` specifies files/directories to
|
| 185 |
+
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
| 186 |
+
# refer to https://docs.cursor.com/context/ignore-files
|
| 187 |
+
.cursorignore
|
| 188 |
+
.cursorindexingignore
|
Dockerfile
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.11-slim
|
| 2 |
+
|
| 3 |
+
# System deps: tesseract, poppler, opencv libs
|
| 4 |
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 5 |
+
tesseract-ocr \
|
| 6 |
+
poppler-utils \
|
| 7 |
+
libgl1 \
|
| 8 |
+
libglib2.0-0 \
|
| 9 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 10 |
+
|
| 11 |
+
WORKDIR /app
|
| 12 |
+
|
| 13 |
+
# Install CPU-only PyTorch first (avoids ~4GB of NVIDIA CUDA libs)
|
| 14 |
+
RUN pip install --no-cache-dir torch torchvision --index-url https://download.pytorch.org/whl/cpu
|
| 15 |
+
|
| 16 |
+
# Install remaining Python deps
|
| 17 |
+
COPY requirements.txt .
|
| 18 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 19 |
+
|
| 20 |
+
# Copy application code
|
| 21 |
+
COPY . .
|
| 22 |
+
|
| 23 |
+
# Create required directories
|
| 24 |
+
RUN mkdir -p OMRChecker/inputs outputs/Results outputs/CheckedOMRs outputs/Manual outputs/Evaluation Images
|
| 25 |
+
|
| 26 |
+
# HF Spaces expects port 7860
|
| 27 |
+
ENV PORT=7860
|
| 28 |
+
EXPOSE 7860
|
| 29 |
+
|
| 30 |
+
CMD ["python", "app.py"]
|
Images/GK_Question_Paper_A4.pdf
ADDED
|
Binary file (2.26 kB). View file
|
|
|
Images/OCR2.jpg
ADDED
|
Images/OCRSheet.jpg
ADDED
|
Git LFS Details
|
Images/OCRTest.pdf
ADDED
|
Binary file (85.5 kB). View file
|
|
|
Images/OMRSheet.jpg
ADDED
|
Git LFS Details
|
Images/OMRSheet2.jpg
ADDED
|
Git LFS Details
|
Images/OMRSheet3.jpg
ADDED
|
Git LFS Details
|
Images/OMRTest.jpg
ADDED
|
Git LFS Details
|
Images/OcrSheetMarked.jpg
ADDED
|
Git LFS Details
|
Images/omr_answer_key.pdf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:879c8f7aa369a6f0cbc65f9a5279a18ae42a35d541ba53e70b140178e83acf3f
|
| 3 |
+
size 105714
|
Images/omr_answer_key.png
ADDED
|
Git LFS Details
|
Images/question.png
ADDED
|
Images/question_paper.pdf
ADDED
|
Binary file (85.5 kB). View file
|
|
|
Images/question_paper.png
ADDED
|
Git LFS Details
|
Images/test.jpg
ADDED
|
Git LFS Details
|
OMRChecker/.pre-commit-config.yaml
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
exclude: "__snapshots__/.*$"
|
| 2 |
+
default_install_hook_types: [pre-commit, pre-push]
|
| 3 |
+
repos:
|
| 4 |
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
| 5 |
+
rev: v4.4.0
|
| 6 |
+
hooks:
|
| 7 |
+
- id: check-yaml
|
| 8 |
+
stages: [commit]
|
| 9 |
+
- id: check-added-large-files
|
| 10 |
+
args: ['--maxkb=300']
|
| 11 |
+
fail_fast: false
|
| 12 |
+
stages: [commit]
|
| 13 |
+
- id: pretty-format-json
|
| 14 |
+
args: ['--autofix', '--no-sort-keys']
|
| 15 |
+
- id: end-of-file-fixer
|
| 16 |
+
exclude_types: ["csv", "json"]
|
| 17 |
+
stages: [commit]
|
| 18 |
+
- id: trailing-whitespace
|
| 19 |
+
stages: [commit]
|
| 20 |
+
- repo: https://github.com/pycqa/isort
|
| 21 |
+
rev: 5.12.0
|
| 22 |
+
hooks:
|
| 23 |
+
- id: isort
|
| 24 |
+
args: ["--profile", "black"]
|
| 25 |
+
stages: [commit]
|
| 26 |
+
- repo: https://github.com/psf/black
|
| 27 |
+
rev: 23.3.0
|
| 28 |
+
hooks:
|
| 29 |
+
- id: black
|
| 30 |
+
fail_fast: true
|
| 31 |
+
stages: [commit]
|
| 32 |
+
- repo: https://github.com/pycqa/flake8
|
| 33 |
+
rev: 6.0.0
|
| 34 |
+
hooks:
|
| 35 |
+
- id: flake8
|
| 36 |
+
args:
|
| 37 |
+
- "--ignore=E501,W503,E203,E741,F541" # Line too long, Line break occurred before a binary operator, Whitespace before ':'
|
| 38 |
+
fail_fast: true
|
| 39 |
+
stages: [commit]
|
| 40 |
+
- repo: local
|
| 41 |
+
hooks:
|
| 42 |
+
- id: pytest-on-commit
|
| 43 |
+
name: Running single sample test
|
| 44 |
+
entry: python3 -m pytest -rfpsxEX --disable-warnings --verbose -k sample1
|
| 45 |
+
language: system
|
| 46 |
+
pass_filenames: false
|
| 47 |
+
always_run: true
|
| 48 |
+
fail_fast: true
|
| 49 |
+
stages: [commit]
|
| 50 |
+
- repo: local
|
| 51 |
+
hooks:
|
| 52 |
+
- id: pytest-on-push
|
| 53 |
+
name: Running all tests before push...
|
| 54 |
+
entry: python3 -m pytest -rfpsxEX --disable-warnings --verbose --durations=3
|
| 55 |
+
language: system
|
| 56 |
+
pass_filenames: false
|
| 57 |
+
always_run: true
|
| 58 |
+
fail_fast: true
|
| 59 |
+
stages: [push]
|
OMRChecker/.pylintrc
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[BASIC]
|
| 2 |
+
# Regular expression matching correct variable names. Overrides variable-naming-style.
|
| 3 |
+
# snake_case with single letter regex -
|
| 4 |
+
variable-rgx=[a-z0-9_]{1,30}$
|
| 5 |
+
|
| 6 |
+
# Good variable names which should always be accepted, separated by a comma.
|
| 7 |
+
good-names=x,y,pt
|
| 8 |
+
|
| 9 |
+
[MESSAGES CONTROL]
|
| 10 |
+
|
| 11 |
+
# Disable the message, report, category or checker with the given id(s). You
|
| 12 |
+
# can either give multiple identifiers separated by comma (,) or put this
|
| 13 |
+
# option multiple times (only on the command line, not in the configuration
|
| 14 |
+
# file where it should appear only once). You can also use "--disable=all" to
|
| 15 |
+
# disable everything first and then reenable specific checks. For example, if
|
| 16 |
+
# you want to run only the similarities checker, you can use "--disable=all
|
| 17 |
+
# --enable=similarities". If you want to run only the classes checker, but have
|
| 18 |
+
# no Warning level messages displayed, use "--disable=all --enable=classes
|
| 19 |
+
# --disable=W".
|
| 20 |
+
disable=import-error,
|
| 21 |
+
unresolved-import,
|
| 22 |
+
too-few-public-methods,
|
| 23 |
+
missing-docstring,
|
| 24 |
+
relative-beyond-top-level,
|
| 25 |
+
too-many-instance-attributes,
|
| 26 |
+
bad-continuation,
|
| 27 |
+
no-member
|
| 28 |
+
|
| 29 |
+
# Note: bad-continuation is a false positive showing bug in pylint
|
| 30 |
+
# https://github.com/psf/black/issues/48
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
[REPORTS]
|
| 34 |
+
# Set the output format. Available formats are text, parseable, colorized, json
|
| 35 |
+
# and msvs (visual studio). You can also give a reporter class, e.g.
|
| 36 |
+
# mypackage.mymodule.MyReporterClass.
|
| 37 |
+
output-format=text
|
| 38 |
+
|
| 39 |
+
# Tells whether to display a full report or only the messages.
|
| 40 |
+
reports=no
|
| 41 |
+
|
| 42 |
+
# Activate the evaluation score.
|
| 43 |
+
score=yes
|
OMRChecker/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!-- https://www.contributor-covenant.org/version/2/1/code_of_conduct/code_of_conduct.md -->
|
| 2 |
+
# Contributor Covenant Code of Conduct
|
| 3 |
+
|
| 4 |
+
## Our Pledge
|
| 5 |
+
|
| 6 |
+
We as members, contributors, and leaders pledge to make participation in our
|
| 7 |
+
community a harassment-free experience for everyone, regardless of age, body
|
| 8 |
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
| 9 |
+
identity and expression, level of experience, education, socio-economic status,
|
| 10 |
+
nationality, personal appearance, race, caste, color, religion, or sexual
|
| 11 |
+
identity and orientation.
|
| 12 |
+
|
| 13 |
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
| 14 |
+
diverse, inclusive, and healthy community.
|
| 15 |
+
|
| 16 |
+
## Our Standards
|
| 17 |
+
|
| 18 |
+
Examples of behavior that contributes to a positive environment for our
|
| 19 |
+
community include:
|
| 20 |
+
|
| 21 |
+
* Demonstrating empathy and kindness toward other people
|
| 22 |
+
* Being respectful of differing opinions, viewpoints, and experiences
|
| 23 |
+
* Giving and gracefully accepting constructive feedback
|
| 24 |
+
* Accepting responsibility and apologizing to those affected by our mistakes,
|
| 25 |
+
and learning from the experience
|
| 26 |
+
* Focusing on what is best not just for us as individuals, but for the overall
|
| 27 |
+
community
|
| 28 |
+
|
| 29 |
+
Examples of unacceptable behavior include:
|
| 30 |
+
|
| 31 |
+
* The use of sexualized language or imagery, and sexual attention or advances of
|
| 32 |
+
any kind
|
| 33 |
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
| 34 |
+
* Public or private harassment
|
| 35 |
+
* Publishing others' private information, such as a physical or email address,
|
| 36 |
+
without their explicit permission
|
| 37 |
+
* Other conduct which could reasonably be considered inappropriate in a
|
| 38 |
+
professional setting
|
| 39 |
+
|
| 40 |
+
## Enforcement Responsibilities
|
| 41 |
+
|
| 42 |
+
Community leaders are responsible for clarifying and enforcing our standards of
|
| 43 |
+
acceptable behavior and will take appropriate and fair corrective action in
|
| 44 |
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
| 45 |
+
or harmful.
|
| 46 |
+
|
| 47 |
+
Community leaders have the right and responsibility to remove, edit, or reject
|
| 48 |
+
comments, commits, code, wiki edits, issues, and other contributions that are
|
| 49 |
+
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
| 50 |
+
decisions when appropriate.
|
| 51 |
+
|
| 52 |
+
## Scope
|
| 53 |
+
|
| 54 |
+
This Code of Conduct applies within all community spaces, and also applies when
|
| 55 |
+
an individual is officially representing the community in public spaces.
|
| 56 |
+
Examples of representing our community include using an official email address,
|
| 57 |
+
posting via an official social media account, or acting as an appointed
|
| 58 |
+
representative at an online or offline event.
|
| 59 |
+
|
| 60 |
+
## Enforcement
|
| 61 |
+
|
| 62 |
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
| 63 |
+
reported to the community leaders responsible for enforcement at
|
| 64 |
+
[INSERT CONTACT METHOD].
|
| 65 |
+
All complaints will be reviewed and investigated promptly and fairly.
|
| 66 |
+
|
| 67 |
+
All community leaders are obligated to respect the privacy and security of the
|
| 68 |
+
reporter of any incident.
|
| 69 |
+
|
| 70 |
+
## Enforcement Guidelines
|
| 71 |
+
|
| 72 |
+
Community leaders will follow these Community Impact Guidelines in determining
|
| 73 |
+
the consequences for any action they deem in violation of this Code of Conduct:
|
| 74 |
+
|
| 75 |
+
### 1. Correction
|
| 76 |
+
|
| 77 |
+
**Community Impact**: Use of inappropriate language or other behavior deemed
|
| 78 |
+
unprofessional or unwelcome in the community.
|
| 79 |
+
|
| 80 |
+
**Consequence**: A private, written warning from community leaders, providing
|
| 81 |
+
clarity around the nature of the violation and an explanation of why the
|
| 82 |
+
behavior was inappropriate. A public apology may be requested.
|
| 83 |
+
|
| 84 |
+
### 2. Warning
|
| 85 |
+
|
| 86 |
+
**Community Impact**: A violation through a single incident or series of
|
| 87 |
+
actions.
|
| 88 |
+
|
| 89 |
+
**Consequence**: A warning with consequences for continued behavior. No
|
| 90 |
+
interaction with the people involved, including unsolicited interaction with
|
| 91 |
+
those enforcing the Code of Conduct, for a specified period of time. This
|
| 92 |
+
includes avoiding interactions in community spaces as well as external channels
|
| 93 |
+
like social media. Violating these terms may lead to a temporary or permanent
|
| 94 |
+
ban.
|
| 95 |
+
|
| 96 |
+
### 3. Temporary Ban
|
| 97 |
+
|
| 98 |
+
**Community Impact**: A serious violation of community standards, including
|
| 99 |
+
sustained inappropriate behavior.
|
| 100 |
+
|
| 101 |
+
**Consequence**: A temporary ban from any sort of interaction or public
|
| 102 |
+
communication with the community for a specified period of time. No public or
|
| 103 |
+
private interaction with the people involved, including unsolicited interaction
|
| 104 |
+
with those enforcing the Code of Conduct, is allowed during this period.
|
| 105 |
+
Violating these terms may lead to a permanent ban.
|
| 106 |
+
|
| 107 |
+
### 4. Permanent Ban
|
| 108 |
+
|
| 109 |
+
**Community Impact**: Demonstrating a pattern of violation of community
|
| 110 |
+
standards, including sustained inappropriate behavior, harassment of an
|
| 111 |
+
individual, or aggression toward or disparagement of classes of individuals.
|
| 112 |
+
|
| 113 |
+
**Consequence**: A permanent ban from any sort of public interaction within the
|
| 114 |
+
community.
|
| 115 |
+
|
| 116 |
+
## Attribution
|
| 117 |
+
|
| 118 |
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
| 119 |
+
version 2.1, available at
|
| 120 |
+
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
| 121 |
+
|
| 122 |
+
Community Impact Guidelines were inspired by
|
| 123 |
+
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
| 124 |
+
|
| 125 |
+
For answers to common questions about this code of conduct, see the FAQ at
|
| 126 |
+
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
| 127 |
+
[https://www.contributor-covenant.org/translations][translations].
|
| 128 |
+
|
| 129 |
+
[homepage]: https://www.contributor-covenant.org
|
| 130 |
+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
| 131 |
+
[Mozilla CoC]: https://github.com/mozilla/diversity
|
| 132 |
+
[FAQ]: https://www.contributor-covenant.org/faq
|
| 133 |
+
[translations]: https://www.contributor-covenant.org/translations
|
OMRChecker/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# How to contribute
|
| 2 |
+
So you want to write code and get it landed in the official OMRChecker repository?
|
| 3 |
+
First, fork our repository into your own GitHub account, and create a local clone of it as described in the installation instructions.
|
| 4 |
+
The latter will be used to get new features implemented or bugs fixed.
|
| 5 |
+
|
| 6 |
+
Once done and you have the code locally on the disk, you can get started. We advise you to not work directly on the master branch,
|
| 7 |
+
but to create a separate branch for each issue you are working on. That way you can easily switch between different work,
|
| 8 |
+
and you can update each one for the latest changes on the upstream master individually.
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
# Writing Code
|
| 12 |
+
For writing the code just follow the [Pep8 Python style](https://peps.python.org/pep-0008/) guide, If there is something unclear about the style, just look at existing code which might help you to understand it better.
|
| 13 |
+
|
| 14 |
+
Also, try to use commits with [conventional messages](https://www.conventionalcommits.org/en/v1.0.0/#summary).
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
# Code Formatting
|
| 18 |
+
Before committing your code, make sure to run the following command to format your code according to the PEP8 style guide:
|
| 19 |
+
```.sh
|
| 20 |
+
pip install -r requirements.dev.txt && pre-commit install
|
| 21 |
+
```
|
| 22 |
+
|
| 23 |
+
Run `pre-commit` before committing your changes:
|
| 24 |
+
```.sh
|
| 25 |
+
git add .
|
| 26 |
+
pre-commit run -a
|
| 27 |
+
```
|
| 28 |
+
|
| 29 |
+
# Where to contribute from
|
| 30 |
+
|
| 31 |
+
- You can pickup any open [issues](https://github.com/Udayraj123/OMRChecker/issues) to solve.
|
| 32 |
+
- You can also check out the [ideas list](https://github.com/users/Udayraj123/projects/2/views/1)
|
OMRChecker/Contributors.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Contributors
|
| 2 |
+
|
| 3 |
+
- [Udayraj123](https://github.com/Udayraj123)
|
| 4 |
+
- [leongwaikay](https://github.com/leongwaikay)
|
| 5 |
+
- [deepakgouda](https://github.com/deepakgouda)
|
| 6 |
+
- [apurva91](https://github.com/apurva91)
|
| 7 |
+
- [sparsh2706](https://github.com/sparsh2706)
|
| 8 |
+
- [namit2saxena](https://github.com/namit2saxena)
|
| 9 |
+
- [Harsh-Kapoorr](https://github.com/Harsh-Kapoorr)
|
| 10 |
+
- [Sandeep-1507](https://github.com/Sandeep-1507)
|
| 11 |
+
- [SpyzzVVarun](https://github.com/SpyzzVVarun)
|
| 12 |
+
- [asc249](https://github.com/asc249)
|
| 13 |
+
- [05Alston](https://github.com/05Alston)
|
| 14 |
+
- [Antibodyy](https://github.com/Antibodyy)
|
| 15 |
+
- [infinity1729](https://github.com/infinity1729)
|
| 16 |
+
- [Rohan-G](https://github.com/Rohan-G)
|
| 17 |
+
- [UjjwalMahar](https://github.com/UjjwalMahar)
|
| 18 |
+
- [Kurtsley](https://github.com/Kurtsley)
|
| 19 |
+
- [gaursagar21](https://github.com/gaursagar21)
|
| 20 |
+
- [aayushibansal2001](https://github.com/aayushibansal2001)
|
| 21 |
+
- [ShamanthVallem](https://github.com/ShamanthVallem)
|
| 22 |
+
- [rudrapsc](https://github.com/rudrapsc)
|
OMRChecker/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2024-present Udayraj Deshmukh and other contributors
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining
|
| 6 |
+
a copy of this software and associated documentation files (the
|
| 7 |
+
"Software"), to deal in the Software without restriction, including
|
| 8 |
+
without limitation the rights to use, copy, modify, merge, publish,
|
| 9 |
+
distribute, sublicense, and/or sell copies of the Software, and to
|
| 10 |
+
permit persons to whom the Software is furnished to do so, subject to
|
| 11 |
+
the following conditions:
|
| 12 |
+
|
| 13 |
+
The above copyright notice and this permission notice shall be
|
| 14 |
+
included in all copies or substantial portions of the Software.
|
| 15 |
+
|
| 16 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
| 17 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
| 18 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
| 19 |
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
| 20 |
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
| 21 |
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
| 22 |
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
OMRChecker/README.md
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# OMR Checker
|
| 2 |
+
|
| 3 |
+
Read OMR sheets fast and accurately using a scanner 🖨 or your phone 🤳.
|
| 4 |
+
|
| 5 |
+
## What is OMR?
|
| 6 |
+
|
| 7 |
+
OMR stands for Optical Mark Recognition, used to detect and interpret human-marked data on documents. OMR refers to the process of reading and evaluating OMR sheets, commonly used in exams, surveys, and other forms.
|
| 8 |
+
|
| 9 |
+
#### **Quick Links**
|
| 10 |
+
|
| 11 |
+
- [Installation](#getting-started)
|
| 12 |
+
- [User Guide](https://github.com/Udayraj123/OMRChecker/wiki)
|
| 13 |
+
- [Contributor Guide](https://github.com/Udayraj123/OMRChecker/blob/master/CONTRIBUTING.md)
|
| 14 |
+
- [Project Ideas List](https://github.com/users/Udayraj123/projects/2/views/1)
|
| 15 |
+
|
| 16 |
+
<hr />
|
| 17 |
+
|
| 18 |
+
[](https://github.com/Udayraj123/OMRChecker/pull/new/master) <!-- [](https://github.com/Udayraj123/OMRChecker/wiki/TODOs) -->
|
| 19 |
+
[](https://github.com/Udayraj123/OMRChecker/pulls?q=is%3Aclosed)
|
| 20 |
+
[](https://GitHub.com/Udayraj123/OMRChecker/issues?q=is%3Aissue+is%3Aclosed)
|
| 21 |
+
[](https://github.com/Udayraj123/OMRChecker/issues/5)
|
| 22 |
+
|
| 23 |
+
<!-- [](https://GitHub.com/Udayraj123/OMRChecker/graphs/contributors/) -->
|
| 24 |
+
|
| 25 |
+
[](https://GitHub.com/Udayraj123/OMRChecker/stargazers/)
|
| 26 |
+
[](https://discord.gg/qFv2Vqf)
|
| 27 |
+
|
| 28 |
+
<!-- [](https://colab.research.google.com/gist/Udayraj123/a125b1531c61cceed5f06994329cba66/omrchecker-on-cloud.ipynb) -->
|
| 29 |
+
|
| 30 |
+
## 🎯 Features
|
| 31 |
+
|
| 32 |
+
A full-fledged OMR checking software that can read and evaluate OMR sheets scanned at any angle and having any color.
|
| 33 |
+
|
| 34 |
+
| Specs <img width=200/> |   <img width=200/> |
|
| 35 |
+
| :--------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| 36 |
+
| 💯 **Accurate** | Currently nearly 100% accurate on good quality document scans; and about 90% accurate on mobile images. |
|
| 37 |
+
| 💪🏿 **Robust** | Supports low resolution, xeroxed sheets. See [**Robustness**](https://github.com/Udayraj123/OMRChecker/wiki/Robustness) for more. |
|
| 38 |
+
| ⏩ **Fast** | Current processing speed without any optimization is 200 OMRs/minute. |
|
| 39 |
+
| ✅ **Customizable** | [Easily apply](https://github.com/Udayraj123/OMRChecker/wiki/User-Guide) to custom OMR layouts, surveys, etc. |
|
| 40 |
+
| 📊 **Visually Rich** | [Get insights](https://github.com/Udayraj123/OMRChecker/wiki/Rich-Visuals) to configure and debug easily. |
|
| 41 |
+
| 🎈 **Lightweight** | Very minimal core code size. |
|
| 42 |
+
| 🏫 **Large Scale** | Tested on a large scale at [Technothlon](https://en.wikipedia.org/wiki/Technothlon). |
|
| 43 |
+
| 👩🏿💻 **Dev Friendly** | [Pylinted](http://pylint.pycqa.org/) and [Black formatted](https://github.com/psf/black) code. Also has a [developer community](https://discord.gg/qFv2Vqf) on discord. |
|
| 44 |
+
|
| 45 |
+
Note: For solving interesting challenges, developers can check out [**TODOs**](https://github.com/Udayraj123/OMRChecker/wiki/TODOs).
|
| 46 |
+
|
| 47 |
+
See the complete guide and details at [Project Wiki](https://github.com/Udayraj123/OMRChecker/wiki/).
|
| 48 |
+
|
| 49 |
+
<!-- 💁🏿♂️ **User Friendly** - WIP, Help by contributing! -->
|
| 50 |
+
|
| 51 |
+
## 💡 What can OMRChecker do for me?
|
| 52 |
+
|
| 53 |
+
Once you configure the OMR layout, just throw images of the sheets at the software; and you'll get back the marked responses in an excel sheet!
|
| 54 |
+
|
| 55 |
+
Images can be taken from various angles as shown below-
|
| 56 |
+
|
| 57 |
+
<p align="center">
|
| 58 |
+
<img alt="sample_input" width="400" src="https://raw.githubusercontent.com/wiki/Udayraj123/OMRChecker/extras/Progress/2019-04-26/images/sample_input.PNG">
|
| 59 |
+
</p>
|
| 60 |
+
|
| 61 |
+
### Code in action on images taken by scanner:
|
| 62 |
+
|
| 63 |
+
<p align="center">
|
| 64 |
+
<img alt="document_scanner" height="300" src="https://raw.githubusercontent.com/wiki/Udayraj123/OMRChecker/extras/mini_scripts/outputs/gif/document_scanner.gif">
|
| 65 |
+
|
| 66 |
+
</p>
|
| 67 |
+
|
| 68 |
+
### Code in action on images taken by a mobile phone:
|
| 69 |
+
|
| 70 |
+
<p align="center">
|
| 71 |
+
<img alt="checking_xeroxed_mobile" height="300" src="https://raw.githubusercontent.com/wiki/Udayraj123/OMRChecker/extras/mini_scripts/outputs/gif/checking_xeroxed_mobile.gif">
|
| 72 |
+
</p>
|
| 73 |
+
|
| 74 |
+
## Visuals
|
| 75 |
+
|
| 76 |
+
### Processing steps
|
| 77 |
+
|
| 78 |
+
See step-by-step processing of any OMR sheet:
|
| 79 |
+
|
| 80 |
+
<p align="center">
|
| 81 |
+
<a href="https://github.com/Udayraj123/OMRChecker/wiki/Rich-Visuals">
|
| 82 |
+
<img alt="rotation_stack" width="650" src="https://raw.githubusercontent.com/wiki/Udayraj123/OMRChecker/extras/Progress/2019-04-26/images/rotation.PNG">
|
| 83 |
+
</a>
|
| 84 |
+
<br>
|
| 85 |
+
*Note: This image is generated by the code itself!*
|
| 86 |
+
</p>
|
| 87 |
+
|
| 88 |
+
### Output
|
| 89 |
+
|
| 90 |
+
Get a CSV sheet containing the detected responses and evaluated scores:
|
| 91 |
+
|
| 92 |
+
<p align="center">
|
| 93 |
+
<a href="https://github.com/Udayraj123/OMRChecker/wiki/Rich-Visuals">
|
| 94 |
+
<img alt="csv_output" width="550" src="https://raw.githubusercontent.com/wiki/Udayraj123/OMRChecker/extras/Progress/2019-04-26/images/csv_output.PNG">
|
| 95 |
+
</a>
|
| 96 |
+
</p>
|
| 97 |
+
|
| 98 |
+
We now support [colored outputs](https://github.com/Udayraj123/OMRChecker/wiki/%5Bv2%5D-About-Evaluation) as well. Here's a sample output on another image -
|
| 99 |
+
<p align="center">
|
| 100 |
+
<a href="https://github.com/Udayraj123/OMRChecker/wiki/%5Bv2%5D-About-Evaluation">
|
| 101 |
+
<img alt="colored_output" width="550" src="./docs/assets/colored_output.jpg">
|
| 102 |
+
</a>
|
| 103 |
+
</p>
|
| 104 |
+
|
| 105 |
+
#### There are many more visuals in the wiki. Check them out [here!](https://github.com/Udayraj123/OMRChecker/wiki/Rich-Visuals)
|
| 106 |
+
|
| 107 |
+
## Getting started
|
| 108 |
+
|
| 109 |
+

|
| 110 |
+
|
| 111 |
+
**Operating system:** OSX or Linux is recommended although Windows is also supported.
|
| 112 |
+
|
| 113 |
+
### 1. Install global dependencies
|
| 114 |
+
|
| 115 |
+
 
|
| 116 |
+
|
| 117 |
+
To check if python3 and pip is already installed:
|
| 118 |
+
|
| 119 |
+
```bash
|
| 120 |
+
python3 --version
|
| 121 |
+
python3 -m pip --version
|
| 122 |
+
```
|
| 123 |
+
|
| 124 |
+
<details>
|
| 125 |
+
<summary><b>Install Python3</b></summary>
|
| 126 |
+
|
| 127 |
+
To install python3 follow instructions [here](https://www.python.org/downloads/)
|
| 128 |
+
|
| 129 |
+
To install pip - follow instructions [here](https://pip.pypa.io/en/stable/installation/)
|
| 130 |
+
|
| 131 |
+
</details>
|
| 132 |
+
<details>
|
| 133 |
+
<summary><b>Install OpenCV</b></summary>
|
| 134 |
+
|
| 135 |
+
**Any installation method is fine.**
|
| 136 |
+
|
| 137 |
+
Recommended:
|
| 138 |
+
|
| 139 |
+
```bash
|
| 140 |
+
python3 -m pip install --user --upgrade pip
|
| 141 |
+
python3 -m pip install --user opencv-python
|
| 142 |
+
python3 -m pip install --user opencv-contrib-python
|
| 143 |
+
```
|
| 144 |
+
|
| 145 |
+
More details on pip install openCV [here](https://www.pyimagesearch.com/2018/09/19/pip-install-opencv/).
|
| 146 |
+
|
| 147 |
+
</details>
|
| 148 |
+
|
| 149 |
+
<details>
|
| 150 |
+
|
| 151 |
+
<summary><b>Extra steps(for Linux users only)</b></summary>
|
| 152 |
+
|
| 153 |
+
<b>Installing missing libraries(if any):</b>
|
| 154 |
+
|
| 155 |
+
On a fresh computer, some of the libraries may get missing in event after a successful pip install. Install them using following commands[(ref)](https://www.pyimagesearch.com/2018/05/28/ubuntu-18-04-how-to-install-opencv/):
|
| 156 |
+
|
| 157 |
+
```bash
|
| 158 |
+
sudo apt-get install -y build-essential cmake unzip pkg-config
|
| 159 |
+
sudo apt-get install -y libjpeg-dev libpng-dev libtiff-dev
|
| 160 |
+
sudo apt-get install -y libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
|
| 161 |
+
sudo apt-get install -y libatlas-base-dev gfortran
|
| 162 |
+
```
|
| 163 |
+
|
| 164 |
+
</details>
|
| 165 |
+
|
| 166 |
+
### 2. Install project dependencies
|
| 167 |
+
|
| 168 |
+
Clone the repo
|
| 169 |
+
|
| 170 |
+
```bash
|
| 171 |
+
git clone https://github.com/Udayraj123/OMRChecker
|
| 172 |
+
cd OMRChecker/
|
| 173 |
+
```
|
| 174 |
+
|
| 175 |
+
Install pip requirements
|
| 176 |
+
|
| 177 |
+
```bash
|
| 178 |
+
python3 -m pip install --user -r requirements.txt
|
| 179 |
+
```
|
| 180 |
+
|
| 181 |
+
_**Note:** If you face a distutils error in pip, use `--ignore-installed` flag in above command._
|
| 182 |
+
|
| 183 |
+
<!-- Wiki should not get cloned -->
|
| 184 |
+
|
| 185 |
+
### 3. Run the code
|
| 186 |
+
|
| 187 |
+
1. First copy and examine the sample data to know how to structure your inputs:
|
| 188 |
+
```bash
|
| 189 |
+
cp -r ./samples/sample1 inputs/
|
| 190 |
+
# Note: you may remove previous inputs (if any) with `mv inputs/* ~/.trash`
|
| 191 |
+
# Change the number N in sampleN to see more examples
|
| 192 |
+
```
|
| 193 |
+
2. Run OMRChecker:
|
| 194 |
+
```bash
|
| 195 |
+
python3 main.py
|
| 196 |
+
```
|
| 197 |
+
|
| 198 |
+
Alternatively you can also use `python3 main.py -i ./samples/sample1`.
|
| 199 |
+
|
| 200 |
+
Each example in the samples folder demonstrates different ways in which OMRChecker can be used.
|
| 201 |
+
|
| 202 |
+
### Common Issues
|
| 203 |
+
|
| 204 |
+
<details>
|
| 205 |
+
<summary>
|
| 206 |
+
1. [Windows] ERROR: Could not open requirements file<br>
|
| 207 |
+
</summary>
|
| 208 |
+
Command: <code>python3 -m pip install --user -r requirements.txt</code>
|
| 209 |
+
<br>
|
| 210 |
+
Link to Solution: <a href="https://github.com/Udayraj123/OMRChecker/issues/54#issuecomment-1264569006">#54</a>
|
| 211 |
+
</details>
|
| 212 |
+
<details>
|
| 213 |
+
<summary>
|
| 214 |
+
2. [Linux] ERROR: No module named pip<br>
|
| 215 |
+
</summary>
|
| 216 |
+
Command: <code>python3 -m pip install --user --upgrade pip</code>
|
| 217 |
+
<br>
|
| 218 |
+
Link to Solution: <a href="https://github.com/Udayraj123/OMRChecker/issues/70#issuecomment-1268094136">#70</a>
|
| 219 |
+
</details>
|
| 220 |
+
|
| 221 |
+
## OMRChecker for custom OMR Sheets
|
| 222 |
+
|
| 223 |
+
1. First, [create your own template.json](https://github.com/Udayraj123/OMRChecker/wiki/User-Guide).
|
| 224 |
+
2. Configure the tuning parameters.
|
| 225 |
+
3. Run OMRChecker with appropriate arguments (See full usage).
|
| 226 |
+
<!-- 4. Add answer key( TODO: add answer key/marking scheme guide) -->
|
| 227 |
+
|
| 228 |
+
## Full Usage
|
| 229 |
+
|
| 230 |
+
```
|
| 231 |
+
python3 main.py [--setLayout] [--inputDir dir1] [--outputDir dir1]
|
| 232 |
+
```
|
| 233 |
+
|
| 234 |
+
Explanation for the arguments:
|
| 235 |
+
|
| 236 |
+
`--setLayout`: Set up OMR template layout - modify your json file and run again until the template is set.
|
| 237 |
+
|
| 238 |
+
`--inputDir`: Specify an input directory.
|
| 239 |
+
|
| 240 |
+
`--outputDir`: Specify an output directory.
|
| 241 |
+
|
| 242 |
+
<details>
|
| 243 |
+
<summary>
|
| 244 |
+
<b>Deprecation logs</b>
|
| 245 |
+
</summary>
|
| 246 |
+
|
| 247 |
+
- The old `--noCropping` flag has been replaced with the 'CropPage' plugin in "preProcessors" of the template.json(see [samples](https://github.com/Udayraj123/OMRChecker/tree/master/samples)).
|
| 248 |
+
- The `--autoAlign` flag is deprecated due to low performance on a generic OMR sheet
|
| 249 |
+
- The `--template` flag is deprecated and instead it's recommended to keep the template file at the parent folder containing folders of different images
|
| 250 |
+
</details>
|
| 251 |
+
|
| 252 |
+
<!-- #### Testing the code
|
| 253 |
+
Datasets to test on :
|
| 254 |
+
Low Quality Dataset(For CV Based methods)) (1.5 GB)
|
| 255 |
+
Standard Quality Dataset(For ML Based methods) (3 GB)
|
| 256 |
+
High Quality Dataset(For custom processing) (6 GB)
|
| 257 |
+
-->
|
| 258 |
+
|
| 259 |
+
## FAQ
|
| 260 |
+
|
| 261 |
+
<details>
|
| 262 |
+
<summary>
|
| 263 |
+
<b>Why is this software free?</b>
|
| 264 |
+
</summary>
|
| 265 |
+
|
| 266 |
+
This project was born out of a student-led organization called as [Technothlon](https://technothlon.techniche.org.in). It is a logic-based international school championship organized by students of IIT Guwahati. Being a non-profit organization, and after seeing it work fabulously at such a large scale we decided to share this tool with the world. The OMR checking processes still involves so much tediousness which we aim to reduce dramatically.
|
| 267 |
+
|
| 268 |
+
We believe in the power of open source! Currently, OMRChecker is in an intermediate stage where only developers can use it. We hope to see it become more user-friendly as well as robust from exposure to different inputs from you all!
|
| 269 |
+
|
| 270 |
+
[](https://github.com/ellerbrock/open-source-badges/)
|
| 271 |
+
|
| 272 |
+
</details>
|
| 273 |
+
|
| 274 |
+
<details>
|
| 275 |
+
<summary>
|
| 276 |
+
<b>Can I use this code in my (public) work?</b>
|
| 277 |
+
</summary>
|
| 278 |
+
|
| 279 |
+
OMRChecker can be forked and modified. You are encouraged to play with it and we would love to see your own projects in action!
|
| 280 |
+
|
| 281 |
+
It is published under the [MIT license](https://github.com/Udayraj123/OMRChecker/blob/master/LICENSE).
|
| 282 |
+
|
| 283 |
+
</details>
|
| 284 |
+
|
| 285 |
+
<details>
|
| 286 |
+
<summary>
|
| 287 |
+
<b>What are the ways to contribute?</b>
|
| 288 |
+
</summary>
|
| 289 |
+
|
| 290 |
+
<!-- - Help OMRChecker reach more people by giving a star! The Goal is to reach top position for the [OMR Topic](https://github.com/topics/omr) -->
|
| 291 |
+
|
| 292 |
+
- Join the developer community on [Discord](https://discord.gg/qFv2Vqf) to fix [issues](https://github.com/Udayraj123/OMRChecker/issues) with OMRChecker.
|
| 293 |
+
|
| 294 |
+
- If this project saved you large costs on OMR Software licenses, or saved efforts to make one. Consider donating an amount of your choice(donate section).
|
| 295 |
+
|
| 296 |
+
<!--  -->
|
| 297 |
+
<!-- [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Z5BNNK7AVFVH8&source=url) -->
|
| 298 |
+
<!-- https://www.amazon.in/hz/wishlist/ls/3V0TDQBI3T8IL -->
|
| 299 |
+
|
| 300 |
+
</details>
|
| 301 |
+
|
| 302 |
+
## Credits
|
| 303 |
+
|
| 304 |
+
_A Huge thanks to:_
|
| 305 |
+
_**Adrian Rosebrock** for his exemplary blog:_ https://pyimagesearch.com
|
| 306 |
+
|
| 307 |
+
_**Harrison Kinsley** aka sentdex for his [video tutorials](https://www.youtube.com/watch?v=Z78zbnLlPUA&list=PLQVvvaa0QuDdttJXlLtAJxJetJcqmqlQq) and many other resources._
|
| 308 |
+
|
| 309 |
+
_**Satya Mallic** for his resourceful blog:_ https://www.learnopencv.com
|
| 310 |
+
|
| 311 |
+
_And to other amazing people from all over the globe who've made significant improvements in this project._
|
| 312 |
+
|
| 313 |
+
_Thank you!_
|
| 314 |
+
|
| 315 |
+
<!--
|
| 316 |
+
OpencV
|
| 317 |
+
matplotlib
|
| 318 |
+
some SO answers from roughworks
|
| 319 |
+
prof
|
| 320 |
+
-->
|
| 321 |
+
|
| 322 |
+
## Related Projects
|
| 323 |
+
|
| 324 |
+
Here's a snapshot of the [Android OMR Helper App (archived)](https://github.com/Udayraj123/AndroidOMRHelper):
|
| 325 |
+
|
| 326 |
+
<p align="center">
|
| 327 |
+
<a href="https://github.com/Udayraj123/AndroidOMRHelper">
|
| 328 |
+
<img height="300" src="https://raw.githubusercontent.com/wiki/Udayraj123/OMRChecker/extras/Progress/2019-04-26/images/app_flow.PNG">
|
| 329 |
+
</a>
|
| 330 |
+
</p>
|
| 331 |
+
|
| 332 |
+
## Stargazers over time
|
| 333 |
+
|
| 334 |
+
[](https://starchart.cc/Udayraj123/OMRChecker)
|
| 335 |
+
|
| 336 |
+
---
|
| 337 |
+
|
| 338 |
+
<h2 align="center">Made with ❤️ by Awesome Contributors</h2>
|
| 339 |
+
|
| 340 |
+
<a href="https://github.com/Udayraj123/OMRChecker/graphs/contributors">
|
| 341 |
+
<img src="https://contrib.rocks/image?repo=Udayraj123/OMRChecker" />
|
| 342 |
+
</a>
|
| 343 |
+
|
| 344 |
+
---
|
| 345 |
+
|
| 346 |
+
### License
|
| 347 |
+
|
| 348 |
+
[](https://github.com/Udayraj123/OMRChecker/blob/master/LICENSE)
|
| 349 |
+
|
| 350 |
+
For more details see [LICENSE](https://github.com/Udayraj123/OMRChecker/blob/master/LICENSE).
|
| 351 |
+
|
| 352 |
+
### Donate
|
| 353 |
+
|
| 354 |
+
<a href="https://www.buymeacoffee.com/Udayraj123" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a> [](https://www.paypal.me/Udayraj123/500)
|
| 355 |
+
|
| 356 |
+
_Find OMRChecker on_ [**_Product Hunt_**](https://www.producthunt.com/posts/omr-checker/) **|** [**_Reddit_**](https://www.reddit.com/r/computervision/comments/ccbj6f/omrchecker_grade_exams_using_python_and_opencv/) **|** [**Discord**](https://discord.gg/qFv2Vqf) **|** [**Linkedin**](https://www.linkedin.com/pulse/open-source-talks-udayraj-udayraj-deshmukh/) **|** [**goodfirstissue.dev**](https://goodfirstissue.dev/language/python) **|** [**codepeak.tech**](https://www.codepeak.tech/) **|** [**fossoverflow.dev**](https://fossoverflow.dev/projects) **|** [**Interview on Console by CodeSee**](https://console.substack.com/p/console-140) **|** [**Open Source Hub**](https://opensourcehub.io/udayraj123/omrchecker)
|
| 357 |
+
|
| 358 |
+
<!-- [***Hacker News***](https://news.ycombinator.com/item?id=20420602) **|** -->
|
| 359 |
+
<!-- **|** [***Swyya***](https://www.swyya.com/projects/omrchecker) -->
|
OMRChecker/docs/assets/colored_output.jpg
ADDED
|
OMRChecker/inputs/OMRImage.jpg
ADDED
|
Git LFS Details
|
OMRChecker/inputs/template.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"pageDimensions": [
|
| 3 |
+
1122,
|
| 4 |
+
1600
|
| 5 |
+
],
|
| 6 |
+
"bubbleDimensions": [
|
| 7 |
+
48,
|
| 8 |
+
50
|
| 9 |
+
],
|
| 10 |
+
"fieldBlocks": {
|
| 11 |
+
"q01block": {
|
| 12 |
+
"origin": [
|
| 13 |
+
100,
|
| 14 |
+
175
|
| 15 |
+
],
|
| 16 |
+
"bubblesGap": 55,
|
| 17 |
+
"labelsGap": 67,
|
| 18 |
+
"fieldLabels": [
|
| 19 |
+
"q1..10"
|
| 20 |
+
],
|
| 21 |
+
"fieldType": "QTYPE_MCQ4"
|
| 22 |
+
},
|
| 23 |
+
"q02block": {
|
| 24 |
+
"origin": [
|
| 25 |
+
100,
|
| 26 |
+
845
|
| 27 |
+
],
|
| 28 |
+
"bubblesGap": 58,
|
| 29 |
+
"labelsGap": 70,
|
| 30 |
+
"fieldLabels": [
|
| 31 |
+
"q11..20"
|
| 32 |
+
],
|
| 33 |
+
"fieldType": "QTYPE_MCQ4"
|
| 34 |
+
}
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
}
|
OMRChecker/main.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
|
| 3 |
+
OMRChecker
|
| 4 |
+
|
| 5 |
+
Author: Udayraj Deshmukh
|
| 6 |
+
Github: https://github.com/Udayraj123
|
| 7 |
+
|
| 8 |
+
"""
|
| 9 |
+
|
| 10 |
+
import argparse
|
| 11 |
+
import sys
|
| 12 |
+
from pathlib import Path
|
| 13 |
+
|
| 14 |
+
from src.entry import entry_point
|
| 15 |
+
from src.logger import logger
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def parse_args():
|
| 19 |
+
# construct the argument parse and parse the arguments
|
| 20 |
+
argparser = argparse.ArgumentParser()
|
| 21 |
+
|
| 22 |
+
argparser.add_argument(
|
| 23 |
+
"-i",
|
| 24 |
+
"--inputDir",
|
| 25 |
+
default=["inputs"],
|
| 26 |
+
# https://docs.python.org/3/library/argparse.html#nargs
|
| 27 |
+
nargs="*",
|
| 28 |
+
required=False,
|
| 29 |
+
type=str,
|
| 30 |
+
dest="input_paths",
|
| 31 |
+
help="Specify an input directory.",
|
| 32 |
+
)
|
| 33 |
+
|
| 34 |
+
argparser.add_argument(
|
| 35 |
+
"-d",
|
| 36 |
+
"--debug",
|
| 37 |
+
required=False,
|
| 38 |
+
dest="debug",
|
| 39 |
+
action="store_false",
|
| 40 |
+
help="Enables debugging mode for showing detailed errors",
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
argparser.add_argument(
|
| 44 |
+
"-o",
|
| 45 |
+
"--outputDir",
|
| 46 |
+
default="outputs",
|
| 47 |
+
required=False,
|
| 48 |
+
dest="output_dir",
|
| 49 |
+
help="Specify an output directory.",
|
| 50 |
+
)
|
| 51 |
+
|
| 52 |
+
argparser.add_argument(
|
| 53 |
+
"-a",
|
| 54 |
+
"--autoAlign",
|
| 55 |
+
required=False,
|
| 56 |
+
dest="autoAlign",
|
| 57 |
+
action="store_true",
|
| 58 |
+
help="(experimental) Enables automatic template alignment - \
|
| 59 |
+
use if the scans show slight misalignments.",
|
| 60 |
+
)
|
| 61 |
+
|
| 62 |
+
argparser.add_argument(
|
| 63 |
+
"-l",
|
| 64 |
+
"--setLayout",
|
| 65 |
+
required=False,
|
| 66 |
+
dest="setLayout",
|
| 67 |
+
action="store_true",
|
| 68 |
+
help="Set up OMR template layout - modify your json file and \
|
| 69 |
+
run again until the template is set.",
|
| 70 |
+
)
|
| 71 |
+
|
| 72 |
+
(
|
| 73 |
+
args,
|
| 74 |
+
unknown,
|
| 75 |
+
) = argparser.parse_known_args()
|
| 76 |
+
|
| 77 |
+
args = vars(args)
|
| 78 |
+
|
| 79 |
+
if len(unknown) > 0:
|
| 80 |
+
logger.warning(f"\nError: Unknown arguments: {unknown}", unknown)
|
| 81 |
+
argparser.print_help()
|
| 82 |
+
exit(11)
|
| 83 |
+
return args
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def entry_point_for_args(args):
|
| 87 |
+
if args["debug"] is True:
|
| 88 |
+
# Disable tracebacks
|
| 89 |
+
sys.tracebacklimit = 0
|
| 90 |
+
for root in args["input_paths"]:
|
| 91 |
+
entry_point(
|
| 92 |
+
Path(root),
|
| 93 |
+
args,
|
| 94 |
+
)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
if __name__ == "__main__":
|
| 98 |
+
args = parse_args()
|
| 99 |
+
entry_point_for_args(args)
|
OMRChecker/outputs/AdrianSample/Manual/ErrorFiles.csv
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
"file_id","input_path","output_path","score","q1","q2","q3","q4","q5"
|
OMRChecker/outputs/AdrianSample/Manual/MultiMarkedFiles.csv
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
"file_id","input_path","output_path","score","q1","q2","q3","q4","q5"
|
OMRChecker/outputs/AdrianSample/Results/Results_07PM.csv
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
"file_id","input_path","output_path","score","q1","q2","q3","q4","q5"
|
OMRChecker/outputs/CheckedOMRs/OMRImage.jpg
ADDED
|
Git LFS Details
|
OMRChecker/outputs/CheckedOMRs/OMRSheet.jpg
ADDED
|
Git LFS Details
|
OMRChecker/outputs/CheckedOMRs/OcrSheetMarked.jpg
ADDED
|
Git LFS Details
|
OMRChecker/outputs/Images/CheckedOMRs/OMRSheet.jpg
ADDED
|
Git LFS Details
|
OMRChecker/outputs/Images/Manual/ErrorFiles.csv
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
"file_id","input_path","output_path","score","q1","q2","q3","q4","q5","q6","q7","q8","q9","q10","q11","q12","q13","q14","q15","q16","q17","q18","q19","q20"
|
OMRChecker/outputs/Images/Manual/MultiMarkedFiles.csv
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
"file_id","input_path","output_path","score","q1","q2","q3","q4","q5","q6","q7","q8","q9","q10","q11","q12","q13","q14","q15","q16","q17","q18","q19","q20"
|
OMRChecker/outputs/Images/Results/Results_10PM.csv
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"file_id","input_path","output_path","score","q1","q2","q3","q4","q5","q6","q7","q8","q9","q10","q11","q12","q13","q14","q15","q16","q17","q18","q19","q20"
|
| 2 |
+
"OMRSheet.jpg","inputs\Images\OMRSheet.jpg","outputs\Images\CheckedOMRs\OMRSheet.jpg","0","C","D","A","C","B","C","C","D","D","B","B","B","D","C","C","ABCD","B","ABCD","C","ABCD"
|
OMRChecker/outputs/Manual/ErrorFiles.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"file_id","input_path","output_path","score","q1","q2","q3","q4","q5","q6","q7","q8","q9","q10","q11","q12","q13","q14","q15","q16","q17","q18","q19","q20"
|
| 2 |
+
"OMRSheet.jpg","inputs\OMRSheet.jpg","outputs\Manual\ErrorFiles\OMRSheet.jpg","NA","","","","","","","","","","","","","","","","","","","",""
|
| 3 |
+
"OMRSheet.jpg","inputs\OMRSheet.jpg","outputs\Manual\ErrorFiles\OMRSheet.jpg","NA","","","","","","","","","","","","","","","","","","","",""
|
OMRChecker/outputs/Manual/MultiMarkedFiles.csv
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
"file_id","input_path","output_path","score","q1","q2","q3","q4","q5","q6","q7","q8","q9","q10","q11","q12","q13","q14","q15","q16","q17","q18","q19","q20"
|
OMRChecker/outputs/MobileCamera/Manual/ErrorFiles.csv
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
"file_id","input_path","output_path","score","Roll","q1","q2","q3","q4","q5","q6","q7","q8","q9","q10","q11","q12","q13","q14","q15","q16","q17","q18","q19","q20"
|
OMRChecker/outputs/MobileCamera/Manual/MultiMarkedFiles.csv
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
"file_id","input_path","output_path","score","Roll","q1","q2","q3","q4","q5","q6","q7","q8","q9","q10","q11","q12","q13","q14","q15","q16","q17","q18","q19","q20"
|
OMRChecker/outputs/MobileCamera/Results/Results_09PM.csv
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
"file_id","input_path","output_path","score","Roll","q1","q2","q3","q4","q5","q6","q7","q8","q9","q10","q11","q12","q13","q14","q15","q16","q17","q18","q19","q20"
|
OMRChecker/pyproject.toml
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[tool.black]
|
| 2 |
+
exclude = '''
|
| 3 |
+
(
|
| 4 |
+
/(
|
| 5 |
+
\.eggs # exclude a few common directories in the
|
| 6 |
+
| \.git # root of the project
|
| 7 |
+
| \.venv
|
| 8 |
+
| _build
|
| 9 |
+
| build
|
| 10 |
+
| dist
|
| 11 |
+
)/
|
| 12 |
+
| foo.py # also separately exclude a file named foo.py in
|
| 13 |
+
# the root of the project
|
| 14 |
+
)
|
| 15 |
+
'''
|
| 16 |
+
include = '\.pyi?$'
|
| 17 |
+
line-length = 88
|
| 18 |
+
target-version = ['py37']
|
OMRChecker/pytest.ini
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# pytest.ini
|
| 2 |
+
[pytest]
|
| 3 |
+
minversion = 7.0
|
| 4 |
+
addopts = -qq --capture=no
|
| 5 |
+
testpaths =
|
| 6 |
+
src/tests
|
OMRChecker/requirements.dev.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-r requirements.txt
|
| 2 |
+
flake8>=6.0.0
|
| 3 |
+
freezegun>=1.2.2
|
| 4 |
+
pre-commit>=3.3.3
|
| 5 |
+
pytest-mock>=3.11.1
|
| 6 |
+
pytest>=7.4.0
|
| 7 |
+
syrupy>=4.0.4
|
OMRChecker/requirements.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
deepmerge>=1.1.0
|
| 2 |
+
dotmap>=1.3.30
|
| 3 |
+
jsonschema>=4.17.3
|
| 4 |
+
matplotlib>=3.7.1
|
| 5 |
+
numpy>=1.25.0
|
| 6 |
+
pandas>=2.0.2
|
| 7 |
+
rich>=13.4.2
|
| 8 |
+
screeninfo>=0.8.1
|