Motivation: Last October 7 there was a presidential election in Venezuela. Although the opposition saw an unprecedented increase in its votes, the government votes increased even more resulting in the current president being re-elected. The votes were counted by computers that are not trustworthy because of what they have done in the past. Each voting machine printed a voting certificate with the results. About 90% of such certificates where collected by the opposition and are available to anyone at http://hayuncamino.com/actas/
In each voting table there was a paper notebook were each voter put its signature and fingerprint. According to the law, the total number of votes from this notebook was supposed to be compared to the votes reported by the machine. The results certificate provided a space where this number must be hand written. Unfortunately it seems that in a very large number of voting tables the law was broken because the space for this verification is empty.
By using Mathematica image processing capabilities I intend to find out in which voting tables the verification was done and compare the results of this subset with its complement.
The original question:
I need to process a large number of images for a non-profit organization report. The images contain a grid with borders and cells. The cells B2 and C2 (spreadsheet coordinates) can be hand written or can be empty, and that is what needs to be detected.
Here is an example of a filled form:
And this is an example of an empty form:
My plan is to detect the coordinates of the following points:
and then compute to total amount o black pixels in the area defined by them.
So my question is: What strategy would you recommend to reliably detect the location of those points indicated in red?
I have already tried using ImageLines
, Radon
, and FindGeometricTransform
without much success. I think that the best approach is not to look for independent lines but instead look for the grid as a whole.
This is what I am trying to do:
figWithoutSideBorders =
ColorNegate @
ImageAdd[fig,
ColorNegate @ Erosion[#, 3] & @ MeanFilter[#, 1] & @ MaxDetect[fig, 0.95]
]
I careful crafted this matrix so that it has the same proportions as the target grid:
formMatrix = SparseArray[{Band[{ 1, 1 }, Automatic, {0,1}] -> 1,
Band[{15, 1 }, Automatic, {0,1}] -> 1,
Band[{29, 1 }, Automatic, {0,1}] -> 1,
Band[{52, 1 }, Automatic, {0,1}] -> 1,
Band[{66, 1 }, Automatic, {0,1}] -> 1,
Band[{ 1, 1 }, Automatic, {1,0}] -> 1,
Band[{ 1,105}, Automatic, {1,0}] -> 1,
Band[{ 1,146}, Automatic, {1,0}] -> 1,
Band[{ 1,265}, Automatic, {1,0}] -> 1},
{66,265}];
formFigure = ColorNegate @ ArrayPlot[formMatrix, AspectRatio -> Automatic, Frame -> False]
But when I try to use FindGeometricTransform
, it fails. Maybe it does not work with hollow objects?
As I last resort, I am thinking about doing horizontal and vertical histograms and look for proportionally spaced peaks, but I want to ask the community before I over engineer a solution. Thanks in advance.
UPDATE 1: @nikie answer is certainly very useful and I am thankful for that. My only concern is that this method looks for any table instead of looking for a 4x3 table with row heights 21%, 21%, 36%, 21% and column widths 40%, 15% and 45%. The fragility of the method is exposed by using the other provided sample image where a vertical line, that is not part of the table is confused for an additional column:
UPDATE 2: As suggested by @belisarius I have added some context / motivation for this question.
UPDATE 3: I have now finished the processing. Only 5.7% on the voting certificates where not blank in the target total votes verification area. About 99% of the voting certificates were processed automatically. I have developed a set of functions that could be useful for other people doing similar tasks (and even in different areas), so I plan to write an answer to share that. Look also for a torrent file in the comments area.