10

我正在 iOS 中开发一些图像处理工具。目前,我计算了一个特征轮廓,其类型为 InputArrayOfArrays。

声明为:

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

现在,我想提取由轮廓圈出的原始 RGB 图片的区域,并可能进一步将子图像存储为 cv::Mat 格式。我怎样才能做到这一点?

提前致谢!

4

3 回答 3

25

我猜你想要做的只是提取检测到的轮廓中的区域。这是一个可能的解决方案:

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;
}

如果您想以支持透明度的格式(例如 png)保存子区域,您可能还需要考虑保存单个蒙版以选择性地用作 Alpha 通道。

注意:我没有为每个轮廓提取边界框中的所有像素,只提取轮廓内的像素。不在轮廓内但在边界框中的像素设置为 0。原因是您的 Mat 对象是一个数组,这使它成为矩形。

最后,我认为您没有任何理由将轮廓中的像素保存在专门创建的数据结构中,因为您需要存储每个像素的位置才能重新创建图像。如果您关心的是节省空间,那根本不会为您节省太多空间。保存最紧密的边界框就足够了。相反,如果您只想分析轮廓区域中的像素,则为每个轮廓保存一个掩码副本,以便您可以使用它来检查轮廓内的像素。

于 2012-04-17T06:54:35.333 回答
0

您正在寻找cv::approxPolyDP()连接点的功能。

我在这篇文章中分享了整个过程的类似用法。通话后检查for循环。findContours()

于 2012-04-16T14:48:52.513 回答
0

我认为您正在寻找的是 cv::boundingRect()。像这样的东西:

using namespace cv;
Mat img = ...;
...
vector<Mat> roiVector;
for(vector<vector<Point> >::iterator it=contours.begin(); it<contours.end(); it++) {
    if (boundingRect( (*it)).area()>minArea) {
        roiVector.push_back(img(boundingRect(*it)));
    }
}

cv::boundingRect() 接受一个点向量并返回一个 cv::Rect。初始化 Mat myRoi = img(myRect) 会为您提供指向图像该部分的指针(因此修改 myRoi 也会修改 img)。

在这里查看更多。

于 2012-04-17T06:32:12.273 回答