Detect selected checkbox in form image

Viewed 1682

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:

enter image description here

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.

enter image description here

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)

enter image description here

The problem is cv2.fastNlMeansDenoising is expensive. Is there a lighter algorithm useful for this use case?

0 Answers
Related