In Brazil there is a form called DNV (after the Portuguese for "Born Alive Declaration"). I work at a Brazilian government agency that receives more than half a million of these every year from every hospital across the state.
I'm trying to detect marks on the checkbox fields. I started with the "Sex" field which has checkboxes for M (male), F (female) or I (ignored).
I'm already able to locate the field and the checkboxes with confidence using OpenCV:
I guess the checkbox region with more dark pixels is the one marked, and it works 99% of the time, even when the image quality is very low.
if sum(checkbox1) < sum(checkbox2):
return "M"
else:
return "F"
Sometimes this fail: a human would tell the "female" checkbox is marked, but since sum(checkbox1) is 577,065 and sum(checkbox1) is 605,880 the computer says it is a boy.
I've tried thresholding operations using several methods and values combined with morphological transforms (erode and dilate in several combinations and using many kernel shapes and sizes) and got this:
sex_field = cv2.fastNlMeansDenoising(cv2.blur(sex_field, (3, 3)), 30, 30, 15, 50)
_, sex_field = cv2.threshold(~sex_field, 127, 255, 0)
sex_field = ~cv2.morphologyEx(sex_field, cv2.MORPH_CLOSE,
np.ones((3, 3), np.uint8), iterations=3)
The problem is cv2.fastNlMeansDenoising is expensive. Is there a lighter algorithm useful for this use case?


