OpenCV 2.3:如何将每个轮廓的所有孔放入子向量中?

Posted

技术标签:

【中文标题】OpenCV 2.3:如何将每个轮廓的所有孔放入子向量中?【英文标题】:OpenCV 2.3: How to put all holes for each contour into subvector? 【发布时间】:2011-11-13 14:08:32 【问题描述】:

对于每个轮廓,我想将其孔放入单独的矢量中。默认情况下,在 OpenCV 2.* 中,我们有 2 个选项 - 使用 OpenCV 1.* 树结构并以 shown in this tutorial 的形式遍历它,让我们了解 vector<Vec4i>,这有点简化但与 OpenCV 1.0 类似的树结构依赖于std::vector< std::vector<Point> >,您可以从findContours 获得。当您需要了解继承时,树就很重要——“什么放在什么里面”。但通常你真的只需要一组区域和它的洞。 (用于矢量化和类似任务)。

目前我有这样的代码:

#include <opencv2/opencv.hpp>

using namespace cv;
int main(  )

    Mat black = Mat::zeros(Size(100, 100), CV_8UC1);
    for(int i = 0; i <= 35; ++i)
    
        for (int k = 0; k <=35; ++k)
        
            black.row(i).col(k) = 255;
        
    

    for(int i = 10; i <= 15; ++i)
    
        for (int k = 10; k <=15; ++k)
        
            black.row(i).col(k) = 0;
        
    

    for(int i = 25; i <= 30; ++i)
    
        for (int k = 25; k <=30; ++k)
        
            black.row(i).col(k) = 0;
        
    

    for(int i = 45; i <= 75; ++i)
    
        for (int k = 45; k <= 75; ++k)
        
            black.row(i).col(k) = 255;
        
    

    for(int i = 55; i <= 65; ++i)
    
        for (int k = 55; k <=65; ++k)
        
            black.row(i).col(k) = 0;
        
    

    for(int i = 57; i <= 62; ++i)
    
        for (int k = 57; k <=62; ++k)
        
            black.row(i).col(k) = 255;
        
    

    namedWindow("Display Image", CV_WINDOW_AUTOSIZE);
    imshow("Display Image", black);

    std::vector< std::vector<Point> > contours;
vector<Vec4i> hierarchy;
if(sum(black).val[0] > 0.0)

    findContours(black, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

else

    std::cout << "It's a black image, so I'm not going to do anything..." << std::endl;


for(int i = 0; i < contours.size(); ++i)

    std::cout << "counter " << i << ":" << std::endl;
    std::cout <<  hierarchy[i][0]  << " "  << hierarchy[i][1] << " " <<  hierarchy[i][2]  << hierarchy[i][3]  << std::endl;

    for (int k = 0; k < contours[i].size(); ++k)
    
        std::cout << "\t point " << k << " x: " << contours[i][k].x << "; y: " <<  contours[i][k].y << std::endl;
    


    waitKey(0);
    std::cin.get();
    return 0;

我想知道是否可以将 std::vector&lt; std::vector&lt;Point&gt; &gt; contours; 更改为 std::vector&lt; std::pair&lt;std::vector&lt;Point&gt;, std::vector&lt;std::vector&lt;Point&gt; &gt; &gt; contours; 之类的东西,其中 pair 由轮廓组成:其孔的向量。是否有可能以及如何使用 openCV 2.3 实现这样的事情?

更新:

我的意思是这样的(糟糕的,糟糕的 C 风格......)我创建的代码 sn-p:

struct vector_object

    std::vector<Point> border;
    std::vector< std::vector<Point> > holes;
;

std::vector<vector_object> container;

void store_vector_hole(std::vector< std::vector<Point> > &holes, std::vector< std::vector<Point> > & contours, std::vector<Vec4i> & hierarchy, const int & cid);
void store_vectror_countors(std::vector< std::vector<Point> > & contours, std::vector<Vec4i> & hierarchy, const int & cid);


void store_vector_hole(std::vector< std::vector<Point> > &holes, std::vector< std::vector<Point> > & contours, std::vector<Vec4i> & hierarchy, const int & cid)

    holes.push_back(contours[cid]);
    if (hierarchy[cid][2] >= 0) // holes in holes == real poligons
    
        store_vectror_countors( contours, hierarchy, hierarchy[cid][2]);
    
    if (hierarchy[cid][0] >= 0) // holes on same level of depth == another holes of this poligon
    
        store_vector_hole(holes, contours, hierarchy, hierarchy[cid][0]);
    
    return;


void store_vectror_countors(std::vector< std::vector<Point> > & contours, std::vector<Vec4i> & hierarchy, const int & cid)

    if (hierarchy[cid][0]>= 0)
        store_vectror_countors(contours, hierarchy, hierarchy[cid][0]);

    vector_object current;
    current.border = contours[cid];

    if ((hierarchy[cid][0]<= 0) && (hierarchy[cid][2] <= 0))
    
            container.push_back(current);
            return;
    

    if(hierarchy[cid][2] >= 0) // h
    
        store_vector_hole(current.holes, contours, hierarchy, hierarchy[cid][2]);
    

    container.push_back(current);
    return;


您通过以下方式激活:

//...
findContours(black, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
store_vectror_countors(contours, hierarchy, 0);

关于使它更健壮和 C++ish 的任何想法?

【问题讨论】:

【参考方案1】:

您是否尝试将它们提取为轮廓树?在 findContours 上使用 CV_RETR_TREE 标志,它应该会为您提供您想要的。

【讨论】:

你的意思是让std::map&lt; std::vector&lt;Point&gt;, std::vector&lt; std::vector&lt;Point&gt; &gt; &gt; contours; 打电话给findContours(black, contours, CV_RETR_TREE , CV_CHAIN_APPROX_SIMPLE);?这不会编译(error C2665: 'cv::findContours' : none of the 2 overloads could convert all the argument types std::vector&lt; std::pair&lt;std::vector&lt;Point&gt;, std::vector&lt; std::vector&lt;Point&gt; &gt; &gt; &gt; contours; + findContours(black, contours, CV_RETR_TREE , CV_CHAIN_APPROX_SIMPLE); 将在运行时与 OpenCV Error: Assertion failed (type == type0 || (CV_MAT_CN(type) == CV_MAT_CN(t ype0) &amp;&amp; ((1 &lt;&lt; type0) &amp; fixedDepthMask) != 0)) in unknown function, file D:\Pro jects\OpenCV-2.3.0\modules\core\src\matrix.cpp, line 1239 一起编译并死掉

以上是关于OpenCV 2.3:如何将每个轮廓的所有孔放入子向量中?的主要内容,如果未能解决你的问题,请参考以下文章

将图像放入轮廓(OpenCV)

如何从 cv2.findContours 结果中重新创建带有孔的原始图像?

Opencv项目实战目标检测:自动检测出现的所有动态目标

OpenCV 锐化边缘(没有孔的边缘)

OpenCV中如何获得物体的主要方向

如何在opencv中平滑图像中插入孔?