This patch removes dependency from Bounding box class to properties.
setBoxDecodingMode does not need to be modified even if a new box property added.
Signed-off-by: Yelin Jeong <yelini.jeong@samsung.com>
#define H_SCALE_DEFAULT (5.0f)
#define W_SCALE_DEFAULT (5.0f)
+#define BOX_SIZE (4)
+#define DETECTION_MAX (2034) /* add ssd_mobilenet v3 support */
+#define PARAMS_MAX (6)
+
#define _expit(x) (1.f / (1.f + expf (-((float) x))))
/**
+ * @brief Class for MobilenetSSD box properties
+ */
+class MobilenetSSD : public BoxProperties
+{
+ public:
+ MobilenetSSD ();
+ ~MobilenetSSD ();
+ int mobilenet_ssd_loadBoxPrior ();
+
+ int setOptionInternal (const char *param);
+ int checkCompatible (const GstTensorsConfig *config);
+ GArray *decode (const GstTensorsConfig *config, const GstTensorMemory *input);
+
+ private:
+ char *box_prior_path; /**< Box Prior file path */
+ gfloat box_priors[BOX_SIZE][DETECTION_MAX + 1]; /** loaded box prior */
+ gfloat params[PARAMS_MAX]; /** Post Processing parameters */
+ gfloat sigmoid_threshold; /** Inverse value of valid detection threshold in sigmoid domain */
+};
+
+/**
* @brief C++-Template-like box location calculation for box-priors
* @bug This is not macro-argument safe. Use paranthesis!
* @param[in] bb The configuration, "bounding_boxes"
return log (x / (1.0 - x));
}
+static BoxProperties *mobilenet = nullptr;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+void init_properties_mobilenetssd (void) __attribute__ ((constructor));
+void fini_properties_mobilenetssd (void) __attribute__ ((destructor));
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
/** @brief Constructor of MobilenetSSD */
MobilenetSSD::MobilenetSSD ()
{
max_detection = 0;
total_labels = 0;
box_prior_path = nullptr;
+ name = g_strdup_printf ("mobilenet-ssd");
+}
+
+/** @brief Destructor of MobilenetSSD */
+MobilenetSSD::~MobilenetSSD ()
+{
+ g_free (name);
}
/**
nms (results, params[IOU_THRESHOLD_IDX]);
return results;
}
+
+/** @brief Initialize this object for tensor decoder bounding box */
+void
+init_properties_mobilenetssd ()
+{
+ mobilenet = new MobilenetSSD ();
+ BoundingBox::addProperties (mobilenet);
+}
+
+/** @brief Destruct this object for tensor decoder bounding box */
+void
+fini_properties_mobilenetssd ()
+{
+ delete mobilenet;
+}
#define CLASSES_IDX (1)
#define SCORES_IDX (2)
#define NUM_IDX (3)
+#define MAX_TENSORS (4U)
#define LOCATIONS_DEFAULT (3)
#define CLASSES_DEFAULT (1)
#define THRESHOLD_DEFAULT (G_MINFLOAT)
/**
+ * @brief Class for MobilenetSSDPP box properties
+ */
+class MobilenetSSDPP : public BoxProperties
+{
+ public:
+ MobilenetSSDPP ();
+ ~MobilenetSSDPP ();
+ int get_mobilenet_ssd_pp_tensor_idx (int idx);
+
+ int setOptionInternal (const char *param);
+ int checkCompatible (const GstTensorsConfig *config);
+ GArray *decode (const GstTensorsConfig *config, const GstTensorMemory *input);
+
+ private:
+ gint tensor_mapping[MAX_TENSORS]; /* Output tensor index mapping */
+ gfloat threshold; /* Detection threshold */
+};
+
+/**
* @brief C++-Template-like box location calculation for Tensorflow SSD model
* @param[in] type The tensor type of inputptr
* @param[in] typename nnstreamer enum corresponding to the type
_get_objects_mobilenet_ssd_pp (type, typename, (mem_num->data), (mem_classes->data), \
(mem_scores->data), (mem_boxes->data), config, results, i_width, i_height)
+static BoxProperties *mobilenetpp = nullptr;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+void init_properties_mobilenetssd_pp (void) __attribute__ ((constructor));
+void fini_properties_mobilenetssd_pp (void) __attribute__ ((destructor));
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
/**
* @brief MOBILENET SSD PostProcess Output tensor feature mapping.
*/
MOBILENET_SSD_PP_BBOX_IDX_UNKNOWN
} mobilenet_ssd_pp_bbox_idx_t;
+
+/** @brief Constructor of MobilenetSSDPP */
MobilenetSSDPP::MobilenetSSDPP ()
{
tensor_mapping[LOCATIONS_IDX] = LOCATIONS_DEFAULT;
tensor_mapping[SCORES_IDX] = SCORES_DEFAULT;
tensor_mapping[NUM_IDX] = NUM_DEFAULT;
threshold = THRESHOLD_DEFAULT;
+ name = g_strdup_printf ("mobilenet-ssd-postprocess");
+}
+
+
+/** @brief Destructor of MobilenetSSDPP */
+MobilenetSSDPP::~MobilenetSSDPP ()
+{
+ g_free (name);
}
/** @brief Helper to retrieve tensor index by feature */
}
return results;
}
+
+/** @brief Initialize this object for tensor decoder bounding box */
+void
+init_properties_mobilenetssd_pp ()
+{
+ mobilenetpp = new MobilenetSSDPP ();
+ BoundingBox::addProperties (mobilenetpp);
+}
+
+/** @brief Destruct this object for tensor decoder bounding box */
+void
+fini_properties_mobilenetssd_pp ()
+{
+ delete mobilenetpp;
+}
#define MIN_SCORE_THRESHOLD_DEFAULT (0.5)
#define PARAMS_STRIDE_SIZE (8)
+#define PARAMS_MAX (13)
+
+/**
+ * @brief Class for MpPalmDetection box properties
+ */
+class MpPalmDetection : public BoxProperties
+{
+ public:
+ MpPalmDetection ();
+ ~MpPalmDetection ();
+ void mp_palm_detection_generate_anchors ();
+ int setOptionInternal (const char *param);
+ int checkCompatible (const GstTensorsConfig *config);
+
+ GArray *decode (const GstTensorsConfig *config, const GstTensorMemory *input);
+
+ private:
+ gint num_layers;
+ /** Number of stride layers */
+ gfloat min_scale; /** Minimum scale */
+ gfloat max_scale; /** Maximum scale */
+ gfloat offset_x; /** anchor X offset */
+ gfloat offset_y; /** anchor Y offset */
+ gint strides[PARAMS_MAX]; /** Stride data for each layers */
+ gfloat min_score_threshold; /** minimum threshold of score */
+
+ GArray *anchors;
+};
/**
* @brief C++-Template-like box location calculation for Tensorflow model
}
}
+static BoxProperties *mp_palm_detection = nullptr;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+void init_properties_mp_palm_detection (void) __attribute__ ((constructor));
+void fini_properties_mp_palm_detection (void) __attribute__ ((destructor));
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
/**
* @brief Generate anchor information
*/
strides[3] = STRIDE_3_DEFAULT;
min_score_threshold = MIN_SCORE_THRESHOLD_DEFAULT;
anchors = g_array_new (FALSE, TRUE, sizeof (anchor));
+ name = g_strdup_printf ("mp-palm-detection");
}
/** @brief Destructor of MpPalmDetection */
if (anchors)
g_array_free (anchors, TRUE);
anchors = NULL;
+ g_free (name);
}
/** @brief Set internal option of MpPalmDetection
nms (results, 0.05f);
return results;
}
+
+/** @brief Initialize this object for tensor decoder bounding box */
+void
+init_properties_mp_palm_detection ()
+{
+ mp_palm_detection = new MpPalmDetection ();
+ BoundingBox::addProperties (mp_palm_detection);
+}
+
+/** @brief Destruct this object for tensor decoder bounding box */
+void
+fini_properties_mp_palm_detection ()
+{
+ delete mp_palm_detection;
+}
#include "../tensordec-boundingbox.h"
#define OV_PERSON_DETECTION_CONF_THRESHOLD (0.8)
+#define DETECTION_MAX (200U)
+#define DEFAULT_MAX_TENSORS (1)
+#define DEFAULT_SIZE_DETECTION_DESC (7)
+
+/**
+ * @brief Class for OVDetection box properties
+ */
+class OVDetection : public BoxProperties
+{
+ public:
+ OVDetection ();
+ ~OVDetection ();
+ int setOptionInternal (const char *param)
+ {
+ UNUSED (param);
+ return TRUE;
+ }
+ int checkCompatible (const GstTensorsConfig *config);
+ GArray *decode (const GstTensorsConfig *config, const GstTensorMemory *input);
+};
+
/**
* @brief C++-Template-like box location calculation for OpenVino Person Detection Model
* @param[in] type The tensor type of inputptr
} \
break
+static BoxProperties *ov_detection = nullptr;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+void init_properties_ovdetection (void) __attribute__ ((constructor));
+void fini_properties_ovdetection (void) __attribute__ ((destructor));
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/** @brief Constructor of OVDetection */
+OVDetection::OVDetection ()
+{
+ name = g_strdup_printf ("ov-person-detection");
+}
+
+/** @brief Destructor of OVDetection */
+OVDetection::~OVDetection ()
+{
+ g_free (name);
+}
+
/** @brief Check compatibility of given tensors config */
int
OVDetection::checkCompatible (const GstTensorsConfig *config)
}
return results;
}
+
+/** @brief Initialize this object for tensor decoder bounding box */
+void
+init_properties_ovdetection ()
+{
+ ov_detection = new OVDetection ();
+ BoundingBox::addProperties (ov_detection);
+}
+
+/** @brief Destruct this object for tensor decoder bounding box */
+void
+fini_properties_ovdetection ()
+{
+ delete ov_detection;
+}
#define DEFAULT_DETECTION_NUM_INFO_YOLO5 (5)
#define DEFAULT_DETECTION_NUM_INFO_YOLO8 (4)
+/**
+ * @brief Class for YoloV5 box properties
+ */
+class YoloV5 : public BoxProperties
+{
+ public:
+ YoloV5 ();
+ ~YoloV5 ();
+ int setOptionInternal (const char *param);
+ int checkCompatible (const GstTensorsConfig *config);
+ GArray *decode (const GstTensorsConfig *config, const GstTensorMemory *input);
+
+ private:
+ /* From option3, whether the output values are scaled or not */
+ int scaled_output;
+ gfloat conf_threshold;
+ gfloat iou_threshold;
+};
+
+/**
+ * @brief Class for YoloV8 box properties
+ */
+class YoloV8 : public BoxProperties
+{
+ public:
+ YoloV8 ();
+ ~YoloV8 ();
+ int setOptionInternal (const char *param);
+ int checkCompatible (const GstTensorsConfig *config);
+ GArray *decode (const GstTensorsConfig *config, const GstTensorMemory *input);
+
+ private:
+ /* From option3, whether the output values are scaled or not */
+ int scaled_output;
+ gfloat conf_threshold;
+ gfloat iou_threshold;
+};
+
+static BoxProperties *yolo5 = nullptr;
+static BoxProperties *yolo8 = nullptr;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+void init_properties_yolo5 (void) __attribute__ ((constructor));
+void fini_properties_yolo5 (void) __attribute__ ((destructor));
+
+void init_properties_yolo8 (void) __attribute__ ((constructor));
+void fini_properties_yolo8 (void) __attribute__ ((destructor));
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
/** @brief Constructor of YoloV5 */
YoloV5::YoloV5 ()
{
scaled_output = 0;
conf_threshold = YOLO_DETECTION_CONF_THRESHOLD;
iou_threshold = YOLO_DETECTION_IOU_THRESHOLD;
+ name = g_strdup_printf ("yolov5");
+}
+
+/** @brief Destructor of YoloV5 */
+YoloV5::~YoloV5 ()
+{
+ g_free (name);
}
/** @brief Set internal option of YoloV5
scaled_output = 0;
conf_threshold = YOLO_DETECTION_CONF_THRESHOLD;
iou_threshold = YOLO_DETECTION_IOU_THRESHOLD;
+ name = g_strdup_printf ("yolov8");
+}
+
+/** @brief Destructor of YoloV8 */
+YoloV8::~YoloV8 ()
+{
+ g_free (name);
}
/** @brief Set internal option of YoloV8 */
nms (results, iou_threshold);
return results;
}
+
+/** @brief Initialize this object for tensor decoder bounding box */
+void
+init_properties_yolo5 ()
+{
+ yolo5 = new YoloV5 ();
+ BoundingBox::addProperties (yolo5);
+}
+
+/** @brief Destruct this object for tensor decoder bounding box */
+void
+fini_properties_yolo5 ()
+{
+ delete yolo5;
+}
+
+/** @brief Initialize this object for tensor decoder bounding box */
+void
+init_properties_yolo8 ()
+{
+ yolo8 = new YoloV8 ();
+ BoundingBox::addProperties (yolo8);
+}
+
+/** @brief Destruct this object for tensor decoder bounding box */
+void
+fini_properties_yolo8 ()
+{
+ delete yolo8;
+}
}
#endif /* __cplusplus */
+/**
+ * @brief mutex for box properties table.
+ */
+G_LOCK_DEFINE_STATIC (box_properties_table);
+
/* font.c */
extern uint8_t rasters[][13];
NULL,
};
+/**
+ * @brief Change deprecated mode name
+ */
+static const char *
+updateDecodingMode (const char *param)
+{
+ if (g_strcmp0 (param, bb_modes[OLDNAME_MOBILENET_SSD_BOUNDING_BOX]) == 0) {
+ return bb_modes[MOBILENET_SSD_BOUNDING_BOX];
+ }
+
+ if (g_strcmp0 (param, bb_modes[OLDNAME_MOBILENET_SSD_PP_BOUNDING_BOX]) == 0) {
+ return bb_modes[MOBILENET_SSD_PP_BOUNDING_BOX];
+ }
+
+ return param;
+}
+
/** @brief tensordec-plugin's GstTensorDecoderDef callback */
static int
bb_init (void **pdata)
if (label_path)
g_free (label_path);
- if (bdata) {
- delete bdata;
- bdata = nullptr;
- }
+ G_LOCK (box_properties_table);
+ g_hash_table_destroy (properties_table);
+ properties_table = nullptr;
+ G_UNLOCK (box_properties_table);
}
/**
int
BoundingBox::setBoxDecodingMode (const char *param)
{
- bounding_box_modes previous = mode;
-
if (NULL == param || *param == '\0') {
GST_ERROR ("Please set the valid mode at option1 to set box decoding mode");
return FALSE;
}
- mode = static_cast<bounding_box_modes> (find_key_strv (bb_modes, param));
-
- if (mode != previous && mode != BOUNDING_BOX_UNKNOWN) {
- if (previous != BOUNDING_BOX_UNKNOWN) {
- delete bdata;
- }
-
- switch (mode) {
- case MOBILENET_SSD_BOUNDING_BOX:
- case OLDNAME_MOBILENET_SSD_BOUNDING_BOX:
- bdata = new MobilenetSSD ();
- break;
- case MOBILENET_SSD_PP_BOUNDING_BOX:
- case OLDNAME_MOBILENET_SSD_PP_BOUNDING_BOX:
- bdata = new MobilenetSSDPP ();
- break;
- case OV_PERSON_DETECTION_BOUNDING_BOX:
- case OV_FACE_DETECTION_BOUNDING_BOX:
- bdata = new OVDetection ();
- break;
- case YOLOV5_BOUNDING_BOX:
- bdata = new YoloV5 ();
- break;
- case YOLOV8_BOUNDING_BOX:
- bdata = new YoloV8 ();
- break;
- case MP_PALM_DETECTION_BOUNDING_BOX:
- bdata = new MpPalmDetection ();
- break;
- default:
- return FALSE;
- }
+ bdata = getProperties (updateDecodingMode (param));
+ if (bdata == nullptr) {
+ nns_loge ("Could not find box properties name %s", param);
+ return FALSE;
}
return TRUE;
return GST_FLOW_ERROR;
}
+
+/**
+ * @brief Get bounding box properties from hash table
+ */
+BoxProperties *
+BoundingBox::getProperties (const gchar *properties_name)
+{
+ gpointer data;
+ G_LOCK (box_properties_table);
+ if (properties_table == nullptr) {
+ properties_table = g_hash_table_new (g_str_hash, g_str_equal);
+ }
+ data = g_hash_table_lookup (properties_table, properties_name);
+ G_UNLOCK (box_properties_table);
+
+ return static_cast<BoxProperties *> (data);
+}
+
+/**
+ * @brief Add bounding box properties into hash table
+ */
+gboolean
+BoundingBox::addProperties (BoxProperties *boxProperties)
+{
+ BoxProperties *data;
+ gboolean ret;
+
+ data = getProperties (boxProperties->name);
+ if (NULL != data) {
+ return TRUE;
+ }
+
+ G_LOCK (box_properties_table);
+ ret = g_hash_table_insert (properties_table, boxProperties->name, boxProperties);
+ G_UNLOCK (box_properties_table);
+
+ return ret;
+}
{
return i_height;
}
+ gchar *name;
protected:
guint i_width; /**< Input Video Width */
GstFlowReturn decode (const GstTensorsConfig *config,
const GstTensorMemory *input, GstBuffer *outbuf);
+ static BoxProperties *getProperties (const gchar *properties_name);
+ static gboolean addProperties (BoxProperties *boxProperties);
+
private:
bounding_box_modes mode;
BoxProperties *bdata;
gint do_log;
gboolean flag_use_label;
-};
-
-/**
- * @brief Class for MobilenetSSD box properties
- */
-class MobilenetSSD : public BoxProperties
-{
- public:
- MobilenetSSD ();
- int mobilenet_ssd_loadBoxPrior ();
-
- int setOptionInternal (const char *param);
- int checkCompatible (const GstTensorsConfig *config);
- GArray *decode (const GstTensorsConfig *config, const GstTensorMemory *input);
-
- static const int BOX_SIZE = 4;
- static const int DETECTION_MAX = 2034; /* add ssd_mobilenet v3 support */
- static const int PARAMS_MAX = 6;
-
- private:
- char *box_prior_path; /**< Box Prior file path */
- gfloat box_priors[BOX_SIZE][DETECTION_MAX + 1]; /** loaded box prior */
- gfloat params[PARAMS_MAX]; /** Post Processing parameters */
- gfloat sigmoid_threshold; /** Inverse value of valid detection threshold in sigmoid domain */
-};
-
-/**
- * @brief Class for MobilenetSSDPP box properties
- */
-class MobilenetSSDPP : public BoxProperties
-{
- public:
- MobilenetSSDPP ();
- int get_mobilenet_ssd_pp_tensor_idx (int idx);
-
- int setOptionInternal (const char *param);
- int checkCompatible (const GstTensorsConfig *config);
- GArray *decode (const GstTensorsConfig *config, const GstTensorMemory *input);
-
- static const guint MAX_TENSORS = 4U;
-
- private:
- gint tensor_mapping[MAX_TENSORS]; /* Output tensor index mapping */
- gfloat threshold; /* Detection threshold */
-};
-
-/**
- * @brief Class for OVDetection box properties
- */
-class OVDetection : public BoxProperties
-{
- public:
- int setOptionInternal (const char *param)
- {
- UNUSED (param);
- return TRUE;
- }
- int checkCompatible (const GstTensorsConfig *config);
- GArray *decode (const GstTensorsConfig *config, const GstTensorMemory *input);
-
- static const guint DETECTION_MAX = 200U;
- static const guint DEFAULT_MAX_TENSORS = 1;
- static const guint DEFAULT_SIZE_DETECTION_DESC = 7;
-};
-
-/**
- * @brief Class for YoloV5 box properties
- */
-class YoloV5 : public BoxProperties
-{
- public:
- YoloV5 ();
- int setOptionInternal (const char *param);
- int checkCompatible (const GstTensorsConfig *config);
- GArray *decode (const GstTensorsConfig *config, const GstTensorMemory *input);
- private:
- /* From option3, whether the output values are scaled or not */
- int scaled_output;
- gfloat conf_threshold;
- gfloat iou_threshold;
+ /* Table for box properties data */
+ inline static GHashTable *properties_table;
};
-/**
- * @brief Class for YoloV8 box properties
- */
-class YoloV8 : public BoxProperties
-{
- public:
- YoloV8 ();
- int setOptionInternal (const char *param);
- int checkCompatible (const GstTensorsConfig *config);
- GArray *decode (const GstTensorsConfig *config, const GstTensorMemory *input);
-
- private:
- /* From option3, whether the output values are scaled or not */
- int scaled_output;
- gfloat conf_threshold;
- gfloat iou_threshold;
-};
-
-/**
- * @brief Class for MpPalmDetection box properties
- */
-class MpPalmDetection : public BoxProperties
-{
- public:
- MpPalmDetection ();
- ~MpPalmDetection ();
- void mp_palm_detection_generate_anchors ();
- int setOptionInternal (const char *param);
- int checkCompatible (const GstTensorsConfig *config);
-
- GArray *decode (const GstTensorsConfig *config, const GstTensorMemory *input);
-
- static const int PARAMS_MAX = 13;
-
- private:
- gint num_layers;
- /** Number of stride layers */
- gfloat min_scale; /** Minimum scale */
- gfloat max_scale; /** Maximum scale */
- gfloat offset_x; /** anchor X offset */
- gfloat offset_y; /** anchor Y offset */
- gint strides[PARAMS_MAX]; /** Stride data for each layers */
- gfloat min_score_threshold; /** minimum threshold of score */
-
- GArray *anchors;
-};
#endif /* _TENSORDECBB_H__ */