Using a simple combination of blur and threshold, I managed to get this result (modified for viewing):

After that, using erosion and the squares.cpp method (which is a sample from OpenCV) produces:

, : . , , ( ) .
:
Mat img = imread(argv[1]);
Mat new_img = img.clone();
medianBlur(new_img, new_img, 5);
double thres = 210;
double color = 255;
threshold(new_img, new_img, thres, color, CV_THRESH_BINARY);
imwrite("thres.png", new_img);
int erosion_size = 4;
Mat element = getStructuringElement(MORPH_CROSS,
Size(2 * erosion_size + 1, 2 * erosion_size + 1),
Point(erosion_size, erosion_size) );
erode(new_img, new_img, element);
imwrite("erode.png", new_img);
vector<vector<Point> > squares;
find_squares(new_img, squares);
std::cout << "squares: " << squares.size() << std::endl;
draw_squares(img, squares);
imwrite("area.png", img);
find_squares() , . , , squares.size() 3.
4 (X, Y), OpenCV vector<Point>, X Y.
squares , :
1st ------ 4th
| |
| |
| |
2nd ------ 3rd
, , , Y 1- 4- :
for (int i = 0; i < squares.size(); i++)
{
for (int j = 0; j < squares[i].size(); j++)
{
// std::cout << "# " << i << " " << squares[i][j].x << ","<< squares[i][j].y << std::endl;
if (j == 0 || j == 3)
squares[i][j].y = 0;
}
}
