Detect the grid of a graph paper

Hi,
I have photos like this : Dropbox - image.jpg - Simplify your life and want to detect the grid of a graph paper.
My code for now is :

String imageName("image.jpg"); // by default
src = imread(  imageName , IMREAD_COLOR ); // Load an image
Mat gray;
cvtColor( src, gray, COLOR_BGR2GRAY ); // Convert the image to Gray
cv::Ptr<cv::LineSegmentDetector> det;
 det = cv::createLineSegmentDetector();
cv::Mat lines;
det->detect(gray, lines);
Mat output = src.clone();
det->drawSegments(output, lines);
imwrite("res.jpg", output);

the result is :

but like you can see the lines detected are small, I want to deduct from these small lines the entire grid.

Please help me !
Best regards

yeah forget that LSD approach, never gonna work.

why do you want to “detect” the grid? what for? keep iterating on the “why?” question a bit.

it’s for detect automatically the scale of parts of image, I found a sudokyu grid detection on the Web which I inspirate with but I don’t succeeded with this code so I still need help, the lines are not always straight so in fact I need to extract the grid from the rest

I have done the following code :

cv::resize(src2, src, cv::Size( w, h));
    imwrite("imResized.jpg", src);
    Mat gray;
    cvtColor( src, gray, COLOR_BGR2GRAY ); // Convert the image to Gray
    //cv::Ptr<cv::LineSegmentDetector> det;
   // det = cv::createLineSegmentDetector();
    Mat outerBox = Mat(gray.size(), CV_8UC1);
    GaussianBlur(gray, gray, Size(3, 3), 0);
    adaptiveThreshold(gray, outerBox, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 5, 2);
    bitwise_not(outerBox, outerBox);
    Mat kernel = (Mat_<uchar>(3, 3) << 0, 1, 0, 1, 1, 1, 0, 1, 0);
    dilate(outerBox, outerBox, kernel);
    imwrite("img1.jpg", outerBox);
    //exit(1);
    int count = 0;
    int max = -1;

    Point maxPt;

    for (int y = 0; y < outerBox.size().height; y++)
    {
        if ((y%100)==0)
            cout << "y=" << y/100 << endl;
        uchar* row = outerBox.ptr(y);
        for (int x = 0; x < outerBox.size().width; x++)
        {
            if (row[x] >= 128)
            {

                int area = floodFill(outerBox, Point(x, y), CV_RGB(0, 0, 64));

                if (area > max)
                {
                    maxPt = Point(x, y);
                    max = area;
                }
            }
        }

    }
    floodFill(outerBox, maxPt, CV_RGB(255, 255, 255));
    imwrite("img2.jpg", outerBox);

which give me the following result :

the next step is to find the mean of small grid squares area
this result is good because find lines would be incorrect because the grid lines are curved. I can isolate the leaves and their shadows by instance segmentation

I think I can take the median and not the mean of the areas of black areas, but how isolate each black area ? And how to select the almost square areas because some squares are not closed ?

Edit : I finally succeeded by this code :

//get the areas of square black areas
Mat squaresContours = src.clone();
vector areas;
vector<vector > contours;
vector<vector > resContours;
vector hierarchy;
findContours(outerBox, contours, hierarchy, RETR_LIST, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); i++) {
// find moments of the image
Moments m = moments(127, true);
Point center (m.m10 / m.m00, m.m01 / m.m00);
if (outerBox.at(center) == 0) {//the center is black so certainly the area
vector approxCurve;
approxPolyDP(contours[i], approxCurve, 3, true);
if (approxCurve.size() == 4) {//the area is rectangle
//lengths of sides
double a = distanceP(approxCurve[0], approxCurve[1]);
double b = distanceP(approxCurve[0], approxCurve[2]);
double c = distanceP(approxCurve[1], approxCurve[0]);
double d = distanceP(approxCurve[1], approxCurve[2]);
double delta = 0.3;
double area = contourArea(contours[i]);
if (max(a, b) / min(a, b)-1 < delta && max(a, c) / min(a, c)-1 < delta
&& max(a, d) / min(a, d)-1 < delta && max(b, c) / min(b, c)-1 < delta
&& max(b, d) / min(b, d)-1 < delta && max(c, d) / min(c, d)-1 < delta
&& area>30) {//the area is square
areas.push_back(area);
resContours.push_back(contours[i]);

            }
        }
    }
    
}
drawContours(squaresContours, resContours, -1, Scalar(0, 0, 255));
imwrite("squaresContours.jpg", squaresContours);
//sort the areas
int temp;
for (int i = areas.size() - 1; i > 0; i--) {
    bool tableau_trie = true;
    for (int j = 0; j < i; j++) {
        if (areas[j + 1] < areas[j]) {
            temp = areas[j];
            areas[j] = areas[j + 1];
            areas[j + 1] = temp;
            tableau_trie = false;
        }
    }
    if (tableau_trie)
        break;
}
//take the median
int median = areas[areas.size() / 2];
cout << "black area median = " << median << endl;
//take the side of a square which is the number of pixels per millimeter
cout << "number of pixels per millimeter = " << sqrt(median) << endl;`Preformatted text`