【问题标题】:Search if a contour exists inside another contour搜索一个轮廓是否存在于另一个轮廓内
【发布时间】:2016-09-11 09:55:55
【问题描述】:

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

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 左右的某个数字,这是不对的。您能否建议任何更改以使其正常工作?

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

我知道 PointPloygon 测试是一种选择,但您能建议更多的方法吗?

【问题讨论】:

  • 为什么不能使用轮廓层次结构?您能否将所有轮廓复制到一张图像中并再次提取它们?
  • @tfv 谢谢!但是,我必须为我的应用程序保持两组轮廓分开..
  • 对于每个轮廓:将其绘制在黑色图像上(作为遮罩)然后对于每个轮廓遮罩:如果遮罩1&&遮罩2 ==遮罩2则遮罩2完全在遮罩1内。也许不是最快的方法,但它应该可以工作。
  • @Micka 您能否进一步详细说明我该怎么做?如果我错了,请纠正我,你想让我在一个空白图像上绘制一个填充的 OUTER_CONTOUR,在另一张图像上绘制一个填充的 INNER_CONTOUR,然后比较两个图像 (image1 && image2)==image2?
  • 是的。如果我不忘记,我明天会写一些代码

标签: c++ opencv image-processing opencv-contour


【解决方案1】:

这是我来自 cmets 的想法:

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

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

计算轮廓掩码并进行比较。

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

我正在使用这张图片来绘制结果:

得到这些结果:

轮廓1:

轮廓2:

轮廓3:

轮廓4:

轮廓5:

如您所见,没有检测到孤独的黄色轮廓与任何红色轮廓相交或包含在任何红色轮廓中。

【讨论】:

  • 谢谢@Micka!这真的很有帮助。
猜你喜欢
  • 2012-07-12
  • 2014-07-12
  • 2020-11-24
  • 1970-01-01
  • 2019-12-24
  • 2018-04-30
  • 1970-01-01
  • 2021-09-07
  • 1970-01-01
相关资源
最近更新 更多