Calibrate a page
Hello,
I'm trying to find whenever checkboxes on a scanned sheet of paper are checked or not. Before analyzing the average color of the checkbox and compare it to the average color of blank area on the page, I need to find position of checkboxes.
To do so, I need to "calibrate" my page (because the page can be slightly rotated, and because the scanner autocrop the sheet of paper, not everytime the same way) . I have drawn 3 black squares on the sheet of paper, that I have put near the top right corner, bottom left corner and bottom right corner of the page. I'm trying to find the position of this 3 squares to be able to find the position of checkboxes (I know their position in centimeter, relativly to the calibrating squares, and I know the distance in centimeter between the calibrating squares).
I used the findsquares function from opencv square example. It works, but it finds multiples times the same square (It detect about 500 to 1000 time each square). So I need to filter the results from findsquares. I tried first to write some code to detect square which is most on the top and on the right and the same for the 2 other squares. But I realized after some trials, that it is not possible to define a"top right" corner when there is more than 3 squares (i got thousand of them) randomly disposed on a plane.
Then, I tried to find which squares are really close of the other and delete them. But I got error on execution (list iterator not incrementable), as I must be out of range in some way. Below the code i use. The "squares" variable comes from findSquares(const Mat& image, vector<vector<point> >& squares) from opencv example.
std::list<vector<Point>> liste_square(squares.begin(), squares.end());
for (list<vector<Point>>::iterator x = liste_square.begin(); x != liste_square.end();x++) {
vector<Point> rect1 = *x;
for (list<vector<Point>>::iterator y = x++; y != liste_square.end();)
{
vector<Point> rect2 = *y;
Point middle1 = (rect1[0] + rect1[2])*0.5;
Point middle2 = (rect2[0] + rect2[2])*0.5;
Point littlediag = rect1[2] - rect1[0]; //diag of a square
Point bigdiag = middle2 - middle1; //vector between the two centers of squares
double diago = cv::sqrt(littlediag.x*littlediag.x + littlediag.y*littlediag.y);
double distance = cv::sqrt(bigdiag.x*bigdiag.x + bigdiag.y*bigdiag.y);
if (distance <= diago)
{
y = liste_square.erase(y);
}
else
{
y++;
}
}
}
So now, I'm a little bit lost. I don't know which way is the better : Try to fix the "list iterator not incrementable" error, find another way to calibrate the page than 3 black squares, improve findsquares function...
Do you have any suggestion?
EDIT: As requested, the image :
It's not the original image, as it makes 3.2Mo and 25048x3507 and I cannot upload such big image. I resized the original image using Lanczos filter in Irfanview. In my code, i take the orignal ...
Could you provide a sample image