mv_machine_learning: introduce engine configuration api for object detection
authorInki Dae <inki.dae@samsung.com>
Fri, 17 Mar 2023 02:20:59 +0000 (11:20 +0900)
committerKwanghoon Son <k.son@samsung.com>
Wed, 22 Mar 2023 04:10:03 +0000 (13:10 +0900)
[Issue type] : new feature

Introduced inference engine configuration task API, which allows user to
set user desired inference engine and its device type for inference
request. Regarding this, this patch adds below itask interfaces,
- setEngineInfo
      . Set user desired inference engine and its device type.
    - getNumberOfEngine
      . Get how many inference engines are available for a given task API.
    - getEngineType
      . Get inference engine type to a given index.
    - getNumberOfDevice
      . Get how many device types are available for a given inference engine.
    - getDeviceType
      . Get device type with a given index.

Object detection task group supports for various concrete classes which
have specific decoders so strategy pattern is used to change each
concrete class object corresponding to a given model type in runtime.

Change-Id: I91c9b75061fb6019eda8984446906417f2da116f
Signed-off-by: Inki Dae <inki.dae@samsung.com>
include/mv_image_classification_internal.h
include/mv_object_detection_internal.h
mv_machine_learning/image_classification/include/mv_image_classification_open.h
mv_machine_learning/object_detection/include/mv_object_detection_open.h
mv_machine_learning/object_detection/include/object_detection.h
mv_machine_learning/object_detection/src/mv_object_detection.c
mv_machine_learning/object_detection/src/mv_object_detection_open.cpp
mv_machine_learning/object_detection/src/object_detection.cpp
mv_machine_learning/object_detection/src/object_detection_adapter.cpp
test/testsuites/machine_learning/object_detection/test_object_detection.cpp

index 19bb3d3..cdc84b5 100644 (file)
@@ -219,7 +219,7 @@ int mv_image_classification_get_engine_type(mv_image_classification_h handle, co
                                                                                        char **engine_type);
 
 /**
-        * @brief Get a number of device types avaliable to a given inference engine.
+        * @brief Get a number of device types available to a given inference engine.
         * @details Use this function to get how many device types are supported for a given inference engine after calling @ref mv_image_classification_create().
         *
         * @since_tizen 7.5
index a78519d..607ac73 100644 (file)
@@ -164,7 +164,7 @@ int mv_object_detection_inference(mv_object_detection_h infer, mv_source_h sourc
  * @since_tizen 7.5
  *
  * @param[in] infer               The handle to the inference
- * @param[out] number_of_objects  A number of objectes detected.
+ * @param[out] number_of_objects  A number of objects detected.
  * @param[out] indices            Label indices to detected objects.
  * @param[out] confidences        Probability to detected objects.
  * @param[out] left               An left position array to bound boxs.
@@ -211,6 +211,105 @@ int mv_object_detection_get_result(mv_object_detection_h infer, unsigned int *nu
  */
 int mv_object_detection_get_label(mv_object_detection_h infer, const unsigned int index, const char **out_label);
 
+/**
+        * @brief Set user-given inference engine and device types for inference.
+        * @details Use this function to change the inference engine and device types for inference instead of default ones after calling @ref mv_object_detection_create().
+        *
+        * @since_tizen 7.5
+        *
+        * @param[in] handle        The handle to the image classification object.
+        * @param[in] engine_type  A string of inference engine type.
+        * @param[in] device_type   A string of device type.
+        *
+        * @return @c 0 on success, otherwise a negative error value
+        * @retval #MEDIA_VISION_ERROR_NONE Successful
+        * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+        * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
+        *
+        * @pre Create a image classification handle by calling @ref mv_object_detection_create()
+        */
+int mv_object_detection_set_engine(mv_object_detection_h handle, const char *engine_type, const char *device_type);
+
+/**
+        * @brief Get a number of inference engines available for image classification task API.
+        * @details Use this function to get how many inference engines are supported for image classification after calling @ref mv_object_detection_create().
+        *
+        * @since_tizen 7.5
+        *
+        * @param[in] handle         The handle to the image classification object.
+        * @param[out] engine_count  A number of inference engines available for image classification API.
+        *
+        * @return @c 0 on success, otherwise a negative error value
+        * @retval #MEDIA_VISION_ERROR_NONE Successful
+        * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+        * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
+        *
+        * @pre Create a image classification handle by calling @ref mv_object_detection_create()
+        */
+int mv_object_detection_get_engine_count(mv_object_detection_h handle, unsigned int *engine_count);
+
+/**
+        * @brief Get engine type to a given inference engine index.
+        * @details Use this function to get inference engine type with a given engine index after calling @ref mv_object_detection_get_engine_count().
+        *
+        * @since_tizen 7.5
+        *
+        * @param[in] handle        The handle to the image classification object.
+        * @param[in] engine_index  A inference engine index for getting the inference engine type.
+        * @param[out] engine_type  A string to inference engine.
+        *
+        * @return @c 0 on success, otherwise a negative error value
+        * @retval #MEDIA_VISION_ERROR_NONE Successful
+        * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+        * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
+        *
+        * @pre Get a number of inference engines available for image classification task API by calling @ref mv_object_detection_get_engine_count()
+        */
+int mv_object_detection_get_engine_type(mv_object_detection_h handle, const unsigned int engine_index,
+                                                                               char **engine_type);
+
+/**
+        * @brief Get a number of device types available to a given inference engine.
+        * @details Use this function to get how many device types are supported for a given inference engine after calling @ref mv_object_detection_create().
+        *
+        * @since_tizen 7.5
+        *
+        * @param[in] handle         The handle to the image classification object.
+        * @param[in] engine_type    A inference engine string.
+        * @param[out] device_count  A number of device types available for a given inference engine.
+        *
+        * @return @c 0 on success, otherwise a negative error value
+        * @retval #MEDIA_VISION_ERROR_NONE Successful
+        * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+        * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
+        *
+        * @pre Create a image classification handle by calling @ref mv_object_detection_create()
+        */
+int mv_object_detection_get_device_count(mv_object_detection_h handle, const char *engine_type,
+                                                                                unsigned int *device_count);
+
+/**
+        * @brief Get device type list available.
+        * @details Use this function to get what device types are supported for current inference engine type after calling @ref mv_object_detection_configure().
+        *
+        * @since_tizen 7.5
+        *
+        * @param[in] handle         The handle to the image classification object.
+        * @param[in] engine_type    A inference engine string.
+        * @param[in] device_index   A device index for getting the device type.
+        * @param[out] device_type   A string to device type.
+        *
+        * @return @c 0 on success, otherwise a negative error value
+        * @retval #MEDIA_VISION_ERROR_NONE Successful
+        * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+        * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
+        *
+        * @pre Create a image classification handle by calling @ref mv_object_detection_create()
+        * @pre Configure image classification task by calling @ref mv_object_detection_configure()
+        */
+int mv_object_detection_get_device_type(mv_object_detection_h handle, const char *engine_type,
+                                                                               const unsigned int device_index, char **device_type);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index b0ef985..aac63bd 100644 (file)
@@ -220,7 +220,7 @@ int mv_image_classification_get_engine_type_open(mv_image_classification_h handl
                                                                                                 char **engine_type);
 
 /**
-        * @brief Get a number of device types avaliable to a given inference engine.
+        * @brief Get a number of device types available to a given inference engine.
         * @details Use this function to get how many device types are supported for a given inference engine after calling @ref mv_image_classification_create_open().
         *
         * @since_tizen 7.5
index 10aa90b..815a273 100644 (file)
@@ -149,7 +149,7 @@ int mv_object_detection_inference_open(mv_object_detection_h handle, mv_source_h
  * @since_tizen 7.5
  *
  * @param[in] handle              The handle to the inference
- * @param[out] number_of_objects  A number of objectes detected.
+ * @param[out] number_of_objects  A number of objects detected.
  * @param[out] indices            Label indices to detected objects.
  * @param[out] confidences        Probability to detected objects.
  * @param[out] left               An left position array to bound boxs.
@@ -196,6 +196,106 @@ int mv_object_detection_get_result_open(mv_object_detection_h handle, unsigned i
  */
 int mv_object_detection_get_label_open(mv_object_detection_h handle, const unsigned int index, const char **out_label);
 
+/**
+        * @brief Set user-given backend and device types for inference.
+        * @details Use this function to change the backend and device types for inference instead of default ones after calling @ref mv_object_detection_create_open().
+        *
+        * @since_tizen 7.5
+        *
+        * @param[in] handle        The handle to the image classification object.
+        * @param[in] backend_type  A string of backend type.
+        * @param[in] device_type   A string of device type.
+        *
+        * @return @c 0 on success, otherwise a negative error value
+        * @retval #MEDIA_VISION_ERROR_NONE Successful
+        * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+        * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
+        *
+        * @pre Create a image classification handle by calling @ref mv_object_detection_create_open()
+        */
+int mv_object_detection_set_engine_open(mv_object_detection_h handle, const char *backend_type,
+                                                                               const char *device_type);
+
+/**
+        * @brief Get a number of inference engines available for image classification task API.
+        * @details Use this function to get how many inference engines are supported for image classification after calling @ref mv_object_detection_create_open().
+        *
+        * @since_tizen 7.5
+        *
+        * @param[in] handle         The handle to the image classification object.
+        * @param[out] engine_count  A number of inference engines available for image classification API.
+        *
+        * @return @c 0 on success, otherwise a negative error value
+        * @retval #MEDIA_VISION_ERROR_NONE Successful
+        * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+        * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
+        *
+        * @pre Create a image classification handle by calling @ref mv_object_detection_create_open()
+        */
+int mv_object_detection_get_engine_count_open(mv_object_detection_h handle, unsigned int *engine_count);
+
+/**
+        * @brief Get engine type to a given inference engine index.
+        * @details Use this function to get inference engine type with a given engine index after calling @ref mv_object_detection_get_engine_count().
+        *
+        * @since_tizen 7.5
+        *
+        * @param[in] handle        The handle to the image classification object.
+        * @param[in] engine_index  A inference engine index for getting the inference engine type.
+        * @param[out] engine_type  A string to inference engine.
+        *
+        * @return @c 0 on success, otherwise a negative error value
+        * @retval #MEDIA_VISION_ERROR_NONE Successful
+        * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+        * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
+        *
+        * @pre Get a number of inference engines available for image classification task API by calling @ref mv_object_detection_get_engine_count()
+        */
+int mv_object_detection_get_engine_type_open(mv_object_detection_h handle, const unsigned int engine_index,
+                                                                                        char **engine_type);
+
+/**
+        * @brief Get a number of device types available to a given inference engine.
+        * @details Use this function to get how many device types are supported for a given inference engine after calling @ref mv_object_detection_create_open().
+        *
+        * @since_tizen 7.5
+        *
+        * @param[in] handle         The handle to the image classification object.
+        * @param[in] engine_type    A inference engine string.
+        * @param[out] device_count  A number of device types available for a given inference engine.
+        *
+        * @return @c 0 on success, otherwise a negative error value
+        * @retval #MEDIA_VISION_ERROR_NONE Successful
+        * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+        * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
+        *
+        * @pre Create a image classification handle by calling @ref mv_object_detection_create_open()
+        */
+int mv_object_detection_get_device_count_open(mv_object_detection_h handle, const char *engine_type,
+                                                                                         unsigned int *device_count);
+
+/**
+        * @brief Get device type list available.
+        * @details Use this function to get what device types are supported for current inference engine type after calling @ref mv_object_detection_configure().
+        *
+        * @since_tizen 7.5
+        *
+        * @param[in] handle         The handle to the image classification object.
+        * @param[in] engine_type    A inference engine string.
+        * @param[in] device_index   A device index for getting the device type.
+        * @param[out] device_type   A string to device type.
+        *
+        * @return @c 0 on success, otherwise a negative error value
+        * @retval #MEDIA_VISION_ERROR_NONE Successful
+        * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
+        * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
+        *
+        * @pre Create a image classification handle by calling @ref mv_object_detection_create_open()
+        * @pre Configure image classification task by calling @ref mv_object_detection_configure_open()
+        */
+int mv_object_detection_get_device_type_open(mv_object_detection_h handle, const char *engine_type,
+                                                                                        const unsigned int device_index, char **device_type);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index b364bfb..4ade7f0 100644 (file)
@@ -36,6 +36,8 @@ class ObjectDetection
 {
 private:
        void loadLabel();
+       void getEngineList();
+       void getDeviceList(const char *engine_type);
 
        ObjectDetectionTaskType _task_type;
 
@@ -44,6 +46,8 @@ protected:
        std::unique_ptr<MediaVision::Common::EngineConfig> _config;
        std::unique_ptr<MetaParser> _parser;
        std::vector<std::string> _labels;
+       std::vector<std::string> _valid_backends;
+       std::vector<std::string> _valid_devices;
        Preprocess _preprocess;
        std::string _modelFilePath;
        std::string _modelMetaFilePath;
@@ -58,7 +62,13 @@ protected:
 public:
        ObjectDetection(ObjectDetectionTaskType task_type);
        virtual ~ObjectDetection() = default;
+       ObjectDetectionTaskType getTaskType();
        void setUserModel(std::string model_file, std::string meta_file, std::string label_file);
+       void setEngineInfo(std::string engine_type, std::string device_type);
+       void getNumberOfEngines(unsigned int *number_of_engines);
+       void getEngineType(unsigned int engine_index, char **engine_type);
+       void getNumberOfDevices(const char *engine_type, unsigned int *number_of_devices);
+       void getDeviceType(const char *engine_type, const unsigned int device_index, char **device_type);
        void parseMetaFile();
        void configure();
        void prepare();
index 04f1125..cda77a6 100644 (file)
@@ -69,6 +69,91 @@ int mv_object_detection_set_model(mv_object_detection_h handle, const char *mode
        return ret;
 }
 
+int mv_object_detection_set_engine(mv_object_detection_h handle, const char *backend_type, const char *device_type)
+{
+       MEDIA_VISION_SUPPORT_CHECK(_mv_inference_face_check_system_info_feature_supported());
+
+       MEDIA_VISION_INSTANCE_CHECK(handle);
+       MEDIA_VISION_NULL_ARG_CHECK(backend_type);
+       MEDIA_VISION_NULL_ARG_CHECK(device_type);
+
+       MEDIA_VISION_FUNCTION_ENTER();
+
+       int ret = mv_object_detection_set_engine_open(handle, backend_type, device_type);
+
+       MEDIA_VISION_FUNCTION_LEAVE();
+
+       return ret;
+}
+
+int mv_object_detection_get_engine_count(mv_object_detection_h handle, unsigned int *engine_count)
+{
+       MEDIA_VISION_SUPPORT_CHECK(_mv_inference_face_check_system_info_feature_supported());
+
+       MEDIA_VISION_INSTANCE_CHECK(handle);
+       MEDIA_VISION_NULL_ARG_CHECK(engine_count);
+
+       MEDIA_VISION_FUNCTION_ENTER();
+
+       int ret = mv_object_detection_get_engine_count_open(handle, engine_count);
+
+       MEDIA_VISION_FUNCTION_LEAVE();
+
+       return ret;
+}
+
+int mv_object_detection_get_engine_type(mv_object_detection_h handle, const unsigned int engine_index,
+                                                                               char **engine_type)
+{
+       MEDIA_VISION_SUPPORT_CHECK(_mv_inference_face_check_system_info_feature_supported());
+
+       MEDIA_VISION_INSTANCE_CHECK(handle);
+       MEDIA_VISION_NULL_ARG_CHECK(engine_type);
+
+       MEDIA_VISION_FUNCTION_ENTER();
+
+       int ret = mv_object_detection_get_engine_type_open(handle, engine_index, engine_type);
+
+       MEDIA_VISION_FUNCTION_LEAVE();
+
+       return ret;
+}
+
+int mv_object_detection_get_device_count(mv_object_detection_h handle, const char *engine_type,
+                                                                                unsigned int *device_count)
+{
+       MEDIA_VISION_SUPPORT_CHECK(_mv_inference_face_check_system_info_feature_supported());
+
+       MEDIA_VISION_INSTANCE_CHECK(handle);
+       MEDIA_VISION_NULL_ARG_CHECK(device_count);
+
+       MEDIA_VISION_FUNCTION_ENTER();
+
+       int ret = mv_object_detection_get_device_count_open(handle, engine_type, device_count);
+
+       MEDIA_VISION_FUNCTION_LEAVE();
+
+       return ret;
+}
+
+int mv_object_detection_get_device_type(mv_object_detection_h handle, const char *engine_type,
+                                                                               const unsigned int device_index, char **device_type)
+{
+       MEDIA_VISION_SUPPORT_CHECK(_mv_inference_face_check_system_info_feature_supported());
+
+       MEDIA_VISION_INSTANCE_CHECK(handle);
+       MEDIA_VISION_NULL_ARG_CHECK(engine_type);
+       MEDIA_VISION_NULL_ARG_CHECK(device_type);
+
+       MEDIA_VISION_FUNCTION_ENTER();
+
+       int ret = mv_object_detection_get_device_type_open(handle, engine_type, device_index, device_type);
+
+       MEDIA_VISION_FUNCTION_LEAVE();
+
+       return ret;
+}
+
 int mv_object_detection_configure(mv_object_detection_h infer)
 {
        MEDIA_VISION_SUPPORT_CHECK(_mv_inference_check_system_info_feature_supported());
index 311d6b1..8dff4d3 100644 (file)
@@ -111,6 +111,123 @@ int mv_object_detection_set_model_open(mv_object_detection_h handle, const char
        return MEDIA_VISION_ERROR_NONE;
 }
 
+int mv_object_detection_set_engine_open(mv_object_detection_h handle, const char *backend_type, const char *device_type)
+{
+       if (!handle) {
+               LOGE("Handle is NULL.");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       try {
+               auto context = static_cast<Context *>(handle);
+               auto task = static_cast<ObjectDetectionTask *>(context->__tasks.at("object_detection"));
+
+               task->setEngineInfo(backend_type, device_type);
+       } catch (const BaseException &e) {
+               LOGE("%s", e.what());
+               return e.getError();
+       }
+
+       LOGD("LEAVE");
+
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+int mv_object_detection_get_engine_count_open(mv_object_detection_h handle, unsigned int *engine_count)
+{
+       if (!handle) {
+               LOGE("Handle is NULL.");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       try {
+               auto context = static_cast<Context *>(handle);
+               auto task = static_cast<ObjectDetectionTask *>(context->__tasks.at("object_detection"));
+
+               task->getNumberOfEngines(engine_count);
+               // TODO.
+       } catch (const BaseException &e) {
+               LOGE("%s", e.what());
+               return e.getError();
+       }
+
+       LOGD("LEAVE");
+
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+int mv_object_detection_get_engine_type_open(mv_object_detection_h handle, const unsigned int engine_index,
+                                                                                        char **engine_type)
+{
+       if (!handle) {
+               LOGE("Handle is NULL.");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       try {
+               auto context = static_cast<Context *>(handle);
+               auto task = static_cast<ObjectDetectionTask *>(context->__tasks.at("object_detection"));
+
+               task->getEngineType(engine_index, engine_type);
+               // TODO.
+       } catch (const BaseException &e) {
+               LOGE("%s", e.what());
+               return e.getError();
+       }
+
+       LOGD("LEAVE");
+
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+int mv_object_detection_get_device_count_open(mv_object_detection_h handle, const char *engine_type,
+                                                                                         unsigned int *device_count)
+{
+       if (!handle) {
+               LOGE("Handle is NULL.");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       try {
+               auto context = static_cast<Context *>(handle);
+               auto task = static_cast<ObjectDetectionTask *>(context->__tasks.at("object_detection"));
+
+               task->getNumberOfDevices(engine_type, device_count);
+               // TODO.
+       } catch (const BaseException &e) {
+               LOGE("%s", e.what());
+               return e.getError();
+       }
+
+       LOGD("LEAVE");
+
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+int mv_object_detection_get_device_type_open(mv_object_detection_h handle, const char *engine_type,
+                                                                                        const unsigned int device_index, char **device_type)
+{
+       if (!handle) {
+               LOGE("Handle is NULL.");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       try {
+               auto context = static_cast<Context *>(handle);
+               auto task = static_cast<ObjectDetectionTask *>(context->__tasks.at("object_detection"));
+
+               task->getDeviceType(engine_type, device_index, device_type);
+               // TODO.
+       } catch (const BaseException &e) {
+               LOGE("%s", e.what());
+               return e.getError();
+       }
+
+       LOGD("LEAVE");
+
+       return MEDIA_VISION_ERROR_NONE;
+}
+
 int mv_object_detection_configure_open(mv_object_detection_h handle)
 {
        LOGD("ENTER");
@@ -126,7 +243,6 @@ int mv_object_detection_configure_open(mv_object_detection_h handle)
                auto context = static_cast<Context *>(handle);
                auto task = static_cast<ObjectDetectionTask *>(context->__tasks.at("object_detection"));
 
-               task->create(static_cast<int>(ObjectDetectionTaskType::MOBILENET_V1_SSD));
                task->configure();
        } catch (const BaseException &e) {
                LOGE("%s", e.what());
index d26ed63..97972c3 100644 (file)
 #include <algorithm>
 
 #include "machine_learning_exception.h"
+#include "mv_machine_learning_common.h"
 #include "mv_object_detection_config.h"
 #include "object_detection.h"
 
 using namespace std;
 using namespace mediavision::inference;
 using namespace MediaVision::Common;
+using namespace mediavision::common;
 using namespace mediavision::machine_learning::exception;
 
 namespace mediavision
@@ -40,6 +42,108 @@ ObjectDetection::ObjectDetection(ObjectDetectionTaskType task_type)
        _parser = make_unique<ObjectDetectionParser>();
 }
 
+ObjectDetectionTaskType ObjectDetection::getTaskType()
+{
+       return _task_type;
+}
+
+void ObjectDetection::getEngineList()
+{
+       for (auto idx = MV_INFERENCE_BACKEND_NONE + 1; idx < MV_INFERENCE_BACKEND_MAX; ++idx) {
+               auto backend = _inference->getSupportedInferenceBackend(idx);
+               // TODO. we need to describe what inference engines are supported by each Task API,
+               //       and based on it, below inference engine types should be checked
+               //       if a given type is supported by this Task API later. As of now, tflite only.
+               if (backend.second == true && backend.first.compare("tflite") == 0)
+                       _valid_backends.push_back(backend.first);
+       }
+}
+
+void ObjectDetection::getDeviceList(const char *engine_type)
+{
+       // TODO. add device types available for a given engine type later.
+       //       In default, cpu and gpu only.
+       _valid_devices.push_back("cpu");
+       _valid_devices.push_back("gpu");
+}
+
+void ObjectDetection::setEngineInfo(std::string engine_type, std::string device_type)
+{
+       if (engine_type.empty() || device_type.empty())
+               throw InvalidParameter("Invalid engine info.");
+
+       transform(engine_type.begin(), engine_type.end(), engine_type.begin(), ::toupper);
+       transform(device_type.begin(), device_type.end(), device_type.begin(), ::toupper);
+
+       _backendType = GetBackendType(engine_type);
+       _targetDeviceType = GetDeviceType(device_type);
+
+       LOGI("Engine type : %s => %d, Device type : %s => %d", engine_type.c_str(), GetBackendType(engine_type),
+                device_type.c_str(), GetDeviceType(device_type));
+
+       if (_backendType == MEDIA_VISION_ERROR_INVALID_PARAMETER ||
+               _targetDeviceType == MEDIA_VISION_ERROR_INVALID_PARAMETER)
+               throw InvalidParameter("backend or target device type not found.");
+}
+
+void ObjectDetection::getNumberOfEngines(unsigned int *number_of_engines)
+{
+       if (!_valid_backends.empty()) {
+               *number_of_engines = _valid_backends.size();
+               return;
+       }
+
+       getEngineList();
+       *number_of_engines = _valid_backends.size();
+}
+
+void ObjectDetection::getEngineType(unsigned int engine_index, char **engine_type)
+{
+       if (!_valid_backends.empty()) {
+               if (_valid_backends.size() <= engine_index)
+                       throw InvalidParameter("Invalid engine index.");
+
+               *engine_type = const_cast<char *>(_valid_backends[engine_index].data());
+               return;
+       }
+
+       getEngineList();
+
+       if (_valid_backends.size() <= engine_index)
+               throw InvalidParameter("Invalid engine index.");
+
+       *engine_type = const_cast<char *>(_valid_backends[engine_index].data());
+}
+
+void ObjectDetection::getNumberOfDevices(const char *engine_type, unsigned int *number_of_devices)
+{
+       if (!_valid_devices.empty()) {
+               *number_of_devices = _valid_devices.size();
+               return;
+       }
+
+       getDeviceList(engine_type);
+       *number_of_devices = _valid_devices.size();
+}
+
+void ObjectDetection::getDeviceType(const char *engine_type, const unsigned int device_index, char **device_type)
+{
+       if (!_valid_devices.empty()) {
+               if (_valid_devices.size() <= device_index)
+                       throw InvalidParameter("Invalid device index.");
+
+               *device_type = const_cast<char *>(_valid_devices[device_index].data());
+               return;
+       }
+
+       getDeviceList(engine_type);
+
+       if (_valid_devices.size() <= device_index)
+               throw InvalidParameter("Invalid device index.");
+
+       *device_type = const_cast<char *>(_valid_devices[device_index].data());
+}
+
 void ObjectDetection::setUserModel(string model_file, string meta_file, string label_file)
 {
        _modelFilePath = model_file;
index be1a73d..4e36baf 100644 (file)
@@ -27,44 +27,55 @@ namespace mediavision
 namespace machine_learning
 {
 template<typename T, typename V> ObjectDetectionAdapter<T, V>::ObjectDetectionAdapter() : _source()
-{}
+{
+       // In default, Mobilenet v1 ssd model will be used.
+       // If other model is set by user then strategy pattern will be used
+       // to create its corresponding concerte class by calling create().
+       _object_detection = make_unique<MobilenetV1Ssd>(ObjectDetectionTaskType::MOBILENET_V1_SSD);
+}
 
 template<typename T, typename V> ObjectDetectionAdapter<T, V>::~ObjectDetectionAdapter()
 {}
 
 template<typename T, typename V> void ObjectDetectionAdapter<T, V>::create(int type)
 {
-       if (!_model_name.empty()) {
-               transform(_model_name.begin(), _model_name.end(), _model_name.begin(), ::toupper);
+       ObjectDetectionTaskType task_type = static_cast<ObjectDetectionTaskType>(type);
 
-               if (_model_name == string("MOBILENET_V1_SSD"))
-                       type = static_cast<int>(ObjectDetectionTaskType::MOBILENET_V1_SSD);
-               else if (_model_name == string("MOBILENET_V2_SSD"))
-                       type = static_cast<int>(ObjectDetectionTaskType::MOBILENET_V2_SSD);
-               // TODO.
-               else
-                       throw InvalidParameter("Invalid object detection model name.");
-       }
+       // If default task type is same as a given one then skip.
+       if (_object_detection->getTaskType() == task_type)
+               return;
 
-       switch (static_cast<ObjectDetectionTaskType>(type)) {
-       case ObjectDetectionTaskType::MOBILENET_V1_SSD:
-               _object_detection = make_unique<MobilenetV1Ssd>(static_cast<ObjectDetectionTaskType>(type));
-               break;
-       case ObjectDetectionTaskType::MOBILENET_V2_SSD:
-               _object_detection = make_unique<MobilenetV2Ssd>(static_cast<ObjectDetectionTaskType>(type));
-               break;
-       default:
-               throw InvalidParameter("Invalid object detection task type.");
-       }
+       _object_detection.reset();
 
-       _object_detection->setUserModel(_model_file, _meta_file, _label_file);
+       if (task_type == ObjectDetectionTaskType::MOBILENET_V1_SSD)
+               _object_detection = make_unique<MobilenetV1Ssd>(task_type);
+       else if (task_type == ObjectDetectionTaskType::MOBILENET_V2_SSD)
+               _object_detection = make_unique<MobilenetV2Ssd>(task_type);
+
+       // TODO.
 }
 
 template<typename T, typename V>
 void ObjectDetectionAdapter<T, V>::setModelInfo(const char *model_file, const char *meta_file, const char *label_file,
                                                                                                const char *model_name)
 {
-       _model_name = string(model_name);
+       string model_name_str(model_name);
+
+       if (!model_name_str.empty()) {
+               transform(model_name_str.begin(), model_name_str.end(), model_name_str.begin(), ::toupper);
+
+               int model_type = 0;
+
+               if (model_name_str == string("MOBILENET_V1_SSD"))
+                       model_type = static_cast<int>(ObjectDetectionTaskType::MOBILENET_V1_SSD);
+               else if (model_name_str == string("MOBILENET_V2_SSD"))
+                       model_type = static_cast<int>(ObjectDetectionTaskType::MOBILENET_V2_SSD);
+               // TODO.
+               else
+                       throw InvalidParameter("Invalid object detection model name.");
+
+               create(static_cast<int>(model_type));
+       }
 
        _model_file = string(model_file);
        _meta_file = string(meta_file);
@@ -72,6 +83,8 @@ void ObjectDetectionAdapter<T, V>::setModelInfo(const char *model_file, const ch
 
        if (_model_file.empty() && _meta_file.empty() && _label_file.empty())
                throw InvalidParameter("Model info not invalid.");
+
+       _object_detection->setUserModel(_model_file, _meta_file, _label_file);
 }
 
 template<typename T, typename V>
@@ -85,19 +98,27 @@ template<typename T, typename V> void ObjectDetectionAdapter<T, V>::configure()
 }
 
 template<typename T, typename V> void ObjectDetectionAdapter<T, V>::getNumberOfEngines(unsigned int *number_of_engines)
-{}
+{
+       _object_detection->getNumberOfEngines(number_of_engines);
+}
 
 template<typename T, typename V>
 void ObjectDetectionAdapter<T, V>::getEngineType(unsigned int engine_index, char **engine_type)
-{}
+{
+       _object_detection->getEngineType(engine_index, engine_type);
+}
 
 template<typename T, typename V>
 void ObjectDetectionAdapter<T, V>::getNumberOfDevices(const char *engine_type, unsigned int *number_of_devices)
-{}
+{
+       _object_detection->getNumberOfDevices(engine_type, number_of_devices);
+}
 
 template<typename T, typename V>
 void ObjectDetectionAdapter<T, V>::getDeviceType(const char *engine_type, unsigned int device_index, char **device_type)
-{}
+{
+       _object_detection->getDeviceType(engine_type, device_index, device_type);
+}
 
 template<typename T, typename V> void ObjectDetectionAdapter<T, V>::prepare()
 {
index 8e27a6e..6607883 100644 (file)
@@ -37,6 +37,52 @@ struct model_info {
        string label_file;
 };
 
+TEST(ObjectDetectionTest, GettingAvailableInferenceEnginesInfoShouldBeOk)
+{
+       mv_object_detection_h handle;
+
+       int ret = mv_object_detection_create(&handle);
+       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+       unsigned int engine_count = 0;
+
+       ret = mv_object_detection_get_engine_count(handle, &engine_count);
+       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+       cout << "Engine count = " << engine_count << endl;
+       ASSERT_GE(engine_count, 1);
+
+       for (unsigned int engine_idx = 0; engine_idx < engine_count; ++engine_idx) {
+               char *engine_type = nullptr;
+
+               ret = mv_object_detection_get_engine_type(handle, engine_idx, &engine_type);
+               ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+               cout << "Engine type : " << engine_type << endl;
+
+               unsigned int device_count = 0;
+
+               ret = mv_object_detection_get_device_count(handle, engine_type, &device_count);
+               ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+               cout << "Device count = " << device_count << endl;
+
+               ASSERT_GE(engine_count, 1);
+
+               for (unsigned int device_idx = 0; device_idx < device_count; ++device_idx) {
+                       char *device_type = nullptr;
+
+                       ret = mv_object_detection_get_device_type(handle, engine_type, device_idx, &device_type);
+                       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+                       cout << "Device type : " << device_type << endl;
+               }
+       }
+
+       ret = mv_object_detection_destroy(handle);
+       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+}
+
 TEST(ObjectDetectionTest, InferenceShouldBeOk)
 {
        mv_object_detection_h handle;
@@ -66,6 +112,7 @@ TEST(ObjectDetectionTest, InferenceShouldBeOk)
 
                mv_object_detection_set_model(handle, model.model_name.c_str(), model.model_file.c_str(),
                                                                          model.meta_file.c_str(), model.label_file.c_str());
+               mv_object_detection_set_engine(handle, "tflite", "cpu");
 
                ret = mv_object_detection_configure(handle);
                ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);