2016-05-15 43 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