OpenCV中是否有任何函数可以找到两个cv :: Rect的交集,并集和补充

时间:2015-05-28 12:52:39

标签: c++ opencv

OpenCV中是否有任何函数可以找到两个cv::Rect的交集,并集和补充?

我可以自己编写,但我希望OpenCV中有一些快速功能可以做到这一点。

搜索文档,没有任何功能。

编辑1

正如一些人所解释的那样,对于rects没有联合和补充,所以我查看了可用的函数,我发现在我的情况下,我可以使用

rect = rect1 | rect2 (minimum area rectangle containing rect1 and rect2 )

而不是联盟。对于补充,我需要一个类似的函数,定义为:

 rect=rect1 || rect2 (maximum area rectangle containing rect1 but not rect2 )

如下图所示:

enter image description here enter image description here

rect1为黄色,rect2为红色,结果为蓝色。

编写此功能的最快方法是什么?

4 个答案:

答案 0 :(得分:9)

来自OpenCV doc:

In addition to the class members, the following operations on rectangles are implemented:

rect = rect +/- point (shifting a rectangle by a certain offset)
rect = rect +/- size (expanding or shrinking a rectangle by a certain amount)

rect += point, rect -= point, rect += size, rect -= size (augmenting operations)
rect = rect1 & rect2 (rectangle intersection)
rect = rect1 | rect2 (minimum area rectangle containing rect2 and rect3 )
rect &= rect1, rect |= rect1 (and the corresponding augmenting operations)
rect == rect1, rect != rect1 (rectangle comparison)

这些只覆盖总是导致另一个rect的运算符,所以补码不在这里。你必须在那里使用面具......

既然你要求补充和联合,我不确定cv::Rect是否适合使用。也许面具更适合满足您的需求。

CV_8UC1个屏蔽的{p>(mask1mask2必须具有相同的尺寸):

union = mask1+mask2
complement = 255-mask 
intersection = mask1.mul(mask2)

要从cv::Rect创建遮罩,您可以执行以下操作:

cv::Mat mask = cv::Mat(yourImage.size(), CV_8UC1, cv::Scalar(0)); // creates an empty mask of your image size
cv::rectangle(mask, yourRect, cv::Scalar(255), -1);

但请记住,cv::Rect在内存消耗和计算速度方面都更有效率。

因此,如果您可以将问题重新表述为仅使用矩形ROI(因此无法补充),我会以这种方式使用它而不是使用掩码!

答案 1 :(得分:5)

C ++方式(cv :: Rect),你可以很容易地说

interesect  = r1 & r2;

Refer to this link。所有操作都在文档中给出。

// In addition to the class members, the following operations 
// on rectangles are implemented:

// (shifting a rectangle by a certain offset)
// (expanding or shrinking a rectangle by a certain amount)
rect += point, rect -= point, rect += size, rect -= size (augmenting operations)
rect = rect1 & rect2 (rectangle intersection)
rect = rect1 | rect2 (minimum area rectangle containing rect2 and rect3 )
rect &= rect1, rect |= rect1 (and the corresponding augmenting operations)
rect == rect1, rect != rect1 (rectangle comparison)

答案 2 :(得分:4)

好吧,我不确定这是否能解决你的问题(我想是的),但是从CV documentation,我提取了这个:

除了类成员之外,还实现了对矩形的以下操作:

  • rect + = point,rect - = point,rect + = size,rect - = size(augmenting 运营)
  • rect = rect1& rect2 (矩形交叉点)
  • rect = rect1 | rect2 (包含rect2和rect3的最小区域矩形)
  • rect& = rect1,rect | = rect1(以及相应的扩充 操作)rect == rect1,rect!= rect1(矩形比较)

答案 3 :(得分:1)

对于complement的定义,您可以使用此功能:

cv::Rect RectWithoutRect(cv::Rect r1, cv::Rect r2)
{
    // 32 bit integer values:
    int minVal = -2147483648;
    int maxVal =  2147483647;

    // rectangles that define the space left, right, top and bottom of r2
    cv::Rect leftOf  = cv::Rect(cv::Point(minVal, minVal), cv::Point(r2.x, maxVal)); // rect covering the whole area left of r2
    cv::Rect topOf   = cv::Rect(cv::Point(minVal, minVal), cv::Point(maxVal, r2.y)); // rect covering the whole area top of r2
    cv::Rect rightOf = cv::Rect(cv::Point(r2.x+r2.width, minVal), cv::Point(maxVal, maxVal)); // rect covering the whole area left of r2
    cv::Rect bottomOf= cv::Rect(cv::Point(minVal, r2.y+r2.height), cv::Point(maxVal,maxVal)); // rect covering the whole area top of r2

    // intersect the spaces with r1 to find regions of r1 that lie left, right, top and bottom of r2
    cv::Rect allExterior[4];
    allExterior[0] = leftOf;
    allExterior[1] = topOf;
    allExterior[2] = rightOf;
    allExterior[3] = bottomOf;

    // now choose the biggest one
    int biggestSize = 0;
    cv::Rect biggestRect(0,0,0,0);

    for(unsigned int i=0; i<4; ++i)
    {
        cv::Rect intersection = allExterior[i] & r1;
        int size = intersection.width * intersection.height ;
        if(size > biggestSize)
        {
            biggestSize = size;
            biggestRect = intersection;
        }
    }

    return biggestRect;
}

使用一个很小的测试程序:

int main()
{
    cv::Mat output = cv::Mat(512,512,CV_8UC3,cv::Scalar(255,255,255));


    cv::Rect r1 = cv::Rect(128,128,256,256);

    //cv::Rect r2 = cv::Rect(300,299, 128,128);
    cv::Rect r2 = cv::Rect(150,140, 50,50);

    cv::Rect intersection = r1 & r2;

    cv::rectangle(output, r1, cv::Scalar(0,255,255),-1);
    cv::rectangle(output, r2, cv::Scalar(0,0,255),-1);

    //cv::rectangle(output, intersection, cv::Scalar(255,0,0),-1);

    cv::Rect rWithoutR = RectWithoutRect(r1, r2);
    cv::rectangle(output, rWithoutR, cv::Scalar(255,0,0),-1);


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

如果您愿意,可以轻松修改RectWithoutRect函数以返回“所有最大值”的向量。

PS:忘记在函数返回后检查矩形的大小,以确定是否返回合法的矩形。

为了提高性能,您可以在调用函数之前优化代码和/或测试r1和r2是否相交。

这里有一些测试结果:

enter image description here

enter image description here

enter image description here

enter image description here