我有两个矩形a和b,它们的边与坐标系的轴平行。我已经知道它们的坐标为x1,y1,x2,y2。
我想要确定它们是否重叠以及它们重叠的程度。我想知道它们是否是相同的矩形,或者只是存在一些微小的差异。因此,我需要计算它们的面积是否相似,例如是否相似95%?
请帮助我计算它们重叠的百分比。
我有两个矩形a和b,它们的边与坐标系的轴平行。我已经知道它们的坐标为x1,y1,x2,y2。
我想要确定它们是否重叠以及它们重叠的程度。我想知道它们是否是相同的矩形,或者只是存在一些微小的差异。因此,我需要计算它们的面积是否相似,例如是否相似95%?
请帮助我计算它们重叠的百分比。
计算交集的面积,它也是一个矩形:
SI = Max(0, Min(XA2, XB2) - Max(XA1, XB1)) * Max(0, Min(YA2, YB2) - Max(YA1, YB1))
然后您可以计算联合部分的面积:
SU = SA + SB - SI
你可以考虑比率
SI / SU
(在完美重叠的情况下为100%,最低为0%)。
A
是矩形A,B
是矩形B;X
是X维度,Y
是Y维度;1
是(顶部或左侧)点,而2
是(底部或右侧)点。因此:XA2
是矩形A右边的X
值;XB2
是矩形B右边的X
值;XA1
是矩形A左边的X
值;XB1
是矩形B左边的X
值;YA2
是矩形A底部的Y
值;YB2
是矩形B底部的Y
值;YA1
是矩形A顶部的Y
值;YB1
是矩形B顶部的Y
值。最后,SI
是交集区域的面积。 - Dan Nissenbaumintersecting_area =
max(0,
min(orange.circle.x, blue.circle.x)
- max(orange.triangle.x, blue.triangle.x)
)
* max(0,
min(orange.circle.y, blue.circle.y)
- max(orange.triangle.y, blue.triangle.y)
)
percent_coverage = intersecting_area
/ (orange_area + blue_area - intersecting_area)
首先,我们可以用下列方式定义一个二维框:
如图所示:
我用三角形表示左上角,用圆圈表示右下角,以避免使用类似 x1, x2
这样的语法。
两个重叠的矩形可能会像这样:
注意要找到它们的重叠区域,需要寻找橙色和蓝色相交的地方:
一旦您认识到这一点,就很容易发现,覆盖区域是通过找到这两条暗线并将其相乘得到的:
每条线的长度都是两个圆形点的最小值减去两个三角形点的最大值。
在这里,我使用了双调三角形(和圆形)来表示橙色和蓝色点的比较。在两个双音符音符后面的小写字母 'y' 表示三角形沿 y 轴进行比较,小写字母 'x' 表示它们沿 x 轴进行比较。
例如,要找到暗蓝色线的长度,您可以看到三角形是通过比较寻找两个三角形之间的最大值来进行比较的。进行比较的属性是 x 属性。两个三角形之间的最大 x 值为 210。
还有一种说法:
适配于两条直线的新线段的长度是从该线段上最近的一侧的最远点减去与另一条线段距离最近的一侧的最近点。
找到这些线会提供关于重叠区域的完整信息。
一旦你有了这个,计算重叠百分比就很容易:
但是,如果橙色矩形与蓝色矩形没有重叠,那么你会遇到问题:
对于这个例子,您将为重叠区域得到-850,这肯定不对。更糟糕的是,如果检测不与任何维度重叠(不在x轴或y轴上),则仍将获得正数,因为两个维度都是负数。这就是为什么您在解决方案中看到Max(0, ...) * Max(0, ...)
的原因;它确保如果任何重叠是负数,则从函数中返回0。
符号体系保持不变的最终公式:
值得注意的是,使用max(0, ...)
函数可能并不是必要的。您可能想知道某个物体是否沿着其维度重叠而不是所有维度;如果使用max,那么您将销毁该信息。因此,请考虑如何处理非重叠边界框。通常,最大函数是可以使用的,但值得注意的是它正在做什么。
最后,请注意,由于此比较仅涉及线性测量,因此可以扩展到任意维度或任意重叠的四边形。
总结一下:
intersecting_area =
max(0,
min(orange.circle.x, blue.circle.x)
- max(orange.triangle.x, blue.triangle.x)
)
* max(0,
min(orange.circle.y, blue.circle.y)
- max(orange.triangle.y, blue.triangle.y)
)
percent_coverage = intersecting_area
/ (orange_area + blue_area - intersecting_area)
max(0, min(orange.circle.x, blue.circle.x) - max(orange.triangle.x, blue.triangle.x)) * max(0, min(orange.circle.y, blue.circle.y) - max(orange.triangle.y, blue.triangle.y))
,将其转化为数字,使得所有橙色三角形都比蓝色三角形大(但小于蓝色圆形),并且所有橙色圆形都比蓝色圆形小(但大于蓝色三角形)。请报告您的发现。 - Connormax(0, min(orange.circle.x, blue.circle.x, green.circle.x) - max(...
。 - Connor我最近也遇到了这个问题,并尝试使用 Yves 的答案,但是出现了错误的区域大小,因此我重写了它。
假设有两个矩形 A 和 B,请找出它们重叠的面积大小:
IF A.right < B.left OR A.left > B.right
OR A.bottom < B.top OR A.top > B.bottom THEN RETURN 0
width := IF A.right > B.right THEN B.right - A.left ELSE A.right - B.left
height := IF A.bottom > B.bottom THEN B.bottom - A.top ELSE A.bottom - B.top
RETURN width * height
使用Python来修正以前的答案,使比率在0和1之间:
# (x1,y1) top-left coord, (x2,y2) bottom-right coord, (w,h) size
A = {'x1': 0, 'y1': 0, 'x2': 99, 'y2': 99, 'w': 100, 'h': 100}
B = {'x1': 0, 'y1': 0, 'x2': 49, 'y2': 49, 'w': 50, 'h': 50}
# overlap between A and B
SA = A['w']*A['h']
SB = B['w']*B['h']
SI = np.max([ 0, 1 + np.min([A['x2'],B['x2']]) - np.max([A['x1'],B['x1']]) ]) * np.max([ 0, 1 + np.min([A['y2'],B['y2']]) - np.max([A['y1'],B['y1']]) ])
SU = SA + SB - SI
overlap_AB = float(SI) / float(SU)
print 'overlap between A and B: %f' % overlap_AB
# overlap between A and A
B = A
SB = B['w']*B['h']
SI = np.max([ 0, 1 + np.min([A['x2'],B['x2']]) - np.max([A['x1'],B['x1']]) ]) * np.max([ 0, 1 + np.min([A['y2'],B['y2']]) - np.max([A['y1'],B['y1']]) ])
SU = SA + SB - SI
overlap_AA = float(SI) / float(SU)
print 'overlap between A and A: %f' % overlap_AA
overlap between A and B: 0.250000
overlap between A and A: 1.000000
x
和y
轴平行,因为这似乎是之前的评论和答案所述的情况。a: (1,1), (4,4)
b: (2,2), (5,3)
bTop - bBottom
,因为b
的垂直部分完全包含在a
中。if aRight <= bLeft or bRight <= aLeft or aTop <= bBottom or bTop <= aBottom:
# There is no intersection in these cases
return 0
else:
# There is some intersection
if aRight >= bRight and aLeft <= bLeft:
# From x axis point of view, b is wholly contained in a
width = bRight - bLeft
elif bRight >= aRight and bLeft <= aLeft:
# From x axis point of view, a is wholly contained in b
width = aRight - aLeft
elif aRight >= bRight:
width = bRight - aLeft
else:
width = aRight - bLeft
if aTop >= bTop and aBottom <= bBottom:
# From y axis point of view, b is wholly contained in a
height = bTop - bBottom
elif bTop >= aTop and bBottom <= aBottom:
# From y axis point of view, a is wholly contained in b
height = aTop - aBottom
elif aTop >= bTop:
height = bTop - aBottom
else:
height = aTop - bBottom
return width * height
这是一个有效的C#函数示例:
public double calculateOverlapPercentage(Rectangle A, Rectangle B)
{
double result = 0.0;
//trivial cases
if (!A.IntersectsWith(B)) return 0.0;
if (A.X == B.X && A.Y == B.Y && A.Width == B.Width && A.Height == B.Height) return 100.0;
//# overlap between A and B
double SA = A.Width * A.Height;
double SB = B.Width * B.Height;
double SI = Math.Max(0, Math.Min(A.Right, B.Right) - Math.Max(A.Left, B.Left)) *
Math.Max(0, Math.Min(A.Bottom, B.Bottom) - Math.Max(A.Top, B.Top));
double SU = SA + SB - SI;
result = SI / SU; //ratio
result *= 100.0; //percentage
return result;
}
[ymin_a, xmin_a, ymax_a, xmax_a] = list(bbox_a)
[ymin_b, xmin_b, ymax_b, xmax_b] = list(bbox_b)
x_intersection = min(xmax_a, xmax_b) - max(xmin_a, xmin_b) + 1
y_intersection = min(ymax_a, ymax_b) - max(ymin_a, ymin_b) + 1
if x_intersection <= 0 or y_intersection <= 0:
return 0
else:
return x_intersection * y_intersection
@User3025064是正确的,也是最简单的解决方案,但首先必须检查不相交的矩形的排他性,例如对于矩形A和B(在Visual Basic中):
If A.Top =< B.Bottom or A.Bottom => B.Top or A.Right =< B.Left or A.Left => B.Right then
Exit sub 'No intersection
else
width = ABS(Min(XA2, XB2) - Max(XA1, XB1))
height = ABS(Min(YA2, YB2) - Max(YA1, YB1))
Area = width * height 'Total intersection area.
End if
XA1<XA2<XB1<XB2
。根据Yves的说法,交集的宽度为:
w = Max(0, Max(XA2, XB2) - Min(XA1, XB1)) = XB2-XA1
,这是一个大矩形,包含了两个矩形之间的间隙。
在固定的公式中,
w = Max(0, Min(XA2, XB2) - Max(XA1, XB1)) = Max(0, XA2-XB1) = 0
,因为 XA2<XB1,所以 XA2-XB1<0。
w=0
表示没有交集。 - Hazem