I am not a programmer, but, using Python, I have pieced together an OMR marking programme from bits of code I got from the web and some ideas of my own.
To my amazement, it works very well!
Most of it I can understand, at least in principle.
Is there some kind person who could explain a little of what is happening in the function countPixels() below ?
What for example does np.zeros() do??
If a question has 3 choices, A, B or C, then:
contours are the contours found by:
thresh2 = thresh.copy()
contours2, hierarchy = cv2.findContours(thresh2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
They represent the bubbles A, B and C and are sorted left to right.
minimum_pixels is just the minimum number of pixels to count as a marked bubble (for my present set-up, 800 works well.)
and thresh is:
thresh = cv2.threshold(grey, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
Here is my function:
def countPixels(contours, minimum_pixels, thresh):
# at the moment this can only accept 1 correct answer. Work on that.
for (j, c) in enumerate(contours):
mask = np.zeros(thresh.shape, dtype="uint8")
cv2.drawContours(mask, [c], -1, 255, -1)
mask = cv2.bitwise_and(thresh, thresh, mask=mask)
total = cv2.countNonZero(mask)
# if the number of pixels is > minimum_pixels, we found the marked choice
if total >= minimum_pixels:
print('number of pixels is: ', total)
bubbled = (total, j)
return bubbled
else:
# there is no answer A, so this counts as 0
bubbled = (total, 'A')
return bubbled