Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With OpenCV, try to extract a region of a picture described by ArrayOfArrays

I am developing some image processing tools in iOS. Currently, I have a contour of features computed, which is of type InputArrayOfArrays.

Declared as:

std::vector<std::vector<cv::Point> > contours_final( temp_contours.size() );

Now, I would like to extract areas of the original RGB picture circled by contours and may further store sub-image as cv::Mat format. How can I do that?

Thanks in advance!

like image 909
feng63600 Avatar asked Apr 16 '12 14:04

feng63600


People also ask

What format is the image read in using OpenCV?

OpenCV offers support for the image formats Windows bitmap (bmp), portable image formats (pbm, pgm, ppm) and Sun raster (sr, ras).

What is ROI in OpenCV?

To separate a particular portion from the image, we have to locate the area first. Then we have to copy that area from the main image to another matrix. This is how the ROI in OpenCV works. In this example, two matrices have been declared at the beginning.

What format is the image read in using OpenCV as an array in C++ and as a list in Python?

Reading and Displaying an image in OpenCV using C++ It loads the image in BGR format.


1 Answers

I'm guessing what you want to do is just extract the regions in the the detected contours. Here is a possible solution:

using namespace cv;

int main(void)
{
    vector<Mat> subregions;
    // contours_final is as given above in your code
    for (int i = 0; i < contours_final.size(); i++)
    {
        // Get bounding box for contour
        Rect roi = boundingRect(contours_final[i]); // This is a OpenCV function

        // Create a mask for each contour to mask out that region from image.
        Mat mask = Mat::zeros(image.size(), CV_8UC1);
        drawContours(mask, contours_final, i, Scalar(255), CV_FILLED); // This is a OpenCV function

        // At this point, mask has value of 255 for pixels within the contour and value of 0 for those not in contour.

        // Extract region using mask for region
        Mat contourRegion;
        Mat imageROI;
        image.copyTo(imageROI, mask); // 'image' is the image you used to compute the contours.
        contourRegion = imageROI(roi);
        // Mat maskROI = mask(roi); // Save this if you want a mask for pixels within the contour in contourRegion. 

        // Store contourRegion. contourRegion is a rectangular image the size of the bounding rect for the contour 
        // BUT only pixels within the contour is visible. All other pixels are set to (0,0,0).
        subregions.push_back(contourRegion);
    }

    return 0;
}

You might also want to consider saving the individual masks to optionally use as a alpha channel in case you want to save the subregions in a format that supports transparency (e.g. png).

NOTE: I'm NOT extracting ALL the pixels in the bounding box for each contour, just those within the contour. Pixels that are not within the contour but in the bounding box are set to 0. The reason is that your Mat object is an array and that makes it rectangular.

Lastly, I don't see any reason for you to just save the pixels in the contour in a specially created data structure because you would then need to store the position for each pixel in order to recreate the image. If your concern is saving space, that would not save you much space if at all. Saving the tightest bounding box would suffice. If instead you wish to just analyze the pixels in the contour region, then save a copy of the mask for each contour so that you can use it to check which pixels are within the contour.

like image 119
lightalchemist Avatar answered Oct 19 '22 04:10

lightalchemist