Domanda

I'm trying to divide an image into a grid, and save the individual pieces. At the moment I loop through the piece number and get a sub-image, which I then save.

Can someone explain how to get the sub-images properly? I've been following similar posts on stackoverflow, but my code keeps failing an assertion which checks the bounds of the sub-image vs. the original.

int unitWidth = image.rows / n;
int unitHeight = image.cols / n;
for(int i=0; i<n; i++) {
    //Take the next tile in the nxn grid. Unit is the width and height of
    //each tile. i%n and i/n are just fancy ways of a double x,y for loop
    Mat subImage = image(Rect((i % n) * unitWidth, (i / n) * unitHeight, unitWidth,unitHeight));

    ostringstream oss;
    oss << i << "_" << n << ".jpg";
    string name = oss.str();
    imwrite(name, subImage);
}

p.s. the first subimage doesn't break the program, but the second does (for a 2x2 grid, so an end piece). I've shortening the sub-image by 10, but that still broke the machine.

È stato utile?

Soluzione

Below is your code fixed so that it breaks the image into nxn tiles.

Firstly you calculation of unitWidth and unitHeight is incorrect, and that is the cause of the assertion failure. It should be:

int unitWidth = image.cols / n;  // you had image.rows / n;
int unitHeight = image.rows / n; //  "   "  image.cols / n;

Furthermore, if you want an nxn tiling, you need to loop n^2 times, not just n times. THe easiest way to do this is to just have two loops, one inside the other, one loping n times for the rows and the other looping n times for the columns.

for(int i = 0; i < n; i++) {  //i is row index
    // inner loop added so that more than one row of tiles written
    for(int j = 0; j < n; j++) { // j is col index
        //Take the next tile in the nxn grid. Unit is the width and height of
        //each tile. i%n and i/n are just fancy ways of a double x,y for loop

        // Mat subImage = image(Rect((i % n) * unitWidth, (i / n) * unitHeight, unitWidth, unitHeight));
        // I didn't understand the above line, as ((i % n)==i and (i / n)==0.
        // 
        Mat subImage = image(Rect(j * unitWidth, i * unitHeight, unitWidth, unitHeight));

        ostringstream oss;
        oss << i << "_" << j << ".jpg";
        string name = oss.str();
        imwrite(name, subImage);
    }
}

The easiest way to debug code like this is to make the Rect a separate object so that you can print out its x,y,width,height and check them against the OpenCV assertion message. Have you compile your code in debug mode?

        cv::Rect roi(j * unitWidth, i * unitHeight, unitWidth, unitHeight);
        cout << "(i, j) = (" << i << ", " << j << ")" << endl;
        cout << "(i %n) = " << i%n  << endl;
        cout << "(i/n) = " << i/n << endl;
        cout << "roi.x = " << roi.x << endl;
        cout << "roi.y = " << roi.y << endl;
        cout << "roi.width = " << roi.width << endl;
        cout << "roi.height = " << roi.height << endl;
        Mat subImage = image(roi);

Altri suggerimenti

for(int i = 0; i < n-unitHeight; i++) {  
    for(int j = 0; j < n-unitWidth; j++) {
        ...........
        ...........
        ...........
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top