Awesome OMR Scanner and Grader using just OpenCV and Python
All thanks to Adrian Rosebrock (from pyimagesearch) for making great tutorials. This project is inspired from his blog: Bubble sheet multiple choice scanner and test grader using OMR, Python and OpenCV. I have included the author's code and the one i wrote my self as well.
- Combines the following techniques:
- Building document scanner
- Sorting the contours
- Perspective transform to get top-down view
- Steps involved:
- Detect the OMR sheet
- Apply perspective transform to get the top-down view of the sheet
- Extract out all the bubbles in the sheet
- Sort them in rows
- Determine the answer bubble for each row
- Match with the correct answer
- Do this for all questions (all rows)
- Assumptions:
- The app assumes that the OMR document we are scanning is the main focus of the image.
- All 4 edges of the OMR document are visible in the image.
- The largest rectangle available in the image will be the OMR document.
- Stored the correct answer keys in a dict in python.
- Used Canny edge detection for detecting the edges in the document and Gussian blur for reducing high frequency noise.
- OpenCV has the way to get the top-down view of the image. Used that methodology to get the top-down view.
- Used Otsu’s thresholding method for thresholding.
- Determined the bubbles using the aspect ratio of approx one (1) for it's bounding rectangle.
- Used bitwise operations and masking to find the filled in bubble using the amount of shaded pixels in the bubble.
- python (3.7.3)
- opencv (4.1.0)
- numpy (1.61.4)
- imutils (0.5.2)
python test_grader.py --image images/test_02.png
The results are pretty amazing. The grading system is working perfectly fine.
input
Output
input
Output
- There is no logic to handle non-filled bubbles. (This can be solved by using a threshold value for marking a bubble as filled)
- Multiple bubbles marking is not handled. (This can also be solved using a threshold for marking bubble as filled and counting the number and position of filled bubbles)