mv_machine_learning: fix two bugs
authorInki Dae <inki.dae@samsung.com>
Fri, 7 Jul 2023 08:59:06 +0000 (17:59 +0900)
committerKwanghoon Son <k.son@samsung.com>
Wed, 12 Jul 2023 09:45:35 +0000 (18:45 +0900)
[Issue type] : bug fix

Fix two bugs - 1. one is to fix wrong result tensor data issue after
registering a new label without inference request, and 2. other is to fix
unexpected exception issue when the first label data is registered without
label file.

For issue number 1, the reason is that we got num_of_confidences from the label
file not internal result structure when mv_face_recognition_get_confidence()
funtion is called. As for this, this patch makes __labels of internal
result object - FaceRecognitionResult structure - to be updated only when
inference request is done, and it gets the num_of_confidences from the
internal result object and returns it to user.

For issue number 2, the reason is that addLabelToFile fucntion returned
0 when the label file doesn't exist, and it resulted in invalid operation
exception. As for this, this patch makes addLabelToFile function not to
return the invalid operation exception when the label file doesn't exist
because what this function has to is to add a given new label name to
the label file.

Change-Id: Ie66e2a65d40a2f2f8e091b46173cb0ecb2ddf23d
Signed-off-by: Inki Dae <inki.dae@samsung.com>
mv_machine_learning/face_recognition/src/face_recognition.cpp
mv_machine_learning/training/include/label_manager.h
mv_machine_learning/training/src/label_manager.cpp
test/testsuites/machine_learning/face_recognition/test_face_recognition.cpp

index 6ed5f4ca2a383b59a4d5b02687d66fce6126f61f..946748f5b4082ad4e9c3da09f7b36f9d5619458c 100644 (file)
@@ -110,6 +110,7 @@ int FaceRecognition::initialize()
                                                                                          _config.input_tensor_shape, _config.internal_model_file_path);
 
        _internal = make_unique<Inference>();
+       _label_manager = make_unique<LabelManager>(_config.label_file_path, _config.decision_threshold);
 
        int ret = _internal->bind(_config.inference_engine_backend_type, _config.inference_target_device_type);
        if (ret != MEDIA_VISION_ERROR_NONE)
@@ -123,10 +124,6 @@ int FaceRecognition::initialize()
 void FaceRecognition::importLabel()
 {
        try {
-               // Prepare can be called several times after initialization is done so previous data should be dropped.
-               _label_manager.reset();
-               _label_manager = make_unique<LabelManager>(_config.label_file_path, _config.decision_threshold);
-
                // Update label manager from a given label file.
                int cnt = _label_manager->importLabel();
 
@@ -146,16 +143,13 @@ int FaceRecognition::registerNewFace(std::vector<float> &input_vec, string label
 
        // TODO. consider data augmentation.
        try {
+               // 1. Store a new label name to label file if the given label doesn't exist.
+               if (!_label_manager->isExist(label_name))
+                       _label_manager->addLabelToFile(label_name);
+
                // Import label data from a label file.
                importLabel();
 
-               // 1. Store a new label name to label file if the given label doesn't exist.
-               if (!_label_manager->isExist(label_name)) {
-                       int ret = _label_manager->addLabelToFile(label_name);
-                       if (ret == 0)
-                               return MEDIA_VISION_ERROR_INVALID_OPERATION;
-               }
-
                // Get label index and count.
                unsigned int label_idx = _label_manager->getLabelIndex(label_name);
                unsigned int label_cnt = _label_manager->getMaxLabel();
@@ -310,6 +304,9 @@ int FaceRecognition::recognizeFace(std::vector<float> &input_vec)
 
                _result.raw_data.clear();
                copy(raw_buffer, raw_buffer + internal_output_buffer->size / sizeof(float), back_inserter(_result.raw_data));
+
+               _result.labels.clear();
+               _result.labels = _label_manager->getLabels();
                _status = WorkingStatus::INFERENCED;
 
                return getAnswer();
@@ -331,14 +328,14 @@ int FaceRecognition::deleteLabel(string label_name)
        // Deleting a given label is to remove existing registered person from label and feature vector files.
 
        try {
-               // Import label data from a label file.
-               importLabel();
-
                if (!_label_manager->isExist(label_name)) {
                        LOGE("%s doesn't exist in label file.", label_name.c_str());
                        return MEDIA_VISION_ERROR_INVALID_OPERATION;
                }
 
+               // Import label data from a label file.
+               importLabel();
+
                unsigned int target_label_idx = _label_manager->getLabelIndex(label_name);
 
                auto label_cnt_ori = _label_manager->getMaxLabel();
@@ -450,13 +447,10 @@ FaceRecognitionResult &FaceRecognition::result()
        if (!_result.is_valid)
                throw NoData("Inference result not ready yet.");
 
-       importLabel();
-
        if (!_label_manager)
                throw NoData("Label file doesn't exist.");
 
        try {
-               _result.labels = _label_manager->getLabels();
                _label_manager->getLabelString(_result.label, _result.label_idx);
        } catch (const BaseException &e) {
                LOGE("%s", e.what());
index 67b1ac13260a55dcd1291c3eef229c742496199d..d09ca6c585a4c86b2353edaaa3ae6102b9c260cd 100644 (file)
@@ -44,7 +44,7 @@ public:
        bool isExist(const std::string given_label);
        unsigned int removeLabel(const std::string given_label);
        void getLabelString(std::string &label, const int idx);
-       unsigned int addLabelToFile(std::string given_label);
+       void addLabelToFile(std::string given_label);
        size_t importLabel(void);
        const std::vector<std::string> &getLabels(void);
        size_t getMaxLabel();
index f5ef5a2805772ff53d1ff104d855cb14629cc140..edb16dfcb6f10ff9799df3d2d217b4cceeaea1c0 100644 (file)
@@ -107,15 +107,13 @@ unsigned int LabelManager::removeLabel(const string given_label)
 
 void LabelManager::getLabelString(string &label, const int idx)
 {
-       importLabel();
-
        if (idx < 0 || _labels.size() <= static_cast<size_t>(idx))
                throw InvalidOperation("A given label index is invalid.");
 
        label = _labels[idx];
 }
 
-unsigned int LabelManager::addLabelToFile(string given_label)
+void LabelManager::addLabelToFile(string given_label)
 {
        ofstream writeFile;
 
@@ -127,13 +125,11 @@ unsigned int LabelManager::addLabelToFile(string given_label)
        given_label += "\n";
        writeFile.write(given_label.c_str(), static_cast<streamsize>(given_label.size()));
        writeFile.close();
-
-       return getMaxLabel();
 }
 
 size_t LabelManager::importLabel(void)
 {
-       // label count is 0 if lael file doesn't exist.
+       // label count is 0 if label file doesn't exist.
        if (!FaceRecogUtil::isFileExist(_label_file))
                return 0;
 
@@ -168,13 +164,15 @@ const std::vector<std::string> &LabelManager::getLabels(void)
 
 bool LabelManager::isExist(const string given_label)
 {
+       // return false if label file doesn't exist.
+       if (!FaceRecogUtil::isFileExist(_label_file))
+               return false;
+
        return (find(_labels.begin(), _labels.end(), given_label) != _labels.end());
 }
 
 size_t LabelManager::getMaxLabel()
 {
-       importLabel();
-
        return _labels.size();
 }
 
index d84d76835a1e66da4c77368685c29ad68f40e14c..f49462d554bae8b4157b5408dbcb02b6958a8ac6 100644 (file)
@@ -211,6 +211,98 @@ TEST(FaceRecognitionTest, RawResultAfterInferenceShouldBeOk)
        RemoveModelResources();
 }
 
+TEST(FaceRecognitionTest, LabelUpdateAfterInferenceShouldBeOk)
+{
+       mv_face_recognition_h handle;
+       vector<string> image_names = { "037830.png", "038965.png", "045978.png", "061310.png", "062261.png",
+                                                                  "029342.png", "000928.png", "008922.png", "054616.png" };
+       vector<string> label_names = { "2929", "2929", "2929", "7779", "7779", "7779", "3448", "3448", "3448" };
+
+       int ret = mv_face_recognition_create(&handle);
+       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+       ret = mv_face_recognition_prepare(handle);
+       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+       // Register two labels.
+       for (size_t idx = 0; idx < image_names.size() - 3; ++idx) {
+               const string image_path = string(TRAINING_IMAGE_PATH) + image_names[idx];
+               mv_source_h mv_source = NULL;
+
+               int ret = mv_create_source(&mv_source);
+               ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+               ret = ImageHelper::loadImageToSource(image_path.c_str(), mv_source);
+               ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+               ret = mv_face_recognition_register(handle, mv_source, label_names[idx].c_str());
+               ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+               ret = mv_face_recognition_inference(handle, mv_source);
+               if (ret != MEDIA_VISION_ERROR_NO_DATA) {
+                       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+               }
+
+               ret = mv_destroy_source(mv_source);
+               ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+       }
+
+       size_t num_of_confidences = 0;
+       const float *confidences = nullptr;
+
+       ret = mv_face_recognition_get_confidence(handle, &confidences, &num_of_confidences);
+       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+       // num_of_confidences must be 2.
+       ASSERT_EQ(num_of_confidences, 2);
+
+       // Register other one.
+       for (size_t idx = image_names.size() - 3; idx < image_names.size(); ++idx) {
+               const string image_path = string(TRAINING_IMAGE_PATH) + image_names[idx];
+               mv_source_h mv_source = NULL;
+
+               int ret = mv_create_source(&mv_source);
+               ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+               ret = ImageHelper::loadImageToSource(image_path.c_str(), mv_source);
+               ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+               ret = mv_face_recognition_register(handle, mv_source, label_names[idx].c_str());
+               ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+               size_t num_of_confidences = 0;
+               const float *confidences = nullptr;
+
+               ret = mv_face_recognition_get_confidence(handle, &confidences, &num_of_confidences);
+               ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+               // num_of_confidence must be 2 because of no inference request.
+               ASSERT_EQ(num_of_confidences, 2);
+
+               // If input is last one then request an inference.
+               if (idx == image_names.size() - 1) {
+                       ret = mv_face_recognition_inference(handle, mv_source);
+                       if (ret != MEDIA_VISION_ERROR_NO_DATA) {
+                               ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+                       }
+
+                       ret = mv_face_recognition_get_confidence(handle, &confidences, &num_of_confidences);
+                       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+                       // num_of_confidence must be 3 now.
+                       ASSERT_EQ(num_of_confidences, 3);
+               }
+
+               ret = mv_destroy_source(mv_source);
+               ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+       }
+
+       ret = mv_face_recognition_destroy(handle);
+       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+       RemoveModelResources();
+}
+
 TEST(FaceRecognitionTest, GetLabelWithoutInferenceShouldBeError)
 {
        mv_face_recognition_h handle;