C++ 使用OpenCV,尝试提取由ArrayOfarray描述的图片区域

C++ 使用OpenCV,尝试提取由ArrayOfarray描述的图片区域,c++,opencv,contour,C++,Opencv,Contour,我正在用iOS开发一些图像处理工具。目前,我已经计算了一个特征轮廓,它是InputArrayOfArrays类型 声明为: std::vector<std::vector<cv::Point> > contours_final( temp_contours.size() ); std::vector contours_final(temp_contours.size()); 现在,我想提取由轮廓环绕的原始RGB图片的区域,并可能进一步将子图像存储为cv::Mat格式。

我正在用iOS开发一些图像处理工具。目前,我已经计算了一个特征轮廓,它是InputArrayOfArrays类型

声明为:

std::vector<std::vector<cv::Point> > contours_final( temp_contours.size() );
std::vector contours_final(temp_contours.size());
现在,我想提取由轮廓环绕的原始RGB图片的区域,并可能进一步将子图像存储为cv::Mat格式。我该怎么做


提前谢谢

您正在寻找连接点的
cv::approxPolyDP()
函数


我在中分享了对整个过程的类似使用。在调用
findContours()
之后,检查
中的
循环。

我认为您要查找的是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;
Mat img=。。。;
...
向量向量;
对于(vector::iterator it=contours.begin();itminArea){
roiVector.push_back(img(boundingRect(*it));
}
}
cv::boundingRect()获取点向量并返回cv::Rect。初始化Mat myRoi=img(myRect)会给您一个指向该图像部分的指针(因此修改myRoi也会修改img)


查看更多信息。

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

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;
}
使用名称空间cv;
内部主(空)
{
矢量次区域;
//您的代码如上所述
对于(int i=0;i

您可能还想考虑保存单独的掩码以供选择使用alpha通道,如果您想以支持透明度的格式保存子区域(例如PNG)。 注意:我没有为每个轮廓提取边界框中的所有像素,只是提取轮廓内的像素。不在轮廓内但在边界框中的像素设置为0。原因是Mat对象是一个数组,这使其成为矩形


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

感谢您的快速响应。但我这里所说的“contours_final”实际上是cv::approxPolyDP()的返回值,很抱歉不清楚。我认为另一种解决问题的方法是如何将最终的_轮廓设置为ROI,这样我就可以在原始图像上获得区域。我不是实时做的。只是一个静态图像。再次感谢!我试图制作eclipse的遮罩,但当我制作其对象时,该函数显示错误,如
椭圆常数遮罩(img,点(20,40),大小(60,40),0,0360,标量(0,0,0))嗨,谢谢你的代码。这个解决方案使用boundingRect函数提取矩形区域,对吗?有没有办法只存储轮廓内的区域?另外,我在将向量转换回cvMat时遇到了一些问题。。看看这个?谢谢。我已经编辑了我的答案。此外,可以将向量子区域中的Mat对象转换为CvMat,如下所示:CvMat m=子区域[i];这个函数返回一个矩形区域,对吗?请参考我的上述评论,并给我更多建议;)