2016-05-15 135 views
1

我有两个等值线向量OUTERCONT和INNERCONT在openCV中定义为向量(向量(点))。我想检查一个轮廓是否存在于另一个轮廓内。我还想知道,每个OUTERCONT内有多少轮廓。 我目前绘制minEnclosingRect每个轮廓周围和检查以下内容:搜索轮廓是否存在于另一个轮廓

for (int i = 0; i < outerrect.size(); i++) 
{ 
    count = 0; 
    for (int j = 0; j < innerrect.size(); j++) 
    { 
     bool is_inside = ((innerrect[j] & outerrect[i]) == innerrect[j]); 
     if (is_inside == 1) 
      count++; 

    } 
    if (count > 0) 
    { 
     //DO SOMETHING 
    } 
    cout << count << endl; 

这似乎并不奏效,它总是返回数为120左右一些号码,这​​是不对的。你能否建议进行任何更改以使其正确工作?

注:我不能使用层次结构,因为这些是从两个不同的函数返回的两个独立的轮廓集。

我知道PointPloygon测试是一个选项,但你能否提出更多的方法来做到这一点?

+0

为什么你不能使用轮廓层次结构?你能将所有的轮廓复制到一个单一的图像,并再次提取它们吗? – tfv

+0

@tfv谢谢!但是,我必须为我的应用程序保留两组轮廓线。 – Vin

+1

对于每个轮廓:在黑色图像(作为蒙版)上绘制它,然后为每个轮廓蒙板:if mask1 && mask2 == mask2然后mask2完全位于掩码1。也许不是最快的方法,但它应该工作。 – Micka

回答

1

下面是评论我的想法:

// stacked contours 
int main(int argc, char* argv[]) 
{ 
    cv::Mat input = cv::imread("C:/StackOverflow/Input/Contours_in_Contours.png"); 

    cv::Mat input_red = cv::imread("C:/StackOverflow/Input/Contours_in_Contours_RED.png"); 

    cv::Mat reds; 
    cv::inRange(input_red, cv::Scalar(0, 0, 200), cv::Scalar(50, 50, 255), reds); 
    std::vector<std::vector<cv::Point> > contours1; 
    cv::findContours(reds, contours1, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); 

    cv::Mat input_yellow = cv::imread("C:/StackOverflow/Input/Contours_in_Contours_YELLOW.png"); 

    cv::Mat yellows; 
    cv::inRange(input, cv::Scalar(0, 200, 200), cv::Scalar(0, 255, 255), yellows); 
    std::vector<std::vector<cv::Point> > contours2; 
    cv::findContours(yellows, contours2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); 

    // now we have 2 sets of contours and want to find out whether contours of set2 are completely within a contour of contours1 without hierarchy information. 

    std::vector<cv::Mat> masks1; 
    std::vector<int> nMaskPixels1; 
    // for each contour in contours1: create a contour mask: 
    for (int i = 0; i < contours1.size(); ++i) 
    { 
     cv::Mat mask1 = cv::Mat::zeros(input.size(), CV_8UC1); 
     cv::drawContours(mask1, contours1, i, cv::Scalar::all(255), -1); // draw filled 
     int nPixel1 = cv::countNonZero(mask1); 

     masks1.push_back(mask1); 
     nMaskPixels1.push_back(nPixel1); 
    } 

    std::vector<cv::Mat> masks2; 
    std::vector<int> nMaskPixels2; 
    // for each contour in contours2: test whether it is completely within the reference contour: 
    for (int j = 0; j < contours2.size(); ++j) 
    { 
     cv::Mat mask2 = cv::Mat::zeros(input.size(), CV_8UC1); 
     cv::drawContours(mask2, contours2, j, cv::Scalar::all(255), -1); // draw filled 
     int nPixel2 = cv::countNonZero(mask2); 

     masks2.push_back(mask2); 
     nMaskPixels2.push_back(nPixel2); 
    } 

    for (int i = 0; i < masks1.size(); ++i) 
    { 
     cv::Mat mask1 = masks1[i]; 

     // draw mask again for visualization: 
     cv::Mat outIm = input.clone(); 
     cv::drawContours(outIm, contours1, i, cv::Scalar(0, 0, 0), 3); 

     for (int j = 0; j < masks2.size(); ++j) 
     { 
      cv::Mat mask2 = masks2[j]; 

      cv::Mat overlap = mask1 & mask2; 
      int nOverlapPixels = cv::countNonZero(overlap); 
      if (nOverlapPixels == 0) continue; // no overlap at all. Test next contour. 

      if (nOverlapPixels == nMaskPixels2[j] && nOverlapPixels < nMaskPixels1[i]) 
      { 
       // second contour is completely within first contour 
       cv::drawContours(outIm, contours2, j, cv::Scalar(0, 255, 0), 3); 
      } 
      else if (nOverlapPixels == nMaskPixels2[j] && nOverlapPixels == nMaskPixels1[i]) 
      { 
       // both contours are identical 
       std::cout << "WARNING: " << "contours " << i << " and " << j << " are identical" << std::endl; 
      } 
      else if (nOverlapPixels < nMaskPixels2[j] && nOverlapPixels == nMaskPixels1[i]) 
      { 
       // first contour is completely within second contour 
       std::cout << "WARNING: " << "contour " << i << " of the first set is inside of " << j << std::endl; 
      } 
      else if (nOverlapPixels < nMaskPixels2[j] && nOverlapPixels < nMaskPixels1[i]) 
      { 
       // both contours intersect 
       cv::drawContours(outIm, contours2, j, cv::Scalar(255, 0, 255), 3); 
      } 

     } 

     cv::imshow("contours", outIm); 
     cv::imwrite("C:/StackOverflow/Output/contours.png", outIm); 
     cv::waitKey(0); 

    } 



    cv::imshow("input", input); 
    cv::waitKey(0); 
    return 0; 
} 

此代码将从这两个图像创建两套轮廓:

enter image description here

enter image description here

计算轮廓口罩和比较他们。

结果将按每个轮廓显示。黑色轮廓是参考,绿色是完全在参考内的那些,紫色是相交的轮廓。

我使用这个图像上绘制的结果:

enter image description here

得到这些结果:

contour1:

enter image description here

轮廓2:

enter image description here

contour3: enter image description here

contour4: enter image description here

contour5: enter image description here

正如你所看到的,孤独的黄色轮廓未检测到相交或包含在任何的那些红色轮廓。

+1

,我会在明天写一些代码谢谢@Micka!这真的很有帮助。 – Vin