mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 17:50:36 +00:00
1643 lines
56 KiB
C
1643 lines
56 KiB
C
/* GStreamer
|
|
* Copyright (C) 2022 Collabora Ltd
|
|
* Copyright (C) 2024 Intel Corporation
|
|
*
|
|
* analyticmeta.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 <gst/check/gstcheck.h>
|
|
#include <gst/analytics/analytics.h>
|
|
|
|
GST_START_TEST (test_add_classification_meta)
|
|
{
|
|
/* Verify we can create a relation metadata
|
|
* and attach it classification mtd
|
|
*/
|
|
GstBuffer *buf;
|
|
GstAnalyticsRelationMeta *rmeta;
|
|
GstAnalyticsClsMtd cls_mtd;
|
|
gfloat conf_lvl[] = { 0.5f, 0.5f };
|
|
GQuark class_quarks[2];
|
|
gboolean ret;
|
|
|
|
class_quarks[0] = g_quark_from_string ("dog");
|
|
class_quarks[1] = g_quark_from_string ("cat");
|
|
|
|
buf = gst_buffer_new ();
|
|
rmeta = gst_buffer_add_analytics_relation_meta (buf);
|
|
ret = gst_analytics_relation_meta_add_cls_mtd (rmeta, 2, conf_lvl,
|
|
class_quarks, &cls_mtd);
|
|
fail_unless (ret == TRUE);
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_meta_pooled)
|
|
{
|
|
GstBufferPool *pool;
|
|
GstStructure *config;
|
|
GstBuffer *buf;
|
|
GstAnalyticsRelationMeta *rmeta1, *rmeta2;
|
|
|
|
pool = gst_buffer_pool_new ();
|
|
config = gst_buffer_pool_get_config (pool);
|
|
gst_buffer_pool_config_set_params (config, NULL, 1, 1, 1);
|
|
gst_buffer_pool_set_config (pool, config);
|
|
gst_buffer_pool_set_active (pool, TRUE);
|
|
|
|
gst_buffer_pool_acquire_buffer (pool, &buf, NULL);
|
|
rmeta1 = gst_buffer_add_analytics_relation_meta (buf);
|
|
gst_buffer_unref (buf);
|
|
|
|
gst_buffer_pool_acquire_buffer (pool, &buf, NULL);
|
|
|
|
rmeta2 = gst_buffer_add_analytics_relation_meta (buf);
|
|
|
|
fail_unless (rmeta1 == rmeta2);
|
|
gst_buffer_unref (buf);
|
|
gst_object_unref (pool);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_classification_meta_classes)
|
|
{
|
|
/* Verify we can retrieve classification data
|
|
* from the relation metadata
|
|
*/
|
|
GstBuffer *buf;
|
|
GstAnalyticsRelationMeta *rmeta;
|
|
gboolean ret;
|
|
GQuark class_quarks[2];
|
|
GstAnalyticsClsMtd cls_mtd, cls_mtd2;
|
|
|
|
class_quarks[0] = g_quark_from_string ("dog");
|
|
class_quarks[1] = g_quark_from_string ("cat");
|
|
|
|
buf = gst_buffer_new ();
|
|
rmeta = gst_buffer_add_analytics_relation_meta (buf);
|
|
gfloat conf_lvl[] = { 0.6f, 0.4f };
|
|
ret = gst_analytics_relation_meta_add_cls_mtd (rmeta, 2, conf_lvl,
|
|
class_quarks, &cls_mtd);
|
|
fail_unless (ret == TRUE);
|
|
fail_unless (gst_analytics_relation_get_length (rmeta) == 1);
|
|
|
|
gint dogIndex = gst_analytics_cls_mtd_get_index_by_quark (&cls_mtd,
|
|
class_quarks[0]);
|
|
fail_unless (dogIndex == 0);
|
|
gfloat confLvl = gst_analytics_cls_mtd_get_level (&cls_mtd, dogIndex);
|
|
GST_LOG ("dog:%f", confLvl);
|
|
assert_equals_float (confLvl, 0.6f);
|
|
|
|
gint catIndex = gst_analytics_cls_mtd_get_index_by_quark (&cls_mtd,
|
|
g_quark_from_string ("cat"));
|
|
confLvl = gst_analytics_cls_mtd_get_level (&cls_mtd, catIndex);
|
|
GST_LOG ("Cat:%f", confLvl);
|
|
assert_equals_float (confLvl, 0.4f);
|
|
assert_equals_int (gst_analytics_mtd_get_id ((GstAnalyticsMtd *) & cls_mtd),
|
|
0);
|
|
|
|
conf_lvl[0] = 0.1f;
|
|
conf_lvl[1] = 0.9f;
|
|
ret =
|
|
gst_analytics_relation_meta_add_cls_mtd (rmeta, 2, conf_lvl,
|
|
class_quarks, &cls_mtd2);
|
|
fail_unless (ret == TRUE);
|
|
fail_unless (gst_analytics_relation_get_length (rmeta) == 2);
|
|
|
|
dogIndex = gst_analytics_cls_mtd_get_index_by_quark (&cls_mtd2,
|
|
class_quarks[0]);
|
|
confLvl = gst_analytics_cls_mtd_get_level (&cls_mtd2, dogIndex);
|
|
assert_equals_float (confLvl, 0.1f);
|
|
|
|
catIndex = gst_analytics_cls_mtd_get_index_by_quark (&cls_mtd2,
|
|
class_quarks[0]);
|
|
confLvl = gst_analytics_cls_mtd_get_level (&cls_mtd2, catIndex);
|
|
assert_equals_float (confLvl, 0.1f);
|
|
|
|
/* Verify the relation meta contain the correct number of relatable metadata */
|
|
fail_unless (gst_analytics_relation_get_length (rmeta) == 2);
|
|
|
|
/* Verify first relatable metadata has the correct id. */
|
|
assert_equals_int (gst_analytics_mtd_get_id ((GstAnalyticsMtd *) & cls_mtd),
|
|
0);
|
|
|
|
/* Verify second relatable metadata has the correct id. */
|
|
assert_equals_int (gst_analytics_mtd_get_id (
|
|
(GstAnalyticsMtd *) & cls_mtd2), 1);
|
|
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_add_relation_meta)
|
|
{
|
|
/* Verify we set a relation between relatable metadata. */
|
|
|
|
GstBuffer *buf;
|
|
GstAnalyticsClsMtd cls_mtd[3];
|
|
GstAnalyticsRelationMetaInitParams init_params = { 5, 150 };
|
|
GstAnalyticsRelationMeta *relations;
|
|
GQuark class_quarks[2];
|
|
gboolean ret;
|
|
|
|
buf = gst_buffer_new ();
|
|
relations = gst_buffer_add_analytics_relation_meta_full (buf, &init_params);
|
|
|
|
gfloat conf_lvl[] = { 0.6f, 0.4f };
|
|
class_quarks[0] = g_quark_from_string ("dog");
|
|
class_quarks[1] = g_quark_from_string ("cat");
|
|
|
|
ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl,
|
|
class_quarks, &cls_mtd[0]);
|
|
fail_unless (ret == TRUE);
|
|
gst_analytics_mtd_get_id ((GstAnalyticsMtd *)
|
|
& cls_mtd[0]);
|
|
|
|
conf_lvl[0] = 0.6f;
|
|
conf_lvl[1] = 0.4f;
|
|
|
|
class_quarks[0] = g_quark_from_string ("plant");
|
|
class_quarks[1] = g_quark_from_string ("animal");
|
|
|
|
|
|
ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl,
|
|
class_quarks, &cls_mtd[1]);
|
|
gst_analytics_mtd_get_id ((GstAnalyticsMtd *)
|
|
& cls_mtd[1]);
|
|
|
|
fail_unless (gst_analytics_relation_meta_set_relation (relations,
|
|
GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[0].id,
|
|
cls_mtd[1].id) == TRUE);
|
|
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_add_relation_inefficiency_reporting_cases)
|
|
{
|
|
/*
|
|
* Verify inefficiency of relation order is reported.
|
|
*/
|
|
GstBuffer *buf;
|
|
GstAnalyticsClsMtd cls_mtd[3];
|
|
GstAnalyticsRelationMetaInitParams init_params = { 2, 10 };
|
|
GstAnalyticsRelationMeta *relations;
|
|
gboolean ret;
|
|
GQuark class_quarks[2];
|
|
|
|
|
|
buf = gst_buffer_new ();
|
|
relations = gst_buffer_add_analytics_relation_meta_full (buf, &init_params);
|
|
|
|
gfloat conf_lvl[] = { 0.6f, 0.4f };
|
|
|
|
class_quarks[0] = g_quark_from_string ("dog");
|
|
class_quarks[1] = g_quark_from_string ("cat");
|
|
|
|
ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl,
|
|
class_quarks, &cls_mtd[0]);
|
|
fail_unless (gst_analytics_relation_get_length (relations) == 1);
|
|
fail_unless (ret == TRUE);
|
|
|
|
conf_lvl[0] = 0.6f;
|
|
conf_lvl[1] = 0.4f;
|
|
class_quarks[0] = g_quark_from_string ("plant");
|
|
class_quarks[1] = g_quark_from_string ("animal");
|
|
|
|
ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl,
|
|
class_quarks, &cls_mtd[1]);
|
|
fail_unless (gst_analytics_relation_get_length (relations) == 2);
|
|
fail_unless (ret == TRUE);
|
|
|
|
conf_lvl[0] = 0.6f;
|
|
conf_lvl[1] = 0.4f;
|
|
class_quarks[0] = g_quark_from_string ("male");
|
|
class_quarks[1] = g_quark_from_string ("female");
|
|
|
|
ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl,
|
|
class_quarks, &cls_mtd[2]);
|
|
fail_unless (gst_analytics_relation_get_length (relations) == 3);
|
|
fail_unless (ret == TRUE);
|
|
|
|
fail_unless (gst_analytics_relation_meta_set_relation (relations,
|
|
GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[0].id, cls_mtd[1].id)
|
|
== TRUE);
|
|
fail_unless (gst_analytics_relation_meta_set_relation (relations,
|
|
GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[0].id, cls_mtd[2].id)
|
|
== TRUE);
|
|
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_query_relation_meta_cases)
|
|
{
|
|
/* Verify we can query existence of direct and indirect relation */
|
|
GstBuffer *buf;
|
|
GstAnalyticsClsMtd cls_mtd[3];
|
|
GstAnalyticsRelationMetaInitParams init_params = { 2, 150 };
|
|
GstAnalyticsRelationMeta *relations;
|
|
gboolean ret;
|
|
GQuark class_quarks[2];
|
|
|
|
buf = gst_buffer_new ();
|
|
relations = gst_buffer_add_analytics_relation_meta_full (buf, &init_params);
|
|
|
|
gfloat conf_lvl[] = { 0.6f, 0.4f };
|
|
|
|
class_quarks[0] = g_quark_from_string ("dog");
|
|
class_quarks[1] = g_quark_from_string ("cat");
|
|
|
|
ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl,
|
|
class_quarks, &cls_mtd[0]);
|
|
fail_unless (ret == TRUE);
|
|
|
|
conf_lvl[0] = 0.6f;
|
|
conf_lvl[1] = 0.4f;
|
|
class_quarks[0] = g_quark_from_string ("plant");
|
|
class_quarks[1] = g_quark_from_string ("animal");
|
|
|
|
ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl,
|
|
class_quarks, &cls_mtd[1]);
|
|
fail_unless (ret == TRUE);
|
|
|
|
conf_lvl[0] = 0.6f;
|
|
conf_lvl[1] = 0.4f;
|
|
class_quarks[0] = g_quark_from_string ("male");
|
|
class_quarks[1] = g_quark_from_string ("female");
|
|
|
|
ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl,
|
|
class_quarks, &cls_mtd[2]);
|
|
fail_unless (ret == TRUE);
|
|
|
|
// Pet is part of kingdom
|
|
gst_analytics_relation_meta_set_relation (relations,
|
|
GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[0].id, cls_mtd[1].id);
|
|
|
|
// Kingdom contain pet
|
|
gst_analytics_relation_meta_set_relation (relations,
|
|
GST_ANALYTICS_REL_TYPE_CONTAIN, cls_mtd[1].id, cls_mtd[0].id);
|
|
|
|
// Pet contain gender
|
|
gst_analytics_relation_meta_set_relation (relations,
|
|
GST_ANALYTICS_REL_TYPE_CONTAIN, cls_mtd[0].id, cls_mtd[2].id);
|
|
|
|
/* Query if pet relate kingdom through a IS_PART relation with a maximum
|
|
* relation span of 1. Max relation span of 1 mean they directly related.*/
|
|
gboolean exist = gst_analytics_relation_meta_exist (relations, cls_mtd[0].id,
|
|
cls_mtd[1].id, 1, GST_ANALYTICS_REL_TYPE_IS_PART_OF, NULL);
|
|
fail_unless (exist == TRUE);
|
|
|
|
/* Query if pet relate to gender through a IS_PART relation. */
|
|
exist = gst_analytics_relation_meta_exist (relations, cls_mtd[0].id,
|
|
cls_mtd[2].id, 1, GST_ANALYTICS_REL_TYPE_IS_PART_OF, NULL);
|
|
fail_unless (exist == FALSE);
|
|
|
|
/* Query if pet relate to kingdom through a CONTAIN relation. */
|
|
exist = gst_analytics_relation_meta_exist (relations, cls_mtd[0].id,
|
|
cls_mtd[1].id, 1, GST_ANALYTICS_REL_TYPE_CONTAIN, NULL);
|
|
fail_unless (exist == FALSE);
|
|
|
|
GstAnalyticsRelTypes cond =
|
|
GST_ANALYTICS_REL_TYPE_IS_PART_OF | GST_ANALYTICS_REL_TYPE_CONTAIN |
|
|
GST_ANALYTICS_REL_TYPE_RELATE_TO;
|
|
|
|
/* Query if pet relate to gender through IS_PART or CONTAIN or
|
|
* RELATE_TO relation. */
|
|
exist = gst_analytics_relation_meta_exist (relations, cls_mtd[0].id,
|
|
cls_mtd[2].id, 1, cond, NULL);
|
|
fail_unless (exist == TRUE);
|
|
|
|
/* Query if pet relate to kindom through CONTAIN or RELATE_TO relation */
|
|
cond = GST_ANALYTICS_REL_TYPE_CONTAIN | GST_ANALYTICS_REL_TYPE_RELATE_TO;
|
|
exist = gst_analytics_relation_meta_exist (relations, cls_mtd[0].id,
|
|
cls_mtd[1].id, 1, cond, NULL);
|
|
fail_unless (exist == FALSE);
|
|
|
|
/* Query if kingdom relate to gender through a CONTAIN relation with a maximum
|
|
* relation span of 1. */
|
|
exist = gst_analytics_relation_meta_exist (relations, cls_mtd[1].id,
|
|
cls_mtd[2].id, 1, GST_ANALYTICS_REL_TYPE_CONTAIN, NULL);
|
|
|
|
/* We expect this to fail because kingdom relate to gender CONTAIN relations
|
|
* but indirectly (via pet) and we set the max relation span to 1*/
|
|
fail_unless (exist == FALSE);
|
|
|
|
/* Same has previous check but using INFINIT relation span */
|
|
exist = gst_analytics_relation_meta_exist (relations, cls_mtd[1].id,
|
|
cls_mtd[2].id, GST_INF_RELATION_SPAN, GST_ANALYTICS_REL_TYPE_CONTAIN,
|
|
NULL);
|
|
fail_unless (exist == TRUE);
|
|
|
|
exist = gst_analytics_relation_meta_exist (relations, cls_mtd[2].id,
|
|
cls_mtd[1].id, GST_INF_RELATION_SPAN, GST_ANALYTICS_REL_TYPE_CONTAIN,
|
|
NULL);
|
|
fail_unless (exist == FALSE);
|
|
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_path_relation_meta)
|
|
{
|
|
/* Verify we can retrieve relation path */
|
|
GstBuffer *buf;
|
|
GstAnalyticsClsMtd cls_mtd[3];
|
|
GstAnalyticsRelationMetaInitParams init_params = { 2, 150 };
|
|
GstAnalyticsRelationMeta *relations;
|
|
gboolean ret;
|
|
GQuark class_quarks[2];
|
|
|
|
buf = gst_buffer_new ();
|
|
relations = gst_buffer_add_analytics_relation_meta_full (buf, &init_params);
|
|
|
|
gfloat conf_lvl[] = { 0.6f, 0.4f };
|
|
class_quarks[0] = g_quark_from_string ("dog");
|
|
class_quarks[1] = g_quark_from_string ("cat");
|
|
|
|
ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl,
|
|
class_quarks, &cls_mtd[0]);
|
|
fail_unless (ret == TRUE);
|
|
fail_unless (cls_mtd[0].id == 0);
|
|
|
|
conf_lvl[0] = 0.6f;
|
|
conf_lvl[1] = 0.4f;
|
|
class_quarks[0] = g_quark_from_string ("plant");
|
|
class_quarks[1] = g_quark_from_string ("animal");
|
|
|
|
ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl,
|
|
class_quarks, &cls_mtd[1]);
|
|
fail_unless (ret == TRUE);
|
|
fail_unless (cls_mtd[1].id == 1);
|
|
|
|
conf_lvl[0] = 0.6f;
|
|
conf_lvl[1] = 0.4f;
|
|
class_quarks[0] = g_quark_from_string ("male");
|
|
class_quarks[1] = g_quark_from_string ("female");
|
|
|
|
ret = gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl,
|
|
class_quarks, &cls_mtd[2]);
|
|
fail_unless (ret == TRUE);
|
|
fail_unless (cls_mtd[2].id == 2);
|
|
|
|
// Pet is part of kingdom
|
|
gst_analytics_relation_meta_set_relation (relations,
|
|
GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[0].id, cls_mtd[1].id);
|
|
|
|
// Kingdom contain pet
|
|
gst_analytics_relation_meta_set_relation (relations,
|
|
GST_ANALYTICS_REL_TYPE_CONTAIN, cls_mtd[1].id, cls_mtd[0].id);
|
|
|
|
// Pet contain gender
|
|
gst_analytics_relation_meta_set_relation (relations,
|
|
GST_ANALYTICS_REL_TYPE_CONTAIN, cls_mtd[0].id, cls_mtd[2].id);
|
|
|
|
GArray *path = NULL;
|
|
GstAnalyticsRelTypes cond = GST_ANALYTICS_REL_TYPE_CONTAIN;
|
|
gboolean exist = gst_analytics_relation_meta_exist (relations, cls_mtd[0].id,
|
|
cls_mtd[2].id, GST_INF_RELATION_SPAN, cond, &path);
|
|
if (exist) {
|
|
fail_unless (path != NULL);
|
|
gint i;
|
|
guint path_check_ids[] = { 0, 2 };
|
|
fail_unless (path->len == 2);
|
|
for (i = 0; i < path->len; i++) {
|
|
fail_unless (path_check_ids[i] == g_array_index (path, guint, i));
|
|
}
|
|
g_array_free (g_steal_pointer (&path), TRUE);
|
|
fail_unless (i == 2);
|
|
}
|
|
|
|
cond = GST_ANALYTICS_REL_TYPE_CONTAIN;
|
|
exist = gst_analytics_relation_meta_exist (relations, cls_mtd[1].id,
|
|
cls_mtd[2].id, GST_INF_RELATION_SPAN, cond, &path);
|
|
if (exist) {
|
|
gint i;
|
|
guint path_check_ids[] = { 1, 0, 2 };
|
|
fail_unless (path != NULL);
|
|
fail_unless (path->len == 3);
|
|
for (i = 0; i < path->len; i++) {
|
|
fail_unless (path_check_ids[i] == g_array_index (path, guint, i));
|
|
}
|
|
g_array_free (g_steal_pointer (&path), TRUE);
|
|
fail_unless (i == 3);
|
|
}
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_cyclic_relation_meta)
|
|
{
|
|
/* Verify we can discover cycle in relation and not report multiple time
|
|
* the same node and get into an infinit exploration */
|
|
|
|
GstBuffer *buf;
|
|
GstAnalyticsClsMtd cls_mtd[3];
|
|
GstAnalyticsRelationMetaInitParams init_params = { 2, 150 };
|
|
GstAnalyticsRelationMeta *relations;
|
|
gfloat conf_lvl[2];
|
|
GQuark class_quarks[2];
|
|
|
|
class_quarks[0] = g_quark_from_string ("attr1");
|
|
class_quarks[1] = g_quark_from_string ("attr2");
|
|
|
|
buf = gst_buffer_new ();
|
|
relations = gst_buffer_add_analytics_relation_meta_full (buf, &init_params);
|
|
|
|
conf_lvl[0] = 0.5f;
|
|
conf_lvl[1] = 0.5f;
|
|
gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl,
|
|
class_quarks, &cls_mtd[0]);
|
|
|
|
gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl,
|
|
class_quarks, &cls_mtd[1]);
|
|
|
|
gst_analytics_relation_meta_add_cls_mtd (relations, 2, conf_lvl,
|
|
class_quarks, &cls_mtd[2]);
|
|
|
|
// (0) -> (1)
|
|
gst_analytics_relation_meta_set_relation (relations,
|
|
GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[0].id, cls_mtd[1].id);
|
|
|
|
// (1)->(2)
|
|
gst_analytics_relation_meta_set_relation (relations,
|
|
GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[1].id, cls_mtd[2].id);
|
|
|
|
// (2) -> (0)
|
|
gst_analytics_relation_meta_set_relation (relations,
|
|
GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd[2].id, cls_mtd[0].id);
|
|
|
|
GArray *path = NULL;
|
|
GstAnalyticsRelTypes cond = GST_ANALYTICS_REL_TYPE_CONTAIN;
|
|
gboolean exist = gst_analytics_relation_meta_exist (relations, cls_mtd[0].id,
|
|
cls_mtd[2].id, GST_INF_RELATION_SPAN, cond, &path);
|
|
fail_unless (exist == FALSE);
|
|
|
|
cond = GST_ANALYTICS_REL_TYPE_IS_PART_OF;
|
|
exist =
|
|
gst_analytics_relation_meta_exist (relations, cls_mtd[0].id,
|
|
cls_mtd[2].id, GST_INF_RELATION_SPAN, cond, &path);
|
|
fail_unless (exist == TRUE);
|
|
if (exist) {
|
|
gint i;
|
|
guint path_ids[] = { 0, 1, 2 };
|
|
fail_unless (path->len == 3);
|
|
for (i = 0; i < path->len; i++) {
|
|
fail_unless (path_ids[i] == g_array_index (path, guint, i));
|
|
}
|
|
g_array_free (g_steal_pointer (&path), TRUE);
|
|
fail_unless (i == 3);
|
|
}
|
|
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_add_od_meta)
|
|
{
|
|
/* Verity we can add Object Detection relatable metadata to a relation
|
|
* metadata */
|
|
GstBuffer *buf;
|
|
GstAnalyticsRelationMetaInitParams init_params = { 5, 150 };
|
|
GstAnalyticsRelationMeta *rmeta;
|
|
GstAnalyticsODMtd od_mtd;
|
|
gboolean ret;
|
|
buf = gst_buffer_new ();
|
|
|
|
rmeta = gst_buffer_add_analytics_relation_meta_full (buf, &init_params);
|
|
|
|
GQuark type = g_quark_from_string ("dog");
|
|
gint x = 20;
|
|
gint y = 20;
|
|
gint w = 10;
|
|
gint h = 15;
|
|
gfloat loc_conf_lvl = 0.6f;
|
|
ret = gst_analytics_relation_meta_add_od_mtd (rmeta, type, x, y,
|
|
w, h, loc_conf_lvl, &od_mtd);
|
|
fail_unless (ret == TRUE);
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_add_oriented_od_meta)
|
|
{
|
|
/* Verity we can add Oriented Object Detection relatable metadata to a relation
|
|
* metadata */
|
|
GstBuffer *buf;
|
|
GstAnalyticsRelationMetaInitParams init_params = { 5, 150 };
|
|
GstAnalyticsRelationMeta *rmeta;
|
|
GstAnalyticsODMtd od_mtd;
|
|
gboolean ret;
|
|
buf = gst_buffer_new ();
|
|
|
|
rmeta = gst_buffer_add_analytics_relation_meta_full (buf, &init_params);
|
|
|
|
GQuark type = g_quark_from_string ("dog");
|
|
gint x = 20;
|
|
gint y = 20;
|
|
gint w = 10;
|
|
gint h = 15;
|
|
gfloat r = 0.785f;
|
|
gfloat loc_conf_lvl = 0.6f;
|
|
ret = gst_analytics_relation_meta_add_oriented_od_mtd (rmeta, type, x, y,
|
|
w, h, r, loc_conf_lvl, &od_mtd);
|
|
fail_unless (ret == TRUE);
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_od_meta_fields)
|
|
{
|
|
/* Verify we can readback fields of object detection metadata */
|
|
GstBuffer *buf;
|
|
GstAnalyticsRelationMetaInitParams init_params = { 5, 150 };
|
|
GstAnalyticsRelationMeta *rmeta;
|
|
GstAnalyticsODMtd od_mtd;
|
|
gboolean ret;
|
|
buf = gst_buffer_new ();
|
|
|
|
rmeta = gst_buffer_add_analytics_relation_meta_full (buf, &init_params);
|
|
|
|
GQuark type = g_quark_from_string ("dog");
|
|
gint x = 21;
|
|
gint y = 20;
|
|
gint w = 10;
|
|
gint h = 15;
|
|
gfloat loc_conf_lvl = 0.6f;
|
|
ret = gst_analytics_relation_meta_add_od_mtd (rmeta, type, x, y,
|
|
w, h, loc_conf_lvl, &od_mtd);
|
|
|
|
fail_unless (ret == TRUE);
|
|
|
|
gint _x, _y, _w, _h;
|
|
gfloat _loc_conf_lvl;
|
|
gst_analytics_od_mtd_get_location (&od_mtd, &_x, &_y, &_w, &_h,
|
|
&_loc_conf_lvl);
|
|
|
|
fail_unless (_x == x);
|
|
fail_unless (_y == y);
|
|
fail_unless (_w == w);
|
|
fail_unless (_h == h);
|
|
fail_unless (_loc_conf_lvl == loc_conf_lvl);
|
|
|
|
_loc_conf_lvl = -200.0; // dirty this var by setting invalid value.
|
|
gst_analytics_od_mtd_get_confidence_lvl (&od_mtd, &_loc_conf_lvl);
|
|
|
|
fail_unless (_loc_conf_lvl == loc_conf_lvl);
|
|
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_oriented_od_meta_fields)
|
|
{
|
|
/* Verify we can readback fields of object detection metadata */
|
|
GstBuffer *buf;
|
|
GstAnalyticsRelationMetaInitParams init_params = { 5, 150 };
|
|
GstAnalyticsRelationMeta *rmeta;
|
|
GstAnalyticsODMtd od_mtd;
|
|
gboolean ret;
|
|
buf = gst_buffer_new ();
|
|
|
|
rmeta = gst_buffer_add_analytics_relation_meta_full (buf, &init_params);
|
|
|
|
GQuark type = g_quark_from_string ("dog");
|
|
gint x = 21;
|
|
gint y = 20;
|
|
gint w = 10;
|
|
gint h = 15;
|
|
gfloat r = 0.785f;
|
|
gfloat loc_conf_lvl = 0.6f;
|
|
ret = gst_analytics_relation_meta_add_oriented_od_mtd (rmeta, type, x, y,
|
|
w, h, r, loc_conf_lvl, &od_mtd);
|
|
|
|
fail_unless (ret == TRUE);
|
|
|
|
gint _x, _y, _w, _h;
|
|
gfloat _r, _loc_conf_lvl;
|
|
gst_analytics_od_mtd_get_oriented_location (&od_mtd, &_x, &_y, &_w, &_h, &_r,
|
|
&_loc_conf_lvl);
|
|
|
|
fail_unless (_x == x);
|
|
fail_unless (_y == y);
|
|
fail_unless (_w == w);
|
|
fail_unless (_h == h);
|
|
fail_unless (_r == r);
|
|
fail_unless (_loc_conf_lvl == loc_conf_lvl);
|
|
|
|
_loc_conf_lvl = -200.0; // dirty this var by setting invalid value.
|
|
gst_analytics_od_mtd_get_confidence_lvl (&od_mtd, &_loc_conf_lvl);
|
|
|
|
fail_unless (_loc_conf_lvl == loc_conf_lvl);
|
|
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_add_non_oriented_get_oriented_od_meta_fields)
|
|
{
|
|
/* Verify we can readback fields of object detection metadata */
|
|
GstBuffer *buf;
|
|
GstAnalyticsRelationMetaInitParams init_params = { 5, 150 };
|
|
GstAnalyticsRelationMeta *rmeta;
|
|
GstAnalyticsODMtd od_mtd;
|
|
gboolean ret;
|
|
buf = gst_buffer_new ();
|
|
|
|
rmeta = gst_buffer_add_analytics_relation_meta_full (buf, &init_params);
|
|
|
|
GQuark type = g_quark_from_string ("dog");
|
|
gint x = 21;
|
|
gint y = 20;
|
|
gint w = 10;
|
|
gint h = 15;
|
|
gfloat loc_conf_lvl = 0.6f;
|
|
ret = gst_analytics_relation_meta_add_od_mtd (rmeta, type, x, y,
|
|
w, h, loc_conf_lvl, &od_mtd);
|
|
|
|
fail_unless (ret == TRUE);
|
|
|
|
gint _x, _y, _w, _h;
|
|
gfloat _r, _loc_conf_lvl;
|
|
gst_analytics_od_mtd_get_oriented_location (&od_mtd, &_x, &_y, &_w, &_h, &_r,
|
|
&_loc_conf_lvl);
|
|
|
|
fail_unless (_x == x);
|
|
fail_unless (_y == y);
|
|
fail_unless (_w == w);
|
|
fail_unless (_h == h);
|
|
fail_unless (_r == 0);
|
|
fail_unless (_loc_conf_lvl == loc_conf_lvl);
|
|
|
|
_loc_conf_lvl = -200.0; // dirty this var by setting invalid value.
|
|
gst_analytics_od_mtd_get_confidence_lvl (&od_mtd, &_loc_conf_lvl);
|
|
|
|
fail_unless (_loc_conf_lvl == loc_conf_lvl);
|
|
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_add_oriented_get_non_oriented_od_meta_fields)
|
|
{
|
|
/* Verify we can readback fields of object detection metadata */
|
|
GstBuffer *buf;
|
|
GstAnalyticsRelationMeta *rmeta;
|
|
GstAnalyticsODMtd od_mtd;
|
|
gboolean ret;
|
|
gint _x, _y, _w, _h;
|
|
gfloat _loc_conf_lvl;
|
|
|
|
buf = gst_buffer_new ();
|
|
rmeta = gst_buffer_add_analytics_relation_meta (buf);
|
|
|
|
struct
|
|
{
|
|
gint x, y, w, h;
|
|
gfloat r;
|
|
gint expected_x, expected_y, expected_w, expected_h;
|
|
} test_cases[] = {
|
|
{500, 300, 200, 100, 0.0f, 500, 300, 200, 100},
|
|
{600, 400, 200, 100, 0.785f, 594, 344, 212, 212},
|
|
{400, 400, 150, 100, 1.570f, 425, 375, 100, 150},
|
|
{400, 300, 200, 100, 2.268f, 397, 241, 206, 218},
|
|
{400, 400, 200, 100, 3.142f, 400, 400, 200, 100},
|
|
{300, 300, 150, 100, 4.712f, 325, 275, 100, 150},
|
|
{500, 400, 1, 100, 0.785f, 465, 415, 71, 71},
|
|
{400, 500, 100, 1, 2.268f, 417, 461, 65, 77},
|
|
{400, 400, 100, 100, 6.283f, 400, 400, 100, 100},
|
|
};
|
|
|
|
gfloat loc_conf_lvl = 0.9f;
|
|
for (gsize i = 0; i < G_N_ELEMENTS (test_cases); i++) {
|
|
gint x = test_cases[i].x;
|
|
gint y = test_cases[i].y;
|
|
gint w = test_cases[i].w;
|
|
gint h = test_cases[i].h;
|
|
gfloat r = test_cases[i].r;
|
|
|
|
gint expected_x = test_cases[i].expected_x;
|
|
gint expected_y = test_cases[i].expected_y;
|
|
gint expected_w = test_cases[i].expected_w;
|
|
gint expected_h = test_cases[i].expected_h;
|
|
|
|
ret =
|
|
gst_analytics_relation_meta_add_oriented_od_mtd (rmeta,
|
|
g_quark_from_string ("dog"), x, y, w, h, r, loc_conf_lvl, &od_mtd);
|
|
fail_unless (ret == TRUE);
|
|
|
|
gst_analytics_od_mtd_get_location (&od_mtd, &_x, &_y, &_w, &_h,
|
|
&_loc_conf_lvl);
|
|
|
|
fail_unless (_x == expected_x);
|
|
fail_unless (_y == expected_y);
|
|
fail_unless (_w == expected_w);
|
|
fail_unless (_h == expected_h);
|
|
fail_unless (_loc_conf_lvl == loc_conf_lvl);
|
|
}
|
|
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_od_cls_relation)
|
|
{
|
|
/* Verify we can add a object detection and classification metadata to
|
|
* a relation metadata */
|
|
|
|
GstBuffer *buf;
|
|
GstAnalyticsClsMtd cls_mtd;
|
|
GstAnalyticsODMtd od_mtd;
|
|
/* We intentionally set buffer small than required to verify sanity
|
|
* with re-allocation */
|
|
GstAnalyticsRelationMetaInitParams init_params = { 5, 150 };
|
|
GstAnalyticsRelationMeta *rmeta;
|
|
gboolean ret;
|
|
GArray *path = NULL;
|
|
gboolean exist;
|
|
gint _x, _y, _w, _h;
|
|
gfloat _loc_conf_lvl;
|
|
GQuark class_quarks[2];
|
|
|
|
buf = gst_buffer_new ();
|
|
rmeta = gst_buffer_add_analytics_relation_meta_full (buf, &init_params);
|
|
|
|
gfloat conf_lvl[] = { 0.7f, 0.3f };
|
|
class_quarks[0] = g_quark_from_string ("dog");
|
|
class_quarks[1] = g_quark_from_string ("cat");
|
|
|
|
gst_analytics_relation_meta_add_cls_mtd (rmeta, 2, conf_lvl,
|
|
class_quarks, &cls_mtd);
|
|
|
|
GQuark type = g_quark_from_string ("dog");
|
|
gint x = 21;
|
|
gint y = 20;
|
|
gint w = 10;
|
|
gint h = 15;
|
|
gfloat loc_conf_lvl = 0.6f;
|
|
gst_analytics_relation_meta_add_od_mtd (rmeta, type, x, y, w, h,
|
|
loc_conf_lvl, &od_mtd);
|
|
|
|
ret = gst_analytics_relation_meta_set_relation (rmeta,
|
|
GST_ANALYTICS_REL_TYPE_CONTAIN, od_mtd.id, cls_mtd.id);
|
|
fail_unless (ret == TRUE);
|
|
|
|
ret = gst_analytics_relation_meta_set_relation (rmeta,
|
|
GST_ANALYTICS_REL_TYPE_IS_PART_OF, cls_mtd.id, od_mtd.id);
|
|
fail_unless (ret == TRUE);
|
|
|
|
/* Verify OD relate to CLS only through a CONTAIN relation */
|
|
exist = gst_analytics_relation_meta_exist (rmeta,
|
|
od_mtd.id, cls_mtd.id, GST_INF_RELATION_SPAN,
|
|
GST_ANALYTICS_REL_TYPE_IS_PART_OF, NULL);
|
|
fail_unless (exist == FALSE);
|
|
|
|
exist = gst_analytics_relation_meta_exist (rmeta,
|
|
od_mtd.id, cls_mtd.id, GST_INF_RELATION_SPAN,
|
|
GST_ANALYTICS_REL_TYPE_CONTAIN, &path);
|
|
fail_unless (exist == TRUE);
|
|
|
|
/* Query the relation path and verify it is correct */
|
|
guint ids[2];
|
|
gint i;
|
|
fail_unless (path->len == 2);
|
|
for (i = 0; i < path->len; i++) {
|
|
ids[i] = g_array_index (path, guint, i);
|
|
GST_LOG ("id=%u", ids[i]);
|
|
}
|
|
g_array_free (g_steal_pointer (&path), TRUE);
|
|
fail_unless (ids[0] == 1);
|
|
fail_unless (ids[1] == 0);
|
|
|
|
GstAnalyticsMtd rlt_mtd;
|
|
exist = gst_analytics_relation_meta_get_mtd (rmeta, ids[0], 0, &rlt_mtd);
|
|
fail_unless (exist == TRUE);
|
|
|
|
GstAnalyticsMtdType mtd_type = gst_analytics_mtd_get_mtd_type (&rlt_mtd);
|
|
|
|
/* Verify relatable meta with id == 1 is of type Object Detection */
|
|
fail_unless (mtd_type == gst_analytics_od_mtd_get_mtd_type ());
|
|
|
|
gst_analytics_od_mtd_get_location ((GstAnalyticsODMtd *) & rlt_mtd, &_x, &_y,
|
|
&_w, &_h, &_loc_conf_lvl);
|
|
fail_unless (_x == x);
|
|
fail_unless (_y == y);
|
|
fail_unless (_w == w);
|
|
fail_unless (_h == h);
|
|
fail_unless (_loc_conf_lvl == loc_conf_lvl);
|
|
|
|
GST_LOG ("mtd_type:%s", gst_analytics_mtd_type_get_name (mtd_type));
|
|
|
|
exist = gst_analytics_relation_meta_get_mtd (rmeta, ids[1], 0, &rlt_mtd);
|
|
fail_unless (exist == TRUE);
|
|
mtd_type = gst_analytics_mtd_get_mtd_type (&rlt_mtd);
|
|
|
|
/* Verify relatable meta with id == 0 is of type classification */
|
|
fail_unless (mtd_type == gst_analytics_cls_mtd_get_mtd_type ());
|
|
gint index =
|
|
gst_analytics_cls_mtd_get_index_by_quark ((GstAnalyticsClsMtd *) &
|
|
rlt_mtd,
|
|
g_quark_from_string ("dog"));
|
|
gfloat lvl =
|
|
gst_analytics_cls_mtd_get_level ((GstAnalyticsClsMtd *) & rlt_mtd, index);
|
|
GST_LOG ("dog %f [%d, %d %d, %d", lvl, _x, _y, _w, _h);
|
|
|
|
fail_unless (lvl == 0.7f);
|
|
index =
|
|
gst_analytics_cls_mtd_get_index_by_quark ((GstAnalyticsClsMtd *) &
|
|
rlt_mtd, g_quark_from_string ("cat"));
|
|
lvl =
|
|
gst_analytics_cls_mtd_get_level ((GstAnalyticsClsMtd *) & rlt_mtd, index);
|
|
fail_unless (lvl == 0.3f);
|
|
|
|
GST_LOG ("mtd_type:%s", gst_analytics_mtd_type_get_name (mtd_type));
|
|
GST_LOG ("cat %f [%d, %d %d, %d", lvl, _x, _y, _w, _h);
|
|
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_multi_od_cls_relation)
|
|
{
|
|
GstBuffer *buf;
|
|
GstAnalyticsClsMtd cls_mtd[3];
|
|
GstAnalyticsODMtd od_mtd[2];
|
|
GstAnalyticsRelationMetaInitParams init_params = { 5, 150 };
|
|
GstAnalyticsRelationMeta *rmeta;
|
|
guint cls_id, ids[2], i;
|
|
gboolean ret;
|
|
const gint dog_cls_index = 0;
|
|
const gint cat_cls_index = 1;
|
|
gfloat cls_conf_lvl[2], lvl;
|
|
GArray *path = NULL;
|
|
gfloat _loc_conf_lvl;
|
|
gint x, _x, y, _y, w, _w, h, _h;
|
|
GstAnalyticsMtdType mtd_type;
|
|
GQuark cls_type;
|
|
GstAnalyticsMtd mtd;
|
|
gpointer state = NULL;
|
|
GQuark class_quarks[2];
|
|
class_quarks[0] = g_quark_from_string ("dog");
|
|
class_quarks[1] = g_quark_from_string ("cat");
|
|
|
|
|
|
buf = gst_buffer_new ();
|
|
rmeta = gst_buffer_add_analytics_relation_meta_full (buf, &init_params);
|
|
|
|
/* Define first relation ObjectDetection -contain-> Classification */
|
|
cls_conf_lvl[dog_cls_index] = 0.7f;
|
|
cls_conf_lvl[cat_cls_index] = 0.3f;
|
|
|
|
gst_analytics_relation_meta_add_cls_mtd (rmeta, 2, cls_conf_lvl,
|
|
class_quarks, &cls_mtd[0]);
|
|
|
|
cls_type = g_quark_from_string ("dog");
|
|
x = 21;
|
|
y = 20;
|
|
w = 10;
|
|
h = 15;
|
|
gfloat loc_conf_lvl = 0.6f;
|
|
gst_analytics_relation_meta_add_od_mtd (rmeta, cls_type, x, y, w,
|
|
h, loc_conf_lvl, &od_mtd[0]);
|
|
|
|
ret = gst_analytics_relation_meta_set_relation (rmeta,
|
|
GST_ANALYTICS_REL_TYPE_CONTAIN, od_mtd[0].id, cls_mtd[0].id);
|
|
fail_unless (ret == TRUE);
|
|
GST_LOG ("Set rel Obj:%d -c-> Cls:%d", od_mtd[0].id, cls_mtd[0].id);
|
|
|
|
/* Define second relation ObjectDetection -contain-> Classification */
|
|
cls_conf_lvl[dog_cls_index] = 0.1f;
|
|
cls_conf_lvl[cat_cls_index] = 0.9f;
|
|
gst_analytics_relation_meta_add_cls_mtd (rmeta, 2, cls_conf_lvl,
|
|
class_quarks, &cls_mtd[1]);
|
|
|
|
cls_type = g_quark_from_string ("cat");
|
|
x = 50;
|
|
y = 21;
|
|
w = 11;
|
|
h = 16;
|
|
loc_conf_lvl = 0.7f;
|
|
gst_analytics_relation_meta_add_od_mtd (rmeta, cls_type, x, y, w,
|
|
h, loc_conf_lvl, &od_mtd[1]);
|
|
|
|
ret = gst_analytics_relation_meta_set_relation (rmeta,
|
|
GST_ANALYTICS_REL_TYPE_CONTAIN, od_mtd[1].id, cls_mtd[1].id);
|
|
|
|
GST_LOG ("Set rel Obj:%d -c-> Cls:%d", od_mtd[1].id, cls_mtd[1].id);
|
|
fail_unless (ret == TRUE);
|
|
|
|
/* Query relations */
|
|
|
|
/* Query relation between first object detection and first classification
|
|
* and verify they are only related by CONTAIN relation OD relate to
|
|
* CLASSIFICATION through a CONTAIN relation. */
|
|
gboolean exist =
|
|
gst_analytics_relation_meta_exist (rmeta, od_mtd[0].id, cls_mtd[0].id,
|
|
GST_INF_RELATION_SPAN,
|
|
GST_ANALYTICS_REL_TYPE_IS_PART_OF, NULL);
|
|
fail_unless (exist == FALSE);
|
|
|
|
exist =
|
|
gst_analytics_relation_meta_exist (rmeta, od_mtd[0].id, cls_mtd[0].id,
|
|
GST_INF_RELATION_SPAN, GST_ANALYTICS_REL_TYPE_CONTAIN, NULL);
|
|
fail_unless (exist == TRUE);
|
|
|
|
|
|
/* Query relation between second object detection and second classification
|
|
* and verify they are only related by CONTAIN relation OD relate to
|
|
* CLASSIFICATION through a CONTAIN relation.
|
|
*/
|
|
exist =
|
|
gst_analytics_relation_meta_exist (rmeta, od_mtd[1].id, cls_mtd[1].id,
|
|
GST_INF_RELATION_SPAN, GST_ANALYTICS_REL_TYPE_CONTAIN, &path);
|
|
fail_unless (exist == TRUE);
|
|
|
|
/* Verify relation path between OD second (id=3) and Cls second (id=2)
|
|
* is correct
|
|
*/
|
|
fail_unless (path->len == 2);
|
|
for (i = 0; i < path->len; i++) {
|
|
ids[i] = g_array_index (path, guint, i);
|
|
GST_LOG ("id=%u", ids[i]);
|
|
}
|
|
g_array_free (g_steal_pointer (&path), TRUE);
|
|
fail_unless (ids[0] == 3);
|
|
fail_unless (ids[1] == 2);
|
|
|
|
/* Verify the relatable metadata 3 is of correct type
|
|
* (ObjectDetection). Verify it describe the correct
|
|
* the correct data.
|
|
*/
|
|
gst_analytics_relation_meta_get_mtd (rmeta, ids[0], 0, &mtd);
|
|
mtd_type = gst_analytics_mtd_get_mtd_type (&mtd);
|
|
fail_unless (mtd_type == gst_analytics_od_mtd_get_mtd_type ());
|
|
|
|
gst_analytics_od_mtd_get_location ((GstAnalyticsODMtd *) & mtd, &_x, &_y, &_w,
|
|
&_h, &_loc_conf_lvl);
|
|
fail_unless (_x == 50);
|
|
fail_unless (_y == 21);
|
|
fail_unless (_w == 11);
|
|
fail_unless (_h == 16);
|
|
fail_unless (_loc_conf_lvl == 0.7f);
|
|
|
|
GST_LOG ("mtd_type:%s", gst_analytics_mtd_type_get_name (mtd_type));
|
|
|
|
/* Verify the relatable metadata 2 is of correct type
|
|
* (ObjectDetection).
|
|
*/
|
|
gst_analytics_relation_meta_get_mtd (rmeta, ids[1], 0, &mtd);
|
|
mtd_type = gst_analytics_mtd_get_mtd_type (&mtd);
|
|
fail_unless (mtd_type == gst_analytics_cls_mtd_get_mtd_type ());
|
|
|
|
/* Verify data of the CLASSIFICATION retrieved */
|
|
gint index =
|
|
gst_analytics_cls_mtd_get_index_by_quark ((GstAnalyticsClsMtd *) & mtd,
|
|
g_quark_from_string ("dog"));
|
|
lvl = gst_analytics_cls_mtd_get_level ((GstAnalyticsClsMtd *) & mtd, index);
|
|
GST_LOG ("dog %f [%d, %d %d, %d", lvl, _x, _y, _w, _h);
|
|
fail_unless (lvl == 0.1f);
|
|
|
|
/* Verify data of the CLASSIFICATION retrieved */
|
|
index =
|
|
gst_analytics_cls_mtd_get_index_by_quark ((GstAnalyticsClsMtd *) & mtd,
|
|
g_quark_from_string ("cat"));
|
|
lvl = gst_analytics_cls_mtd_get_level ((GstAnalyticsClsMtd *) & mtd, index);
|
|
GST_LOG ("mtd_type:%s", gst_analytics_mtd_type_get_name (mtd_type));
|
|
GST_LOG ("cat %f [%d, %d %d, %d", lvl, _x, _y, _w, _h);
|
|
fail_unless (lvl == 0.9f);
|
|
|
|
/* Retrieve relatable metadata related to the first object detection
|
|
* through a CONTAIN relation of type CLASSIFICATION
|
|
* Verify it's the first classification metadata
|
|
*/
|
|
gst_analytics_relation_meta_get_direct_related (rmeta, od_mtd[0].id,
|
|
GST_ANALYTICS_REL_TYPE_CONTAIN, gst_analytics_cls_mtd_get_mtd_type (),
|
|
&state, &mtd);
|
|
|
|
cls_id = gst_analytics_mtd_get_id (&mtd);
|
|
GST_LOG ("Obj:%d -> Cls:%d", od_mtd[0].id, cls_id);
|
|
fail_unless (cls_id == cls_mtd[0].id);
|
|
|
|
state = NULL;
|
|
/* Retrieve relatable metadata related to the second object detection
|
|
* through a CONTAIN relation of type CLASSIFICATION
|
|
* Verify it's the first classification metadata
|
|
*/
|
|
gst_analytics_relation_meta_get_direct_related (rmeta, od_mtd[1].id,
|
|
GST_ANALYTICS_REL_TYPE_CONTAIN, gst_analytics_cls_mtd_get_mtd_type (),
|
|
&state, &mtd);
|
|
cls_id = gst_analytics_mtd_get_id (&mtd);
|
|
|
|
GST_LOG ("Obj:%d -> Cls:%d", od_mtd[1].id, cls_id);
|
|
fail_unless (cls_id == cls_mtd[1].id);
|
|
|
|
cls_conf_lvl[dog_cls_index] = 0.2f;
|
|
cls_conf_lvl[cat_cls_index] = 0.8f;
|
|
class_quarks[0] = g_quark_from_string ("canine");
|
|
class_quarks[1] = g_quark_from_string ("feline");
|
|
gst_analytics_relation_meta_add_cls_mtd (rmeta, 2, cls_conf_lvl,
|
|
class_quarks, &cls_mtd[2]);
|
|
|
|
ret = gst_analytics_relation_meta_set_relation (rmeta,
|
|
GST_ANALYTICS_REL_TYPE_CONTAIN, od_mtd[1].id, cls_mtd[2].id);
|
|
|
|
state = NULL;
|
|
ret = gst_analytics_relation_meta_get_direct_related (rmeta, od_mtd[1].id,
|
|
GST_ANALYTICS_REL_TYPE_CONTAIN, gst_analytics_od_mtd_get_mtd_type (),
|
|
&state, &mtd);
|
|
|
|
fail_unless (ret == FALSE);
|
|
|
|
gst_buffer_unref (buf);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_add_tracking_meta)
|
|
{
|
|
/* Verify we can add tracking relatable meta to relation meta */
|
|
GstBuffer *buf1, *buf2;
|
|
GstAnalyticsRelationMetaInitParams init_params = { 5, 150 };
|
|
GstAnalyticsRelationMeta *rmeta;
|
|
GstAnalyticsTrackingMtd tracking_mtd;
|
|
guint tracking_id;
|
|
GstClockTime tracking_observation_time_1;
|
|
gboolean ret;
|
|
|
|
/* Verify we can add multiple trackings to relation metadata
|
|
*/
|
|
|
|
buf1 = gst_buffer_new ();
|
|
rmeta = gst_buffer_add_analytics_relation_meta_full (buf1, &init_params);
|
|
tracking_id = 1;
|
|
tracking_observation_time_1 = GST_BUFFER_TIMESTAMP (buf1);
|
|
ret = gst_analytics_relation_meta_add_tracking_mtd (rmeta, tracking_id,
|
|
tracking_observation_time_1, &tracking_mtd);
|
|
fail_unless (ret == TRUE);
|
|
|
|
gst_buffer_unref (buf1);
|
|
|
|
buf2 = gst_buffer_new ();
|
|
rmeta = gst_buffer_add_analytics_relation_meta_full (buf2, &init_params);
|
|
tracking_id = 1;
|
|
ret = gst_analytics_relation_meta_add_tracking_mtd (rmeta, tracking_id,
|
|
tracking_observation_time_1, &tracking_mtd);
|
|
fail_unless (ret == TRUE);
|
|
|
|
gst_buffer_unref (buf2);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_verify_mtd_clear)
|
|
{
|
|
/* This test use segmentation mtd but it's a general functionality of
|
|
* analytics-meta that _mtd_clear is called when buffer is freed.
|
|
* _mtd_clear should be called regardless if the buffer where relation-meta
|
|
* is attached is from a pool or not. This test verify that _mtd_clear is
|
|
* called when buffer where relation-meta is attached it not from a pool.
|
|
*/
|
|
GstBuffer *vbuf, *mbuf;
|
|
GstAnalyticsRelationMetaInitParams init_params = { 5, 150 };
|
|
GstAnalyticsRelationMeta *rmeta;
|
|
GstBufferPool *mpool;
|
|
GstCaps *caps;
|
|
GstStructure *config;
|
|
GstVideoInfo minfo;
|
|
GstAnalyticsSegmentationMtd smtd;
|
|
GstBufferPoolAcquireParams pool_acq_params = { 0, };
|
|
pool_acq_params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
|
|
|
|
vbuf = gst_buffer_new ();
|
|
rmeta = gst_buffer_add_analytics_relation_meta_full (vbuf, &init_params);
|
|
|
|
/* Create pool for segmentation masks */
|
|
gst_video_info_init (&minfo);
|
|
gst_video_info_set_format (&minfo, GST_VIDEO_FORMAT_GRAY8, 32, 32);
|
|
caps = gst_video_info_to_caps (&minfo);
|
|
mpool = gst_video_buffer_pool_new ();
|
|
config = gst_buffer_pool_get_config (mpool);
|
|
|
|
/* Here we intentionnaly create a pool of only one element to validate the
|
|
* buffer used to store the masks is returned to the pool when the video
|
|
* buffer to which it is attached is unreffed with the intention of having
|
|
* gst_buffer_pool_acquire_buffer (mpool,...) fail if it didn't happen.*/
|
|
gst_buffer_pool_config_set_params (config, caps, minfo.size, 0, 1);
|
|
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
|
gst_buffer_pool_set_config (mpool, config);
|
|
gst_buffer_pool_set_active (mpool, TRUE);
|
|
gst_caps_unref (caps);
|
|
|
|
fail_unless (gst_buffer_pool_acquire_buffer (mpool, &mbuf,
|
|
&pool_acq_params) == GST_FLOW_OK);
|
|
|
|
/* Here we pretend the masks contain 2 region types [2,3] */
|
|
static const gsize region_count = 2;
|
|
guint region_ids[] = { 2, 3 };
|
|
|
|
gst_analytics_relation_meta_add_segmentation_mtd (rmeta, mbuf,
|
|
GST_SEGMENTATION_TYPE_INSTANCE, region_count, region_ids, 0, 0, 0, 0,
|
|
&smtd);
|
|
|
|
/* This _unref will dispose vbuf and also mbuf to mpool
|
|
* because GstAnalyticsSegmentationMtd define a
|
|
* GstAnalyticsMtdImpl::mtd_meta_clear */
|
|
gst_buffer_unref (vbuf);
|
|
|
|
/* This will succeed because mbuf was returned to the pool. If this
|
|
* test fail it highlight a memory managemnt failure in analytics-meta.*/
|
|
fail_unless (gst_buffer_pool_acquire_buffer (mpool, &mbuf,
|
|
&pool_acq_params) == GST_FLOW_OK);
|
|
|
|
gst_buffer_unref (mbuf);
|
|
gst_buffer_pool_set_active (mpool, FALSE);
|
|
gst_object_unref (mpool);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_add_segmentation_meta)
|
|
{
|
|
/*
|
|
* This a very simple test that add a segmentation analytics-meta
|
|
* to a buffer. In this test the masks have the same resolution as
|
|
* the buffer. It verify that masks (GstBuffer) memory management by
|
|
* validating the GstBuffer was returned to the pool by
|
|
*/
|
|
GstBuffer *vbuf, *mbuf;
|
|
GstAnalyticsRelationMetaInitParams init_params = { 5, 150 };
|
|
GstAnalyticsRelationMeta *rmeta;
|
|
GstBufferPool *vpool, *mpool;
|
|
GstCaps *caps;
|
|
GstStructure *config;
|
|
GstVideoInfo vinfo, minfo;
|
|
GstAnalyticsSegmentationMtd smtd;
|
|
|
|
/* Create a pool for video frames */
|
|
gst_video_info_init (&vinfo);
|
|
vpool = gst_video_buffer_pool_new ();
|
|
config = gst_buffer_pool_get_config (vpool);
|
|
gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_RGBA, 32, 32);
|
|
caps = gst_video_info_to_caps (&vinfo);
|
|
gst_buffer_pool_config_set_params (config, caps, vinfo.size, 0, 0);
|
|
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
|
gst_buffer_pool_set_config (vpool, config);
|
|
gst_buffer_pool_set_active (vpool, TRUE);
|
|
gst_caps_unref (caps);
|
|
|
|
fail_unless (gst_buffer_pool_acquire_buffer (vpool, &vbuf, NULL) ==
|
|
GST_FLOW_OK);
|
|
|
|
rmeta = gst_buffer_add_analytics_relation_meta_full (vbuf, &init_params);
|
|
|
|
/* Create pool for segmentation masks */
|
|
gst_video_info_init (&minfo);
|
|
gst_video_info_set_format (&minfo, GST_VIDEO_FORMAT_GRAY8, 32, 32);
|
|
caps = gst_video_info_to_caps (&minfo);
|
|
mpool = gst_video_buffer_pool_new ();
|
|
config = gst_buffer_pool_get_config (mpool);
|
|
|
|
/* Here we intentionnaly create a pool of only one element to validate the
|
|
* buffer used to store the masks is returned to the pool when the video
|
|
* buffer to which it is attached is unreffed with the intention of having
|
|
* gst_buffer_pool_acquire_buffer (mpool,...) fail if it didn't happen.*/
|
|
gst_buffer_pool_config_set_params (config, caps, minfo.size, 0, 1);
|
|
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
|
gst_buffer_pool_set_config (mpool, config);
|
|
gst_buffer_pool_set_active (mpool, TRUE);
|
|
gst_caps_unref (caps);
|
|
|
|
fail_unless (gst_buffer_pool_acquire_buffer (mpool, &mbuf, NULL) ==
|
|
GST_FLOW_OK);
|
|
|
|
/* Here we pretend the masks contain 2 region types [2,3] */
|
|
static const gsize region_count = 2;
|
|
guint region_ids[] = { 2, 3 };
|
|
|
|
gst_analytics_relation_meta_add_segmentation_mtd (rmeta, mbuf,
|
|
GST_SEGMENTATION_TYPE_INSTANCE, region_count, region_ids, 0, 0, 0, 0,
|
|
&smtd);
|
|
|
|
/* This _unref will return vbuf to vpool and also mbuf to mpool
|
|
* because GstAnalyticsSegmentationMtd define a
|
|
* GstAnalyticsMtdImpl::mtd_meta_clear */
|
|
gst_buffer_unref (vbuf);
|
|
|
|
/* This will succeed because mbuf was returned to the pool. If this
|
|
* test fail it highlight a memory managemnt failure in analytics-meta.*/
|
|
fail_unless (gst_buffer_pool_acquire_buffer (mpool, &mbuf, NULL) ==
|
|
GST_FLOW_OK);
|
|
|
|
gst_buffer_unref (mbuf);
|
|
gst_buffer_pool_set_active (mpool, FALSE);
|
|
gst_object_unref (mpool);
|
|
gst_buffer_pool_set_active (vpool, FALSE);
|
|
gst_object_unref (vpool);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (test_associate_segmentation_meta)
|
|
{
|
|
/* This test verify that classification can be associated to segmentation.
|
|
* More specifically we use a grayscale image that contain 2 set of
|
|
* imbricated pattern. The segmentation problem is simplified by having a
|
|
* specific value for each region. In a sense the original image is already
|
|
* segmented to avoid to do a real segmentation, since the goal of this test
|
|
* is to very segmentation analytics-meta API.
|
|
*
|
|
* Original image: 32x24 grayscale
|
|
* Segmentation input: 16x16 grayscale
|
|
* Segmentation output: 16x16 tensor (where each value correspond to a region
|
|
* id in the input)
|
|
*/
|
|
|
|
GstBuffer *vbuf, *mbuf;
|
|
GstAnalyticsRelationMetaInitParams init_params = { 5, 150 };
|
|
GstAnalyticsRelationMeta *rmeta;
|
|
GstBufferPool *vpool, *mpool;
|
|
GstCaps *caps;
|
|
GstStructure *config;
|
|
GstVideoInfo vinfo, minfo;
|
|
GstAnalyticsSegmentationMtd smtd;
|
|
GstAnalyticsClsMtd clsmtd;
|
|
|
|
/* Create a pool for video frames */
|
|
gst_video_info_init (&vinfo);
|
|
vpool = gst_video_buffer_pool_new ();
|
|
config = gst_buffer_pool_get_config (vpool);
|
|
gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_GRAY8, 32, 24);
|
|
caps = gst_video_info_to_caps (&vinfo);
|
|
gst_buffer_pool_config_set_params (config, caps, vinfo.size, 0, 0);
|
|
gst_buffer_pool_set_config (vpool, config);
|
|
gst_buffer_pool_set_active (vpool, TRUE);
|
|
gst_caps_unref (caps);
|
|
|
|
fail_unless (gst_buffer_pool_acquire_buffer (vpool, &vbuf, NULL) ==
|
|
GST_FLOW_OK);
|
|
|
|
/* This image a 32 x 24, GRAY8 that contain └ and ┐ that are imbricated.
|
|
* └ is formed by pixels values of: 9 and 7.
|
|
* ┐ is formed by pixels values of: 8 and 6.
|
|
* 9 and 8 are imbricated and 7 and 6 are impbricated. Pixel values [6,7,8,9],
|
|
* have no importance.
|
|
*/
|
|
|
|
guint8 img[] = {
|
|
/* 0|0|0|0|0|0|0|0|0|0|1|1|1|1|1|1|1|1|1|1|2|2|2|2|2|2|2|2|2|2|3|3 */
|
|
/* 0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1 */
|
|
/* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 2 */ 0, 0, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 3 */ 0, 0, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 4 */ 0, 0, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 5 */ 0, 0, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 6 */ 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 7 */ 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 8 */ 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 9 */ 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 11 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 12 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 6, 6,
|
|
6, 6, 6, 6, 6, 6, 0, 0, 0, 0,
|
|
/* 13 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 6, 6,
|
|
6, 6, 6, 6, 6, 6, 0, 0, 0, 0,
|
|
/* 14 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 6, 6,
|
|
6, 6, 6, 6, 6, 6, 0, 0, 0, 0,
|
|
/* 15 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 6, 6,
|
|
6, 6, 6, 6, 6, 6, 0, 0, 0, 0,
|
|
/* 16 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7,
|
|
7, 7, 6, 6, 6, 6, 0, 0, 0, 0,
|
|
/* 17 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7,
|
|
7, 7, 6, 6, 6, 6, 0, 0, 0, 0,
|
|
/* 18 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7,
|
|
7, 7, 6, 6, 6, 6, 0, 0, 0, 0,
|
|
/* 19 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7,
|
|
7, 7, 6, 6, 6, 6, 0, 0, 0, 0,
|
|
/* 20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 21 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 22 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 23 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
};
|
|
|
|
/* Pre-processing step 1 will convert the original image to segmentation
|
|
* processing format.
|
|
*
|
|
* Decimation (32x24) -> (16x12)
|
|
0|0|0|0|0|0|0|0|0|0|1|1|1|1|1|1|
|
|
0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|
|
|
|
|
0 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
1 0,9,9,8,8,8,8,0,0,0,0,0,0,0,0,0,
|
|
2 0,9,9,8,8,8,8,0,0,0,0,0,0,0,0,0,
|
|
3 0,9,9,9,9,8,8,0,0,0,0,0,0,0,0,0,
|
|
4 0,9,9,9,9,8,8,0,0,0,0,0,0,0,0,0,
|
|
5 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
6 0,0,0,0,0,0,0,0,7,7,6,6,6,6,0,0,
|
|
7 0,0,0,0,0,0,0,0,7,7,6,6,6,6,0,0,
|
|
8 0,0,0,0,0,0,0,0,7,7,7,7,6,6,0,0,
|
|
9 0,0,0,0,0,0,0,0,7,7,7,7,6,6,0,0,
|
|
10 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
11 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, */
|
|
|
|
|
|
/* Pre-processing step 2: Add padding match segmentation input format
|
|
* Padding top-bottom (16x12) -> (16x16)
|
|
*
|
|
0|0|0|0|0|0|0|0|0|0|1|1|1|1|1|1|
|
|
0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|
|
|
|
|
0 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, Padding line
|
|
1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, Padding line
|
|
1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
3 0,9,9,8,8,8,8,0,0,0,0,0,0,0,0,0,
|
|
4 0,9,9,8,8,8,8,0,0,0,0,0,0,0,0,0,
|
|
5 0,9,9,9,9,8,8,0,0,0,0,0,0,0,0,0,
|
|
6 0,9,9,9,9,8,8,0,0,0,0,0,0,0,0,0,
|
|
7 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
8 0,0,0,0,0,0,0,0,7,7,6,6,6,6,0,0,
|
|
9 0,0,0,0,0,0,0,0,7,7,6,6,6,6,0,0,
|
|
10 0,0,0,0,0,0,0,0,7,7,7,7,6,6,0,0,
|
|
11 0,0,0,0,0,0,0,0,7,7,7,7,6,6,0,0,
|
|
12 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
13 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
14 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, Padding line
|
|
15 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, Padding line */
|
|
|
|
|
|
/* Post-processing remove area of the output that correspond to padding
|
|
* area in the input. In the following array 2, 3, 4, 5 correspond to
|
|
* segmented region ids.*/
|
|
guint8 post_proc_segmasks[] = {
|
|
/* 0|0|0|0|0|0|0|0|0|0|1|1|1|1|1|1| */
|
|
/* 0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5| */
|
|
/* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 1 */ 0, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 2 */ 0, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 3 */ 0, 2, 2, 2, 2, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 4 */ 0, 2, 2, 2, 2, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 5 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 6 */ 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 5, 5, 5, 5, 0, 0,
|
|
/* 7 */ 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 5, 5, 5, 5, 0, 0,
|
|
/* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 5, 5, 0, 0,
|
|
/* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 5, 5, 0, 0,
|
|
/* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 11 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
};
|
|
|
|
/* Creating analytics-relation meta to host analytics results */
|
|
rmeta = gst_buffer_add_analytics_relation_meta_full (vbuf, &init_params);
|
|
|
|
/* Create pool for segmentation masks */
|
|
gst_video_info_init (&minfo);
|
|
gst_video_info_set_format (&minfo, GST_VIDEO_FORMAT_GRAY8, 32, 24);
|
|
caps = gst_video_info_to_caps (&minfo);
|
|
mpool = gst_video_buffer_pool_new ();
|
|
config = gst_buffer_pool_get_config (mpool);
|
|
|
|
gst_buffer_pool_config_set_params (config, caps, minfo.size, 1, 0);
|
|
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
|
gst_buffer_pool_set_config (mpool, config);
|
|
gst_buffer_pool_set_active (mpool, TRUE);
|
|
gst_caps_unref (caps);
|
|
|
|
fail_unless (gst_buffer_pool_acquire_buffer (mpool, &mbuf, NULL) ==
|
|
GST_FLOW_OK);
|
|
|
|
gst_buffer_fill (mbuf, 0, post_proc_segmasks, 32 * 24);
|
|
|
|
/* Masks contain 5 region types [0,1,2,3,4]. We intentionnally change the
|
|
* order of region ids relative to their appearance in the output to
|
|
* show that API does not depend on any order or continuity. */
|
|
static const gsize region_count = 5;
|
|
guint region_ids[5];
|
|
|
|
/* Confidence levels are irrelevant in this context. */
|
|
gfloat confi[] = { 1.0, 1.0, 1.0, 1.0, 1.0 };
|
|
GQuark classes[5];
|
|
|
|
/* It's important that region index and classification index match. This
|
|
* is how a region is associated to a specific class.
|
|
*
|
|
* Region-id-0 correspond to region-index-0 is associated to class
|
|
* "background".
|
|
* Region-id-5 correspond to region-index-1 is associated to class
|
|
* "top-right-corner". ┐
|
|
* Region-id-2 correspond to region-index-2 is associated to class
|
|
* "bottom-left-corner". └
|
|
* Region-id-3 correspond to region-index-3 is associated to class
|
|
* "top-right-corner". ┐
|
|
* Region-id-4 correspond to region-index-4 is associated to class
|
|
* "bottom-left-corner". └ */
|
|
region_ids[0] = 0;
|
|
classes[0] = g_quark_from_string ("background");
|
|
|
|
region_ids[1] = 5;
|
|
classes[1] = g_quark_from_string ("top-right-corner");
|
|
|
|
region_ids[2] = 2;
|
|
classes[2] = g_quark_from_string ("bottom-left-corner");
|
|
|
|
region_ids[3] = 3;
|
|
classes[3] = g_quark_from_string ("top-right-corner");
|
|
|
|
region_ids[4] = 4;
|
|
classes[4] = g_quark_from_string ("bottom-left-corner");
|
|
|
|
gst_analytics_relation_meta_add_segmentation_mtd (rmeta, mbuf,
|
|
GST_SEGMENTATION_TYPE_INSTANCE, region_count, region_ids, 0, 0, 0, 0,
|
|
&smtd);
|
|
|
|
gst_analytics_relation_meta_add_cls_mtd (rmeta, region_count, confi,
|
|
classes, &clsmtd);
|
|
|
|
gst_analytics_relation_meta_set_relation (rmeta,
|
|
GST_ANALYTICS_REL_TYPE_RELATE_TO, smtd.id, clsmtd.id);
|
|
|
|
|
|
/* Generate a truth vector for segmented region and associated class. */
|
|
guint8 truth_vector_segmentation_id[768];
|
|
GQuark truth_vector_segmentation_classes[768];
|
|
|
|
for (gsize i = 0; i < 768; i++) {
|
|
if (img[i] == 9) {
|
|
truth_vector_segmentation_id[i] = 2;
|
|
truth_vector_segmentation_classes[i] =
|
|
g_quark_from_string ("bottom-left-corner");
|
|
} else if (img[i] == 8) {
|
|
truth_vector_segmentation_id[i] = 3;
|
|
truth_vector_segmentation_classes[i] =
|
|
g_quark_from_string ("top-right-corner");
|
|
} else if (img[i] == 7) {
|
|
truth_vector_segmentation_id[i] = 4;
|
|
truth_vector_segmentation_classes[i] =
|
|
g_quark_from_string ("bottom-left-corner");
|
|
} else if (img[i] == 6) {
|
|
truth_vector_segmentation_id[i] = 5;
|
|
truth_vector_segmentation_classes[i] =
|
|
g_quark_from_string ("top-right-corner");
|
|
} else {
|
|
truth_vector_segmentation_id[i] = 0;
|
|
truth_vector_segmentation_classes[i] = g_quark_from_string ("background");
|
|
}
|
|
}
|
|
|
|
/* Verify segmentation analytics-meta and associated classification
|
|
* match truth vectors */
|
|
gsize idx;
|
|
GstBufferMapInfo mmap_info; /* mask map info */
|
|
gst_buffer_map (mbuf, &mmap_info, GST_MAP_READ);
|
|
for (gsize r = 0; r < 24; r++) {
|
|
gsize mr = r / 2;
|
|
for (gsize c = 0; c < 32; c++) {
|
|
gsize mc = c / 2;
|
|
gsize mask_idx = mr * 16 + mc;
|
|
gsize img_idx = r * 32 + c;
|
|
|
|
fail_unless (mmap_info.data[mask_idx] ==
|
|
truth_vector_segmentation_id[img_idx]);
|
|
|
|
/* Retrieve segmentation region index */
|
|
fail_unless (gst_analytics_segmentation_mtd_get_region_index (&smtd,
|
|
&idx, mmap_info.data[mask_idx]) == TRUE);
|
|
|
|
/* Check that the _get_region_id() API is consistent */
|
|
fail_unless (gst_analytics_segmentation_mtd_get_region_id (&smtd,
|
|
idx) == mmap_info.data[mask_idx]);
|
|
|
|
/* Retrieve classification associated with region */
|
|
fail_unless (gst_analytics_relation_meta_get_direct_related (rmeta,
|
|
smtd.id, GST_ANALYTICS_REL_TYPE_RELATE_TO,
|
|
gst_analytics_cls_mtd_get_mtd_type (), NULL, &clsmtd));
|
|
|
|
/* Retrive class associated with segmentation region */
|
|
fail_unless (gst_analytics_cls_mtd_get_length (&clsmtd) ==
|
|
gst_analytics_segmentation_mtd_get_region_count (&smtd));
|
|
|
|
/* Retrieve class associated with segmentation region */
|
|
fail_unless (gst_analytics_cls_mtd_get_quark (&clsmtd, idx) ==
|
|
truth_vector_segmentation_classes[img_idx]);
|
|
}
|
|
}
|
|
gst_buffer_unmap (mbuf, &mmap_info);
|
|
|
|
|
|
/* This _unref will return vbuf to vpool and also mbuf to mpool
|
|
* because GstAnalyticsSegmentationMtd define a
|
|
* GstAnalyticsMtdImpl::mtd_meta_clear */
|
|
gst_buffer_unref (vbuf);
|
|
|
|
gst_buffer_pool_set_active (mpool, FALSE);
|
|
gst_object_unref (mpool);
|
|
gst_buffer_pool_set_active (vpool, FALSE);
|
|
gst_object_unref (vpool);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
static Suite *
|
|
analyticmeta_suite (void)
|
|
{
|
|
|
|
Suite *s;
|
|
TCase *tc_chain_cls;
|
|
TCase *tc_chain_relation;
|
|
TCase *tc_chain_od;
|
|
TCase *tc_chain_od_cls;
|
|
TCase *tc_chain_tracking;
|
|
TCase *tc_chain_segmentation;
|
|
|
|
s = suite_create ("Analytic Meta Library");
|
|
|
|
tc_chain_cls = tcase_create ("Classification Mtd");
|
|
suite_add_tcase (s, tc_chain_cls);
|
|
tcase_add_test (tc_chain_cls, test_add_classification_meta);
|
|
tcase_add_test (tc_chain_cls, test_classification_meta_classes);
|
|
|
|
tcase_add_test (tc_chain_cls, test_meta_pooled);
|
|
|
|
tc_chain_relation = tcase_create ("Relation Meta");
|
|
suite_add_tcase (s, tc_chain_relation);
|
|
tcase_add_test (tc_chain_relation, test_add_relation_meta);
|
|
tcase_add_test (tc_chain_relation,
|
|
test_add_relation_inefficiency_reporting_cases);
|
|
tcase_add_test (tc_chain_relation, test_query_relation_meta_cases);
|
|
tcase_add_test (tc_chain_relation, test_path_relation_meta);
|
|
tcase_add_test (tc_chain_relation, test_cyclic_relation_meta);
|
|
tcase_add_test (tc_chain_relation, test_verify_mtd_clear);
|
|
|
|
tc_chain_od = tcase_create ("Object Detection Mtd");
|
|
suite_add_tcase (s, tc_chain_od);
|
|
tcase_add_test (tc_chain_od, test_add_od_meta);
|
|
tcase_add_test (tc_chain_od, test_add_oriented_od_meta);
|
|
tcase_add_test (tc_chain_od, test_od_meta_fields);
|
|
tcase_add_test (tc_chain_od, test_oriented_od_meta_fields);
|
|
tcase_add_test (tc_chain_od,
|
|
test_add_non_oriented_get_oriented_od_meta_fields);
|
|
tcase_add_test (tc_chain_od,
|
|
test_add_oriented_get_non_oriented_od_meta_fields);
|
|
|
|
tc_chain_od_cls = tcase_create ("Object Detection <-> Classification Mtd");
|
|
suite_add_tcase (s, tc_chain_od_cls);
|
|
tcase_add_test (tc_chain_od_cls, test_od_cls_relation);
|
|
tcase_add_test (tc_chain_od_cls, test_multi_od_cls_relation);
|
|
|
|
tc_chain_tracking = tcase_create ("Tracking Mtd");
|
|
suite_add_tcase (s, tc_chain_tracking);
|
|
tcase_add_test (tc_chain_tracking, test_add_tracking_meta);
|
|
|
|
tc_chain_segmentation = tcase_create ("Segmentation Mtd");
|
|
suite_add_tcase (s, tc_chain_segmentation);
|
|
tcase_add_test (tc_chain_segmentation, test_add_segmentation_meta);
|
|
tcase_add_test (tc_chain_segmentation, test_associate_segmentation_meta);
|
|
|
|
return s;
|
|
}
|
|
|
|
GST_CHECK_MAIN (analyticmeta);
|