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