OpenCV中是否有任何函数可以找到两个cv::Rect
的交集,并集和补充?
我可以自己编写,但我希望OpenCV中有一些快速功能可以做到这一点。
搜索文档,没有任何功能。
正如一些人所解释的那样,对于rects没有联合和补充,所以我查看了可用的函数,我发现在我的情况下,我可以使用
rect = rect1 | rect2 (minimum area rectangle containing rect1 and rect2 )
而不是联盟。对于补充,我需要一个类似的函数,定义为:
rect=rect1 || rect2 (maximum area rectangle containing rect1 but not rect2 )
如下图所示:
rect1
为黄色,rect2
为红色,结果为蓝色。
编写此功能的最快方法是什么?
答案 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>(mask1
和mask2
必须具有相同的尺寸):
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,我提取了这个:
除了类成员之外,还实现了对矩形的以下操作:
答案 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是否相交。
这里有一些测试结果: