如果您使用屏幕(像素)坐标,投票率最高的答案会出现数学错误!几周前我提交了一份编辑,为所有读者提供了很长的解释,以便他们理解数学。但是那个编辑没有被审稿人理解并被删除,所以我再次提交了相同的编辑,但这次更简要地总结了。(更新:拒绝 2vs1,因为它被认为是“重大变化”,呵呵)。
所以我将在这个单独的答案中用它的数学来完全解释这个大问题。
所以,是的,一般来说,票数最高的答案是正确的,是计算 IoU 的好方法。但是(正如其他人也指出的那样)它的数学对于计算机屏幕是完全不正确的。你不能只做(x2 - x1) * (y2 - y1)
,因为这不会产生正确的面积计算。屏幕索引从像素开始,0,0
到width-1,height-1
. 屏幕坐标的范围是inclusive:inclusive
(包括两端),所以像素坐标的范围 from 0
to10
实际上是 11 个像素宽,因为它包括0 1 2 3 4 5 6 7 8 9 10
(11 个项目)。因此,要计算屏幕坐标的面积,您必须因此在每个维度上加上 +1,如下所示(x2 - x1 + 1) * (y2 - y1 + 1)
:
inclusive:exclusive
如果您在范围不包含在内的其他坐标系0
中工作(例如10
表示“元素 0-9 但不是 10”的系统),则不需要额外的数学运算。但最有可能的是,您正在处理基于像素的边界框。好吧,屏幕坐标从那里开始0,0
并从那里上升。
屏幕1920x1080
的索引从0
(第一个像素)到1919
(水平的最后一个像素)和从0
(第一个像素)到1079
(垂直的最后一个像素)。
因此,如果我们在“像素坐标空间”中有一个矩形,要计算它的面积,我们必须在每个方向上加 1。否则,我们得到面积计算的错误答案。
想象一下,我们的1920x1080
屏幕有一个基于像素坐标的矩形left=0,top=0,right=1919,bottom=1079
(覆盖整个屏幕上的所有像素)。
好吧,我们知道1920x1080
像素就是2073600
像素,这是1080p屏幕的正确区域。
但是如果数学错误area = (x_right - x_left) * (y_bottom - y_top)
,我们会得到:(1919 - 0) * (1079 - 0)
= 1919 * 1079
=2070601
像素!那是错误的!
这就是为什么我们必须添加+1
到每个计算中,这给了我们以下更正的数学:area = (x_right - x_left + 1) * (y_bottom - y_top + 1)
,给我们:(1919 - 0 + 1) * (1079 - 0 + 1)
= 1920 * 1080
=2073600
像素!这确实是正确的答案!
最简短的总结是:像素坐标范围是inclusive:inclusive
,所以如果我们想要像素坐标范围的真实区域,我们必须添加+ 1
到每个轴。
有关为什么+1
需要的更多详细信息,请参阅 Jindil 的回答:https ://stackoverflow.com/a/51730512/8874388
以及这篇 pyimagesearch 文章:
https ://www.pyimagesearch.com/2016/11/07/intersection-over-union-iou-for-object-detection/
而这个 GitHub 评论:
https ://github.com/AlexeyAB/darknet/issues/3995#issuecomment-535697357
由于固定数学没有被批准,任何从投票最多的答案复制代码的人都希望看到这个答案,并且能够自己修复它,只需复制下面的错误修复断言和面积计算行,它们已经固定inclusive:inclusive
(像素)坐标范围:
assert bb1['x1'] <= bb1['x2']
assert bb1['y1'] <= bb1['y2']
assert bb2['x1'] <= bb2['x2']
assert bb2['y1'] <= bb2['y2']
................................................
# The intersection of two axis-aligned bounding boxes is always an
# axis-aligned bounding box.
# NOTE: We MUST ALWAYS add +1 to calculate area when working in
# screen coordinates, since 0,0 is the top left pixel, and w-1,h-1
# is the bottom right pixel. If we DON'T add +1, the result is wrong.
intersection_area = (x_right - x_left + 1) * (y_bottom - y_top + 1)
# compute the area of both AABBs
bb1_area = (bb1['x2'] - bb1['x1'] + 1) * (bb1['y2'] - bb1['y1'] + 1)
bb2_area = (bb2['x2'] - bb2['x1'] + 1) * (bb2['y2'] - bb2['y1'] + 1)