mv_machine_learning: use DEFAULT_MODEL_NAME for landmark detection task group
authorInki Dae <inki.dae@samsung.com>
Wed, 25 Oct 2023 11:07:07 +0000 (20:07 +0900)
committerInki Dae <inki.dae@samsung.com>
Tue, 14 Nov 2023 07:38:48 +0000 (16:38 +0900)
[Issue type] : new feature

Use the meta file for landmark detection tasks to set the default model

With this patch, a proper concrete class object will be created
at the constructor of FacialLandmarkAdapter and PoseLandmarkAdapter classes
according to the default model names which are parsed from each meta file,
facial_landmark.json and pose_landmark.json files.

And also this patch calls the member function, create, to create the concrete
class object corresponding to the default model name instead of creating
a default concrete class object directly.

Finally, we can create user-desired concrete class object without rebuilding
by simply modifying the meta files.

Change-Id: I4ef045fe1ae24177ae4ebc7a3f48ae6e136c01dc
Signed-off-by: Inki Dae <inki.dae@samsung.com>
mv_machine_learning/landmark_detection/include/facial_landmark_adapter.h
mv_machine_learning/landmark_detection/include/landmark_detection_type.h
mv_machine_learning/landmark_detection/include/mv_landmark_detection_config.h
mv_machine_learning/landmark_detection/include/pose_landmark_adapter.h
mv_machine_learning/landmark_detection/meta/facial_landmark.json
mv_machine_learning/landmark_detection/meta/pose_landmark.json
mv_machine_learning/landmark_detection/src/facial_landmark_adapter.cpp
mv_machine_learning/landmark_detection/src/pose_landmark_adapter.cpp

index 82f8e1c..5061e75 100644 (file)
@@ -36,8 +36,10 @@ private:
        std::string _model_file;
        std::string _meta_file;
        std::string _label_file;
+       const std::string _config_file_name = "facial_landmark.json";
 
        void create(LandmarkDetectionTaskType task_type);
+       LandmarkDetectionTaskType convertToTaskType(std::string model_name);
 
 public:
        FacialLandmarkAdapter();
index 66464c0..13ce7c5 100644 (file)
@@ -28,7 +28,6 @@ namespace machine_learning
 {
 struct LandmarkDetectionInput {
        mv_source_h inference_src;
-       // TODO.
 };
 
 struct LandmarkDetectionResult {
@@ -44,7 +43,6 @@ enum class LandmarkDetectionTaskType {
        LANDMARK_DETECTION_TASK_NONE = 0,
        FLD_TWEAK_CNN,
        PLD_CPM
-       // TODO
 };
 
 }
index 2266bcf..cb8a3b7 100644 (file)
 #define MV_LANDMARK_DETECTION_MODEL_FILE_PATH "MODEL_FILE_NAME"
 
 /**
+ * @brief Defines #MV_LANDMARK_DETECTION_DEFAULT_MODEL_NAME
+ *        to set the landmark detection default model name.
+ *
+ * @since_tizen 8.0
+ */
+#define MV_LANDMARK_DETECTION_DEFAULT_MODEL_NAME "DEFAULT_MODEL_NAME"
+
+/**
  * @brief Defines #MV_LANDMARK_DETECTION_MODEL_META_FILE_PATH to set inference
  *        models's metadata file attribute of the engine configuration.
  * @details The file includes inference model's metadata such as input and output
index b9659f1..e8879b6 100644 (file)
@@ -36,8 +36,10 @@ private:
        std::string _model_file;
        std::string _meta_file;
        std::string _label_file;
+       const std::string _config_file_name = "pose_landmark.json";
 
        void create(LandmarkDetectionTaskType task_type);
+       LandmarkDetectionTaskType convertToTaskType(std::string model_name);
 
 public:
        PoseLandmarkAdapter();
index 2c5cc69..ad7f7b8 100644 (file)
             "value" : "fld_tweakcnn_128x128.tflite"
         },
         {
+            "name"  : "DEFAULT_MODEL_NAME",
+            "type"  : "string",
+            "value" : "FLD_TWEAK_CNN"
+        },
+        {
             "name"  : "META_FILE_NAME",
             "type"  : "string",
             "value" : "fld_tweakcnn_128x128.json"
index 787b3a8..a8637f8 100644 (file)
             "value" : "pld_cpm_192x192.tflite"
         },
         {
+            "name"  : "DEFAULT_MODEL_NAME",
+            "type"  : "string",
+            "value" : "PLD_CPM"
+        },
+        {
             "name"  : "META_FILE_NAME",
             "type"  : "string",
             "value" : "pld_cpm_192x192.json"
index 58677e9..5f649d7 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "machine_learning_exception.h"
 #include "facial_landmark_adapter.h"
+#include "mv_landmark_detection_config.h"
 
 using namespace std;
 using namespace MediaVision::Common;
@@ -28,10 +29,15 @@ namespace machine_learning
 {
 template<typename T, typename V> FacialLandmarkAdapter<T, V>::FacialLandmarkAdapter() : _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 concrete class by calling create().
-       _landmark_detection = make_unique<FldTweakCnn>(LandmarkDetectionTaskType::FLD_TWEAK_CNN);
+       auto config = make_unique<EngineConfig>(MV_CONFIG_PATH + _config_file_name);
+
+       string defaultModelName;
+
+       int ret = config->getStringAttribute(MV_LANDMARK_DETECTION_DEFAULT_MODEL_NAME, &defaultModelName);
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to get default model name.");
+
+       create(convertToTaskType(defaultModelName));
 }
 
 template<typename T, typename V> FacialLandmarkAdapter<T, V>::~FacialLandmarkAdapter()
@@ -41,40 +47,47 @@ template<typename T, typename V> FacialLandmarkAdapter<T, V>::~FacialLandmarkAda
 
 template<typename T, typename V> void FacialLandmarkAdapter<T, V>::create(LandmarkDetectionTaskType task_type)
 {
-       // If default task type is same as a given one then skip.
-       if (_landmark_detection->getTaskType() == task_type)
-               return;
-
-       _landmark_detection.reset();
+       if (_landmark_detection) {
+               // If current task type is same as a given one then skip.
+               if (_landmark_detection->getTaskType() == task_type)
+                       return;
+       }
 
        if (task_type == LandmarkDetectionTaskType::FLD_TWEAK_CNN)
                _landmark_detection = make_unique<FldTweakCnn>(task_type);
-       // TODO.
 }
 
 template<typename T, typename V>
-void FacialLandmarkAdapter<T, V>::setModelInfo(const char *model_file, const char *meta_file, const char *label_file,
-                                                                                          const char *model_name)
+LandmarkDetectionTaskType FacialLandmarkAdapter<T, V>::convertToTaskType(string model_name)
 {
-       string model_name_str(model_name);
+       if (model_name.empty())
+               throw InvalidParameter("model name is empty.");
 
-       if (!model_name_str.empty()) {
-               transform(model_name_str.begin(), model_name_str.end(), model_name_str.begin(), ::toupper);
+       transform(model_name.begin(), model_name.end(), model_name.begin(), ::toupper);
 
-               LandmarkDetectionTaskType task_type = LandmarkDetectionTaskType::LANDMARK_DETECTION_TASK_NONE;
+       if (model_name == "FLD_TWEAK_CNN")
+               return LandmarkDetectionTaskType::FLD_TWEAK_CNN;
+       // TODO.
 
-               if (model_name_str == string("FLD_TWEAK_CNN"))
-                       task_type = LandmarkDetectionTaskType::FLD_TWEAK_CNN;
-               // TODO.
-               else
-                       throw InvalidParameter("Invalid landmark detection model name.");
+       throw InvalidParameter("Invalid facial detection model name.");
+}
 
-               create(task_type);
+template<typename T, typename V>
+void FacialLandmarkAdapter<T, V>::setModelInfo(const char *model_file, const char *meta_file, const char *label_file,
+                                                                                          const char *model_name)
+{
+       try {
+               create(convertToTaskType(model_name));
+       } catch (const BaseException &e) {
+               LOGW("A given model name is invalid so default task type will be used.");
        }
 
-       _model_file = string(model_file);
-       _meta_file = string(meta_file);
-       _label_file = string(label_file);
+       if (model_file)
+               _model_file = model_file;
+       if (meta_file)
+               _meta_file = meta_file;
+       if (label_file)
+               _label_file = label_file;
 
        if (_model_file.empty() && _meta_file.empty()) {
                LOGW("Given model info is invalid so default model info will be used instead.");
@@ -92,7 +105,7 @@ void FacialLandmarkAdapter<T, V>::setEngineInfo(const char *engine_type, const c
 
 template<typename T, typename V> void FacialLandmarkAdapter<T, V>::configure()
 {
-       _landmark_detection->configure("facial_landmark.json");
+       _landmark_detection->configure(_config_file_name);
 }
 
 template<typename T, typename V> void FacialLandmarkAdapter<T, V>::getNumberOfEngines(unsigned int *number_of_engines)
index c1a3fa1..2bd4bc3 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "machine_learning_exception.h"
 #include "pose_landmark_adapter.h"
+#include "mv_landmark_detection_config.h"
 
 using namespace std;
 using namespace MediaVision::Common;
@@ -28,10 +29,15 @@ namespace machine_learning
 {
 template<typename T, typename V> PoseLandmarkAdapter<T, V>::PoseLandmarkAdapter() : _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 concrete class by calling create().
-       _landmark_detection = make_unique<PldCpm>(LandmarkDetectionTaskType::PLD_CPM);
+       auto config = make_unique<EngineConfig>(MV_CONFIG_PATH + _config_file_name);
+
+       string defaultModelName;
+
+       int ret = config->getStringAttribute(MV_LANDMARK_DETECTION_DEFAULT_MODEL_NAME, &defaultModelName);
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to get default model name.");
+
+       create(convertToTaskType(defaultModelName));
 }
 
 template<typename T, typename V> PoseLandmarkAdapter<T, V>::~PoseLandmarkAdapter()
@@ -41,40 +47,50 @@ template<typename T, typename V> PoseLandmarkAdapter<T, V>::~PoseLandmarkAdapter
 
 template<typename T, typename V> void PoseLandmarkAdapter<T, V>::create(LandmarkDetectionTaskType task_type)
 {
-       // If default task type is same as a given one then skip.
-       if (_landmark_detection->getTaskType() == task_type)
-               return;
-
-       _landmark_detection.reset();
+       // If a concrete class object created already exists, reset the object
+       // so that other concrete class object can be created again according to a given task_type.
+       if (_landmark_detection) {
+               // If default task type is same as a given one then skip.
+               if (_landmark_detection->getTaskType() == task_type)
+                       return;
+       }
 
        if (task_type == LandmarkDetectionTaskType::PLD_CPM)
                _landmark_detection = make_unique<PldCpm>(task_type);
-       // TODO.
 }
 
 template<typename T, typename V>
-void PoseLandmarkAdapter<T, V>::setModelInfo(const char *model_file, const char *meta_file, const char *label_file,
-                                                                                        const char *model_name)
+LandmarkDetectionTaskType PoseLandmarkAdapter<T, V>::convertToTaskType(string model_name)
 {
-       string model_name_str(model_name);
+       if (model_name.empty())
+               throw InvalidParameter("model name is empty.");
+
+       transform(model_name.begin(), model_name.end(), model_name.begin(), ::toupper);
 
-       if (!model_name_str.empty()) {
-               transform(model_name_str.begin(), model_name_str.end(), model_name_str.begin(), ::toupper);
+       LandmarkDetectionTaskType task_type = LandmarkDetectionTaskType::LANDMARK_DETECTION_TASK_NONE;
 
-               LandmarkDetectionTaskType task_type = LandmarkDetectionTaskType::LANDMARK_DETECTION_TASK_NONE;
+       if (model_name == "PLD_CPM")
+               return LandmarkDetectionTaskType::PLD_CPM;
 
-               if (model_name_str == string("PLD_CPM"))
-                       task_type = LandmarkDetectionTaskType::PLD_CPM;
-               // TODO.
-               else
-                       throw InvalidParameter("Invalid landmark detection model name.");
+       throw InvalidParameter("Invalid pose landmark model name.");
+}
 
-               create(task_type);
+template<typename T, typename V>
+void PoseLandmarkAdapter<T, V>::setModelInfo(const char *model_file, const char *meta_file, const char *label_file,
+                                                                                        const char *model_name)
+{
+       try {
+               create(convertToTaskType(model_name));
+       } catch (const BaseException &e) {
+               LOGW("A given model name is invalid so default task type will be used.");
        }
 
-       _model_file = string(model_file);
-       _meta_file = string(meta_file);
-       _label_file = string(label_file);
+       if (model_file)
+               _model_file = model_file;
+       if (meta_file)
+               _meta_file = meta_file;
+       if (label_file)
+               _label_file = label_file;
 
        if (_model_file.empty() && _meta_file.empty()) {
                LOGW("Given model info is invalid so default model info will be used instead.");
@@ -92,7 +108,7 @@ void PoseLandmarkAdapter<T, V>::setEngineInfo(const char *engine_type, const cha
 
 template<typename T, typename V> void PoseLandmarkAdapter<T, V>::configure()
 {
-       _landmark_detection->configure("pose_landmark.json");
+       _landmark_detection->configure(_config_file_name);
 }
 
 template<typename T, typename V> void PoseLandmarkAdapter<T, V>::getNumberOfEngines(unsigned int *number_of_engines)