В ответе, получившем наибольшее количество голосов, есть математическая ошибка, если вы работаете с координатами экрана (пикселей)! Несколько недель назад я отправил правку с подробным объяснением для всех читателей, чтобы они поняли математику. Но это изменение не было понято рецензентами и было удалено, поэтому я снова отправил то же изменение, но на этот раз более кратко. (Обновление: Отклонено 2 на 1, потому что это было сочтено «существенным изменением», хех).
Поэтому я полностью объясню БОЛЬШУЮ проблему с ее математикой здесь, в этом отдельном ответе.
Итак, да, в общем, ответ, получивший наибольшее количество голосов, является правильным и является хорошим способом расчета IoU. Но (как указывали и другие люди) его математика совершенно неверна для экранов компьютеров. Вы не можете просто сделать (x2 - x1) * (y2 - y1)
, так как это вообще не приведет к правильному вычислению площади. Индексация экрана начинается с пикселя 0,0
и заканчивается width-1,height-1
. Диапазон экранных координат inclusive:inclusive
(включительно с обоих концов), поэтому диапазон от 0
до 10
в пиксельных координатах на самом деле имеет ширину 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
, см. В ответе Джиндиля: 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)
person
Mitch McMabers
schedule
26.09.2019