analytics: Move IoU calculation to gstanalytics lib
Calculating intersection-of-union (IoU) is a very common operation used by tensor-decoder handling tensors from vision models. Having this in a library will improve maintainability and ease of writing tensor-decoder. - Post-fix _uint: We might eventually want to handle different datatype that we woule post-fix with _type Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8805>
This commit is contained in:
parent
4c4e80d286
commit
e887b2e20e
@ -1724,6 +1724,94 @@ desired to track an object across many frames. This type of metadata holds
|
||||
information about the tracking, for example, it can be used alongside a
|
||||
#GstAnalyticsODMtd to track an object.</doc>
|
||||
</docsection>
|
||||
<function name="image_util_iou_float" c:identifier="gst_analytics_image_util_iou_float" version="1.28">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Calculate the intersection over the union (IoU) of the two areas defined by
|
||||
the bounding box 1 and bounding box 2. IoU is a measure of how much two
|
||||
regions overlap.</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">IoU of bb1 and bb2.</doc>
|
||||
<type name="gfloat" c:type="gfloat"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<parameter name="bb1_x" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 1, X coordinate</doc>
|
||||
<type name="gfloat" c:type="gfloat"/>
|
||||
</parameter>
|
||||
<parameter name="bb1_y" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 1, Y coordinate</doc>
|
||||
<type name="gfloat" c:type="gfloat"/>
|
||||
</parameter>
|
||||
<parameter name="bb1_w" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 1, width</doc>
|
||||
<type name="gfloat" c:type="gfloat"/>
|
||||
</parameter>
|
||||
<parameter name="bb1_h" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 1, height</doc>
|
||||
<type name="gfloat" c:type="gfloat"/>
|
||||
</parameter>
|
||||
<parameter name="bb2_x" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 2, X coordinate</doc>
|
||||
<type name="gfloat" c:type="gfloat"/>
|
||||
</parameter>
|
||||
<parameter name="bb2_y" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 2, Y coordinate</doc>
|
||||
<type name="gfloat" c:type="gfloat"/>
|
||||
</parameter>
|
||||
<parameter name="bb2_w" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 2, width</doc>
|
||||
<type name="gfloat" c:type="gfloat"/>
|
||||
</parameter>
|
||||
<parameter name="bb2_h" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 2, height</doc>
|
||||
<type name="gfloat" c:type="gfloat"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</function>
|
||||
<function name="image_util_iou_int" c:identifier="gst_analytics_image_util_iou_int" version="1.28">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Calculate the intersection over the union (IoU) of the two areas defined by
|
||||
the bounding box 1 and bounding box 2. IoU is a measure of how much two
|
||||
regions overlap.</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">IoU of bb1 and bb2.</doc>
|
||||
<type name="gfloat" c:type="gfloat"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<parameter name="bb1_x" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 1, X coordinate</doc>
|
||||
<type name="gint" c:type="gint"/>
|
||||
</parameter>
|
||||
<parameter name="bb1_y" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 1, Y coordinate</doc>
|
||||
<type name="gint" c:type="gint"/>
|
||||
</parameter>
|
||||
<parameter name="bb1_w" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 1, width</doc>
|
||||
<type name="gint" c:type="gint"/>
|
||||
</parameter>
|
||||
<parameter name="bb1_h" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 1, height</doc>
|
||||
<type name="gint" c:type="gint"/>
|
||||
</parameter>
|
||||
<parameter name="bb2_x" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 2, X coordinate</doc>
|
||||
<type name="gint" c:type="gint"/>
|
||||
</parameter>
|
||||
<parameter name="bb2_y" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 2, Y coordinate</doc>
|
||||
<type name="gint" c:type="gint"/>
|
||||
</parameter>
|
||||
<parameter name="bb2_w" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 2, width</doc>
|
||||
<type name="gint" c:type="gint"/>
|
||||
</parameter>
|
||||
<parameter name="bb2_h" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalytics_image_util.c">Bounding box 2, height</doc>
|
||||
<type name="gint" c:type="gint"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</function>
|
||||
<function name="mtd_type_get_name" c:identifier="gst_analytics_mtd_type_get_name" moved-to="Mtd.type_get_name" version="1.24">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalyticsmeta.c">Gets the string version of the name of this type of analytics data</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/analytics/gstanalyticsmeta.h"/>
|
||||
|
@ -32,5 +32,6 @@
|
||||
#include <gst/analytics/gstanalyticsobjecttrackingmtd.h>
|
||||
#include <gst/analytics/gstanalyticssegmentationmtd.h>
|
||||
#include <gst/analytics/gsttensormeta.h>
|
||||
#include <gst/analytics/gstanalytics_image_util.h>
|
||||
|
||||
#endif /* __ANALYTICS_H__ */
|
||||
|
@ -0,0 +1,226 @@
|
||||
/* GStreamer
|
||||
* Copyright (C) 2025 Collabora Ltd
|
||||
* @author: Daniel Morin <daniel.morin@dmohub.org>
|
||||
*
|
||||
* gstanalytics_image_util.c
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "gstanalytics_image_util.h"
|
||||
|
||||
/* Evaluate if there's an intersection between segement s1 and s2 */
|
||||
static guint
|
||||
linear_intersection_uint (guint s1_min, guint s1_max, guint s2_min,
|
||||
guint s2_max)
|
||||
{
|
||||
guint tmp;
|
||||
if (s1_max > s2_min && s2_max > s1_min) {
|
||||
if (s1_min > s2_min) {
|
||||
tmp = (s2_max > s1_max) ? s1_max : s2_max;
|
||||
return tmp - s1_min;
|
||||
} else {
|
||||
tmp = (s1_max > s2_max) ? s2_max : s1_max;
|
||||
return tmp - s2_min;
|
||||
}
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
static gfloat
|
||||
linear_intersection_float (gfloat s1_min, gfloat s1_max, gfloat s2_min,
|
||||
gfloat s2_max)
|
||||
{
|
||||
gfloat tmp;
|
||||
if (s1_max > s2_min && s2_max > s1_min) {
|
||||
if (s1_min > s2_min) {
|
||||
tmp = (s2_max > s1_max) ? s1_max : s2_max;
|
||||
return tmp - s1_min;
|
||||
} else {
|
||||
tmp = (s1_max > s2_max) ? s2_max : s1_max;
|
||||
return tmp - s2_min;
|
||||
}
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
_clips_and_adj_dim_int (gint * xy, gint * wh)
|
||||
{
|
||||
g_return_val_if_fail (xy != NULL, FALSE);
|
||||
g_return_val_if_fail (wh != NULL, FALSE);
|
||||
|
||||
if (*xy < 0) {
|
||||
if ((*xy + *wh) < 0) {
|
||||
/* Bouding box completly outside the visible area */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* reduce width by the portion that is negative */
|
||||
*wh += *xy;
|
||||
*xy = 0;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_clips_and_adj_dim_float (gfloat * xy, gfloat * wh)
|
||||
{
|
||||
g_return_val_if_fail (xy != NULL, FALSE);
|
||||
g_return_val_if_fail (wh != NULL, FALSE);
|
||||
|
||||
if (*xy < 0.0f) {
|
||||
if ((*xy + *wh) < 0.0f) {
|
||||
/* Bouding box completly outside the visible area */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* reduce width by the portion that is negative */
|
||||
*wh += *xy;
|
||||
*xy = 0.0;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_analytics_image_util_iou_int:
|
||||
* @bb1_x: Bounding box 1, X coordinate
|
||||
* @bb1_y: Bounding box 1, Y coordinate
|
||||
* @bb1_w: Bounding box 1, width
|
||||
* @bb1_h: Bounding box 1, height
|
||||
* @bb2_x: Bounding box 2, X coordinate
|
||||
* @bb2_y: Bounding box 2, Y coordinate
|
||||
* @bb2_w: Bounding box 2, width
|
||||
* @bb2_h: Bounding box 2, height
|
||||
*
|
||||
* Calculate the intersection over the union (IoU) of the two areas defined by
|
||||
* the bounding box 1 and bounding box 2. IoU is a measure of how much two
|
||||
* regions overlap.
|
||||
*
|
||||
* Return: IoU of bb1 and bb2.
|
||||
*
|
||||
* Since: 1.28
|
||||
*/
|
||||
gfloat
|
||||
gst_analytics_image_util_iou_int (gint bb1_x, gint bb1_y, gint bb1_w,
|
||||
gint bb1_h, gint bb2_x, gint bb2_y, gint bb2_w, gint bb2_h)
|
||||
{
|
||||
if (_clips_and_adj_dim_int (&bb1_x, &bb1_w) == FALSE) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (_clips_and_adj_dim_int (&bb1_y, &bb1_h) == FALSE) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (_clips_and_adj_dim_int (&bb2_x, &bb2_w) == FALSE) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (_clips_and_adj_dim_int (&bb2_y, &bb2_h) == FALSE) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/* Rational: linear intersection is much faster to calculate then
|
||||
* 2d intersection. We project the two bounding boxes considered for
|
||||
* intersection on one axis and verify if the segments the create intersect.
|
||||
* If they don't, the bounding boxes can't intersect in 2d and we don't
|
||||
* need to verify if they intersect on the other dimension. If they
|
||||
* intersect on the first dimension we verify if they intersec on the other
|
||||
* dimension. Again if the don't intersect the bounding boxes can't intersect
|
||||
* on in a 2D space. If they intersected on both axis we calculate the IoU.*/
|
||||
const guint x_intersection =
|
||||
linear_intersection_uint (bb1_x, bb1_x + bb1_w, bb2_x, bb2_x + bb2_w);
|
||||
if (x_intersection > 0) {
|
||||
const guint y_intersection = linear_intersection_uint (bb1_y, bb1_y + bb1_h,
|
||||
bb2_y, bb2_y + bb2_h);
|
||||
if (y_intersection > 0) {
|
||||
const guint bb1_area = bb1_w * bb1_h;
|
||||
const guint bb2_area = bb2_w * bb2_h;
|
||||
const guint intersect_area = x_intersection * y_intersection;
|
||||
const guint union_area = bb1_area + bb2_area - intersect_area;
|
||||
return union_area == 0 ? 0.0f : ((gfloat) intersect_area) / union_area;
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_analytics_image_util_iou_float:
|
||||
* @bb1_x: Bounding box 1, X coordinate
|
||||
* @bb1_y: Bounding box 1, Y coordinate
|
||||
* @bb1_w: Bounding box 1, width
|
||||
* @bb1_h: Bounding box 1, height
|
||||
* @bb2_x: Bounding box 2, X coordinate
|
||||
* @bb2_y: Bounding box 2, Y coordinate
|
||||
* @bb2_w: Bounding box 2, width
|
||||
* @bb2_h: Bounding box 2, height
|
||||
*
|
||||
* Calculate the intersection over the union (IoU) of the two areas defined by
|
||||
* the bounding box 1 and bounding box 2. IoU is a measure of how much two
|
||||
* regions overlap.
|
||||
*
|
||||
* Return: IoU of bb1 and bb2.
|
||||
*
|
||||
* Since: 1.28
|
||||
*/
|
||||
gfloat
|
||||
gst_analytics_image_util_iou_float (gfloat bb1_x, gfloat bb1_y, gfloat bb1_w,
|
||||
gfloat bb1_h, gfloat bb2_x, gfloat bb2_y, gfloat bb2_w, gfloat bb2_h)
|
||||
{
|
||||
if (_clips_and_adj_dim_float (&bb1_x, &bb1_w) == FALSE) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (_clips_and_adj_dim_float (&bb1_y, &bb1_h) == FALSE) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (_clips_and_adj_dim_float (&bb2_x, &bb2_w) == FALSE) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (_clips_and_adj_dim_float (&bb2_y, &bb2_h) == FALSE) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/* Rational: linear intersection is much faster to calculate then
|
||||
* 2d intersection. We project the two bounding boxes considered for
|
||||
* intersection on one axis and verify if the segments the create intersect.
|
||||
* If they don't, the bounding boxes can't intersect in 2d and we don't
|
||||
* need to verify if they intersect on the other dimension. If they
|
||||
* intersect on the first dimension we verify if they intersec on the other
|
||||
* dimension. Again if the don't intersect the bounding boxes can't intersect
|
||||
* on in a 2D space. If they intersected on both axis we calculate the IoU.*/
|
||||
const gfloat x_intersection =
|
||||
linear_intersection_float (bb1_x, bb1_x + bb1_w, bb2_x, bb2_x + bb2_w);
|
||||
if (x_intersection > 0) {
|
||||
const float y_intersection =
|
||||
linear_intersection_float (bb1_y, bb1_y + bb1_h,
|
||||
bb2_y, bb2_y + bb2_h);
|
||||
if (y_intersection > 0) {
|
||||
const gfloat bb1_area = bb1_w * bb1_h;
|
||||
const gfloat bb2_area = bb2_w * bb2_h;
|
||||
const gfloat intersect_area = x_intersection * y_intersection;
|
||||
const gfloat union_area = bb1_area + bb2_area - intersect_area;
|
||||
return union_area == 0.0f ? 0.0f : intersect_area / union_area;
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/* GStreamer
|
||||
* Copyright (C) 2025 Collabora Ltd
|
||||
* @author: Daniel Morin <daniel.morin@dmohub.org>
|
||||
*
|
||||
* gstanalyticssegmentationmtd.h
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_ANALYTICS_IMAGE_UTIL_H__
|
||||
#define __GST_ANALYTICS_IMAGE_UTIL_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/analytics/analytics-meta-prelude.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GST_ANALYTICS_META_API
|
||||
gfloat gst_analytics_image_util_iou_int (gint bb1_x, gint bb1_y, gint bb1_w,
|
||||
gint bb1_h, gint bb2_x, gint bb2_y, gint bb2_w, gint bb2_h);
|
||||
|
||||
GST_ANALYTICS_META_API
|
||||
gfloat gst_analytics_image_util_iou_float (gfloat bb1_x, gfloat bb1_y, gfloat
|
||||
bb1_w, gfloat bb1_h, gfloat bb2_x, gfloat bb2_y, gfloat bb2_w, gfloat
|
||||
bb2_h);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_ANALYTICS_IMAGE_UTIL_H__ */
|
@ -4,7 +4,8 @@ analytics_sources = files( 'gstanalyticsmeta.c',
|
||||
'gstanalyticsobjecttrackingmtd.c',
|
||||
'gstanalyticssegmentationmtd.c',
|
||||
'gsttensormeta.c',
|
||||
'gsttensor.c')
|
||||
'gsttensor.c',
|
||||
'gstanalytics_image_util.c')
|
||||
|
||||
analytics_headers = files( 'analytics.h',
|
||||
'gstanalyticsmeta.h',
|
||||
@ -14,7 +15,9 @@ analytics_headers = files( 'analytics.h',
|
||||
'gstanalyticsobjecttrackingmtd.h',
|
||||
'gstanalyticssegmentationmtd.h',
|
||||
'gsttensormeta.h',
|
||||
'gsttensor.h')
|
||||
'gsttensor.h',
|
||||
'gstanalytics_image_util.h')
|
||||
|
||||
install_headers(analytics_headers, subdir : 'gstreamer-1.0/gst/analytics')
|
||||
|
||||
doc_sources = []
|
||||
|
Loading…
x
Reference in New Issue
Block a user