Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Evaluation Schema + a necessary revamp #118

Merged
merged 24 commits into from
Feb 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8471190
fix: add upsc mock; refactor; create evaluation-schema
Udayraj123 Dec 30, 2022
a796fe6
fix: refactor; change defaults to .py; pickup config.json recursively…
Udayraj123 Jan 1, 2023
f41d128
fix: update evaluation-schema and sample json wip
Udayraj123 Jan 2, 2023
e74394e
refactor: separate static vs instance ImageUtils; breakfown files fur…
Udayraj123 Jan 3, 2023
c69b978
fix: load json error handling; dynamic config json working for sample5
Udayraj123 Jan 5, 2023
91fc506
fix: use formatted strings at all places necessary
Udayraj123 Jan 5, 2023
3e7450f
fix: correct config schema
Udayraj123 Jan 5, 2023
453680b
fix: working evaluation code
Udayraj123 Jan 5, 2023
f8b97c3
fix: add range operator support; add validations for marking scheme a…
Udayraj123 Jan 7, 2023
aa69b50
fix: add a sample with answer_key.csv
Udayraj123 Jan 7, 2023
d16b647
fix: minor fixes
Udayraj123 Jan 8, 2023
9bd65dd
fix: foundation for answer_key_image_path; refactoring; minor changes
Udayraj123 Jan 8, 2023
cb6817d
fix: remove unnecessary comments; fix minor comments
Udayraj123 Jan 8, 2023
f8a7d91
fix: further on foundation for csv_from_image feature; refactoring
Udayraj123 Jan 8, 2023
8169a81
fix: stronger validations; conditionality in streak scheme; joinpath …
Udayraj123 Jan 12, 2023
54383b3
fix: support multi-correct and basic multi-weighted; update explanations
Udayraj123 Jan 13, 2023
b715c8f
fix: csv load custom key support
Udayraj123 Jan 13, 2023
ea75858
fix: add evaluation configs in some samples
Udayraj123 Jan 13, 2023
3692500
fix: load answer key from image with working samples
Udayraj123 Jan 23, 2023
fb15654
fix: compress images
Udayraj123 Jan 26, 2023
d308609
fix: update samples; add readme for template shift sample
Udayraj123 Jan 26, 2023
1f54a6e
Merge branch 'master' into feature/evalution-refactor
Udayraj123 Feb 1, 2023
b2f394b
fix: reduce images; minor changes
Udayraj123 Feb 1, 2023
426b7a6
[Feature] setup pytest on existing samples (#124)
Udayraj123 Feb 12, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 11 additions & 12 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
**/__pycache__
**/CheckedOMRs
**/ignore
**/.DS_Store
**/.vscode
venv/
.idea/
OMRChecker.wiki/
# Any directory starting with a dot
**/\.*/
# Except .github
!.github/

# Everything in inputs/ and outputs/
inputs/*
outputs/*
# Except *.json and OMR_Files/
# !inputs/OMR_Files/
# !inputs/*.json
# !inputs/omr_marker.jpg

# Misc
**/.DS_Store
**/__pycache__
venv/
OMRChecker.wiki/
53 changes: 41 additions & 12 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,23 +1,52 @@
exclude: "__snapshots__/.*$"
default_install_hook_types: [pre-commit, pre-push]
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/pycqa/isort
- id: check-yaml
stages: [commit]
- id: end-of-file-fixer
exclude_types: ["csv", "json"]
stages: [commit]
- id: trailing-whitespace
stages: [commit]
- repo: https://github.com/pycqa/isort
rev: 5.5.4
hooks:
- id: isort
- id: isort
args: ["--profile", "black"]
- repo: https://github.com/psf/black
stages: [commit]
- repo: https://github.com/psf/black
rev: 22.3.0
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
- id: black
stages: [commit]
- repo: https://github.com/pycqa/flake8
rev: 3.7.9
hooks:
- id: flake8
- id: flake8
args:
- "F401,F841" # unused imports, unused variables
- "--ignore=E501,W503,E203" # Line too long, Line break occurred before a binary operator, Whitespace before ':'
- "F401,F841" # unused imports, unused variables
- "--ignore=E501,W503,E203,E741" # Line too long, Line break occurred before a binary operator, Whitespace before ':'
stages: [commit]
- repo: local
hooks:
- id: pytest-on-commit
name: Running single sample test
entry: pytest -k sample1
language: system
pass_filenames: false
always_run: true
fail_fast: true
stages: [commit]
- repo: local
hooks:
- id: pytest-on-push
name: Running all tests before push...
entry: pytest
language: system
pass_filenames: false
always_run: true
fail_fast: true
stages: [push]
24 changes: 15 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Read OMRs fast and accurately using a scanner 🖨 or your phone 🤳.

#### **Quick Links**
#### **Quick Links**
- [Installation](#getting-started)
- [User Guide](https://github.com/Udayraj123/OMRChecker/wiki)
- [Contributor Guide](https://github.com/Udayraj123/OMRChecker/blob/master/CONTRIBUTING.md)
Expand Down Expand Up @@ -104,7 +104,7 @@ Get a CSV sheet containing the detected responses and evaluated scores:

### 1. Install global dependencies

![opencv 4.0.0](https://img.shields.io/badge/opencv-4.0.0-blue.svg) ![python 3.4+](https://img.shields.io/badge/python-3.4+-blue.svg)
![opencv 4.0.0](https://img.shields.io/badge/opencv-4.0.0-blue.svg) ![python 3.5+](https://img.shields.io/badge/python-3.5+-blue.svg)

To check if python3 and pip is already installed:

Expand Down Expand Up @@ -215,25 +215,30 @@ Command: <code>python3 -m pip install --user --upgrade pip</code>
1. First, [create your own template.json](https://github.com/Udayraj123/OMRChecker/wiki/User-Guide).
2. Configure the tuning parameters.
3. Run OMRChecker with appropriate arguments (See full usage).
<!-- 3. Add answer key( TODO: add answer key/marking scheme guide) -->
<!-- 4. Add answer key( TODO: add answer key/marking scheme guide) -->

## Full Usage

```
python3 main.py [--setLayout] [--autoAlign] [--inputDir dir1] [--outputDir dir1]
python3 main.py [--setLayout] [--inputDir dir1] [--outputDir dir1]
```

Explanation for the arguments:

`--setLayout`: Set up OMR template layout - modify your json file and run again until the template is set.

`--autoAlign`: (experimental) Enables automatic template alignment - use if the scans show slight misalignments.

`--inputDir`: Specify an input directory.

`--outputDir`: Specify an output directory.

**Note:** The `--noCropping` flag has been replaced with including/excluding a 'CropPage' plugin in "preProcessors" of the template.json(see [samples](https://github.com/Udayraj123/OMRChecker/tree/master/samples)).
<details>
<summary>
<b>Deprecation logs</b>
</summary>

- 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)).
- The old `--autoAlign` flag can now be toggled from config.json
</details>

<!-- #### Testing the code
Datasets to test on :
Expand All @@ -242,6 +247,7 @@ Standard Quality Dataset(For ML Based methods) (3 GB)
High Quality Dataset(For custom processing) (6 GB)
-->


## FAQ

<details>
Expand Down Expand Up @@ -313,7 +319,7 @@ Here's a snapshot of the [Android OMR Helper App (archived)](https://github.com/

<p align="center">
<a href="https://github.com/Udayraj123/AndroidOMRHelper">
<img height="350" src="https://raw.githubusercontent.com/wiki/Udayraj123/OMRChecker/extras/Progress/2019-04-26/images/app_flow.PNG">
<img height="300" src="https://raw.githubusercontent.com/wiki/Udayraj123/OMRChecker/extras/Progress/2019-04-26/images/app_flow.PNG">
</a>
</p>

Expand All @@ -339,7 +345,7 @@ For more details see [LICENSE](https://github.com/Udayraj123/OMRChecker/blob/mas
<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> [![paypal](https://www.paypalobjects.com/en_GB/i/btn/btn_donate_LG.gif)](https://www.paypal.me/Udayraj123/500)


_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)
_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)

<!-- [***Hacker News***](https://news.ycombinator.com/item?id=20420602) **|** -->
<!-- **|** [***Swyya***](https://www.swyya.com/projects/omrchecker) -->
141 changes: 72 additions & 69 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,77 +7,80 @@

"""

import argparse
from pathlib import Path

from src.entry import entry_point
from src.logger import logger

logger.info(f"Loading OMRChecker modules...")
# It takes a few seconds for the imports

import argparse
from pathlib import Path
def parse_args():
# construct the argument parse and parse the arguments
argparser = argparse.ArgumentParser()

argparser.add_argument(
"-i",
"--inputDir",
default=["inputs"],
# https://docs.python.org/3/library/argparse.html#nargs
nargs="*",
required=False,
type=str,
dest="input_paths",
help="Specify an input directory.",
)

from src.core import entry_point

# construct the argument parse and parse the arguments
argparser = argparse.ArgumentParser()

argparser.add_argument(
"-i",
"--inputDir",
default=["inputs"],
# https://docs.python.org/3/library/argparse.html#nargs
nargs="*",
required=False,
type=str,
dest="input_paths",
help="Specify an input directory.",
)

argparser.add_argument(
"-o",
"--outputDir",
default="outputs",
required=False,
dest="output_dir",
help="Specify an output directory.",
)

# TODO: separate the interactive modes from main code
argparser.add_argument(
"-a",
"--autoAlign",
required=False,
dest="autoAlign",
action="store_true",
help="(experimental) Enables automatic template alignment - \
use if the scans show slight misalignments.",
)

argparser.add_argument(
"-l",
"--setLayout",
required=False,
dest="setLayout",
action="store_true",
help="Set up OMR template layout - modify your json file and \
run again until the template is set.",
)


(
args,
unknown,
) = argparser.parse_known_args()
args = vars(args)

# FIX: remove join
if len(unknown) > 0:
logger.warning("".join(["\nError: Unknown arguments: ", unknown]))
argparser.print_help()
exit(11)

for root in args["input_paths"]:
entry_point(
Path(root),
Path(root),
args,
argparser.add_argument(
"-o",
"--outputDir",
default="outputs",
required=False,
dest="output_dir",
help="Specify an output directory.",
)

argparser.add_argument(
"-a",
"--autoAlign",
required=False,
dest="autoAlign",
action="store_true",
help="(experimental) Enables automatic template alignment - \
use if the scans show slight misalignments.",
)

argparser.add_argument(
"-l",
"--setLayout",
required=False,
dest="setLayout",
action="store_true",
help="Set up OMR template layout - modify your json file and \
run again until the template is set.",
)

(
args,
unknown,
) = argparser.parse_known_args()

args = vars(args)

if len(unknown) > 0:
logger.warning(f"\nError: Unknown arguments: {unknown}", unknown)
argparser.print_help()
exit(11)
return args


def entry_point_for_args(args):
for root in args["input_paths"]:
entry_point(
Path(root),
args,
)


if __name__ == "__main__":
args = parse_args()
entry_point_for_args(args)
6 changes: 6 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# pytest.ini
[pytest]
minversion = 7.0
addopts = -qq --capture=no
testpaths =
src/tests
6 changes: 5 additions & 1 deletion requirements.dev.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
-r requirements.txt
pre-commit
pytest>=7.1.3
pytest-mock>=3.10.0
syrupy>=3.0.6
freezegun>=1.2.2
pre-commit>=2.20.0
13 changes: 7 additions & 6 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
matplotlib>=3.3.1
numpy>=1.16.1
pandas>=1.1.1
deepmerge>=0.1.0
dotmap>=1.3.17
jsonschema>=4.3.3
deepmerge>=1.0.1
dotmap>=1.3.30
jsonschema>=4.16.0
matplotlib>=3.5.3
numpy>=1.23.2
pandas>=1.4.3
rich>=12.6.0
screeninfo>=0.8.1
22 changes: 8 additions & 14 deletions samples/community/Antibodyy/template.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
{
"dimensions": [ 299, 398 ],
"pageDimensions": [ 299, 398 ],
"bubbleDimensions": [ 42, 42 ],
"concatenations": {},
"singles": [ "q1", "q2", "q3", "q4", "q5", "q6" ],
"qBlocks": {
"fieldBlocks": {
"MCQBlock1": {
"qType": "QTYPE_MCQ5",
"orig": [ 65, 79 ],
"qNos": [
[
[ "q1", "q2", "q3", "q4", "q5", "q6" ]
]
],
"gaps": [ 43, 50 ],
"bigGaps": [ 30, 30 ]
"fieldType": "QTYPE_MCQ5",
"origin": [65, 79],
"bubblesGap":43,
"labelsGap": 50,
"fieldLabels": ["q1..6"]
}
},
"preProcessors": [
Expand All @@ -24,4 +18,4 @@
}
}
]
}
}
Binary file modified samples/community/Sandeep-1507/omr-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading