Context *context = static_cast<Context *>(handle);
map<string, void *>::iterator iter;
+ std::lock_guard<std::mutex> lock(context->_mutex);
+
for (iter = context->__tasks.begin(); iter != context->__tasks.end(); ++iter) {
if (iter->first.compare("face_recognition") == 0) {
auto face_recognition_task = static_cast<FaceRecognitionTask *>(iter->second);
auto face_recognition_task = static_cast<FaceRecognitionTask *>(context->__tasks["face_recognition"]);
auto facenet_task = static_cast<FacenetTask *>(context->__tasks["facenet"]);
+ std::lock_guard<std::mutex> lock(context->_mutex);
+
face_recognition_task->configure();
facenet_task->configure();
face_recognition_task->prepare();
auto face_recognition_task = static_cast<FaceRecognitionTask *>(context->__tasks["face_recognition"]);
auto facenet_task = static_cast<FacenetTask *>(context->__tasks["facenet"]);
+ std::lock_guard<std::mutex> lock(context->_mutex);
+
facenet_input_s facenet_input = { { source } };
facenet_task->setInput(facenet_input);
Context *context = static_cast<Context *>(handle);
auto face_recognition_task = static_cast<FaceRecognitionTask *>(context->__tasks["face_recognition"]);
+ std::lock_guard<std::mutex> lock(context->_mutex);
+
mv_face_recognition_input_s input = { mode::DELETE };
input.labels.clear();
auto face_recognition_task = static_cast<FaceRecognitionTask *>(context->__tasks["face_recognition"]);
auto facenet_task = static_cast<FacenetTask *>(context->__tasks["facenet"]);
+ std::lock_guard<std::mutex> lock(context->_mutex);
+
facenet_input_s facenet_input = { { source } };
facenet_task->setInput(facenet_input);
Context *context = static_cast<Context *>(handle);
auto face_recognition_task = static_cast<FaceRecognitionTask *>(context->__tasks["face_recognition"]);
+ std::lock_guard<std::mutex> lock(context->_mutex);
+
*out_label = face_recognition_task->getOutput().label.c_str();
} catch (const BaseException &e) {
LOGE("%s", e.what());
ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
ret = mv_face_recognition_inference(handle, mv_source);
- if (ret != MEDIA_VISION_ERROR_NO_DATA) {
+ 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);
const char *out_label = NULL;
ret = mv_face_recognition_get_label(handle, &out_label);
+ if (ret == MEDIA_VISION_ERROR_NO_DATA) {
+ image_idx++;
+ mv_destroy_source(mv_source);
+ continue;
+ }
+
ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
string label_str(out_label);
ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
ret = mv_face_recognition_register(handle, mv_source, image.second.c_str());
- ASSERT_EQ(ret, 0);
+ ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
ret = mv_destroy_source(mv_source);
ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
const char *out_label = NULL;
ret = mv_face_recognition_get_label(handle, &out_label);
- ASSERT_EQ(ret, MEDIA_VISION_ERROR_INVALID_OPERATION);
+ ASSERT_EQ(ret, MEDIA_VISION_ERROR_NO_DATA);
ret = mv_face_recognition_destroy(handle);
ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
const char *out_label = NULL;
ret = mv_face_recognition_get_label(handle, &out_label);
+ if (ret == MEDIA_VISION_ERROR_NO_DATA) {
+ is_no_data = true;
+ ret = MEDIA_VISION_ERROR_NONE;
+ }
+
ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
if (is_no_data)
--- /dev/null
+/**
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+#include <iostream>
+#include <string.h>
+#include <map>
+#include <thread>
+
+#include "gtest/gtest.h"
+
+#include "ImageHelper.h"
+#include "mv_face_recognition.h"
+#include "face_recognition_test_util.h"
+
+#define TRAINING_IMAGE_PATH "/home/owner/media/res/face_recognition/res/test/training/"
+#define TEST_IMAGE_PATH "/home/owner/media/res/face_recognition/res/test/test/"
+#define MAX_DATA_SET 15
+
+using namespace testing;
+using namespace std;
+
+static const map<string, string> training_images = {
+ { "037830.png", "2929" }, { "038965.png", "2929" }, { "045978.png", "2929" }, { "050501.png", "2929" },
+ { "065899.png", "2929" }, { "010348.png", "7779" }, { "029342.png", "7779" }, { "035939.png", "7779" },
+ { "061310.png", "7779" }, { "062261.png", "7779" }, { "000928.png", "3448" }, { "008922.png", "3448" },
+ { "029633.png", "3448" }, { "032962.png", "3448" }, { "054616.png", "3448" }
+};
+
+static const map<string, string> test_images = {
+ { "068468.png", "2929" }, { "068883.png", "2929" }, { "075004.png", "2929" }, { "078125.png", "2929" },
+ { "080649.png", "2929" }, { "074645.png", "7779" }, { "086536.png", "7779" }, { "089334.png", "7779" },
+ { "096514.png", "7779" }, { "100336.png", "7779" }, { "054757.png", "3448" }, { "064838.png", "3448" },
+ { "072749.png", "3448" }, { "073526.png", "3448" }, { "080451.png", "3448" }
+};
+
+using namespace MediaVision::Common;
+
+void Register(mv_face_recognition_h handle)
+{
+ for (auto &image : training_images) {
+ const string image_path = string(TRAINING_IMAGE_PATH) + image.first;
+ 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, image.second.c_str());
+ ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+ ret = mv_destroy_source(mv_source);
+ ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+ }
+}
+
+void Recognize(mv_face_recognition_h handle)
+{
+ vector<string> answers = { "3448", "3448", "2929", "2929", "3448", "3448", "7779", "2929",
+ "2929", "3448", "2929", "7779", "7779", "7779", "7779" };
+
+ unsigned int image_idx = 0;
+ unsigned int correct_cnt = 0;
+
+ for (auto &image : test_images) {
+ const string image_path = string(TEST_IMAGE_PATH) + image.first;
+ 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_inference(handle, mv_source);
+ if (ret == MEDIA_VISION_ERROR_NO_DATA) {
+ mv_destroy_source(mv_source);
+ image_idx++;
+ continue;
+ }
+
+ ret = mv_destroy_source(mv_source);
+ ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+ const char *out_label = NULL;
+
+ ret = mv_face_recognition_get_label(handle, &out_label);
+ if (ret != MEDIA_VISION_ERROR_NONE) {
+ image_idx++;
+ continue;
+ }
+
+ string label_str(out_label);
+
+ if (answers[image_idx++] == label_str)
+ correct_cnt++;
+ }
+
+ cout << "Correct/Total = " << correct_cnt << " / " << image_idx << endl;
+}
+
+void Unregister(mv_face_recognition_h handle)
+{
+ vector<string> labels = { "3448", "2929", "7779" };
+
+ for (auto &image : training_images) {
+ const string image_path = string(TRAINING_IMAGE_PATH) + image.first;
+ 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, image.second.c_str());
+ ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+ ret = mv_destroy_source(mv_source);
+ ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+ }
+
+ for (auto &label : labels) {
+ int ret = mv_face_recognition_unregister(handle, label.c_str());
+ ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+ }
+}
+
+TEST(FaceRecognitionMultithreadTest, RegisterAndRecognizeShouldBeOk)
+{
+ mv_face_recognition_h handle;
+
+ 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);
+
+ std::thread register_thread([&] { Register(handle); });
+
+ std::thread recognize_thread([&] { Recognize(handle); });
+
+ register_thread.join();
+ recognize_thread.join();
+
+ ret = mv_face_recognition_destroy(handle);
+ ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+ RemoveModelResources();
+}
+
+TEST(FaceRecognitionMultithreadTest, RegisterAndRecognizeAndUnregisterShouldBeOk)
+{
+ mv_face_recognition_h handle;
+
+ 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);
+
+ std::thread register_thread([&] { Register(handle); });
+
+ std::thread recognize_thread([&] { Recognize(handle); });
+
+ std::thread unregister_thread([&] { Unregister(handle); });
+
+ register_thread.join();
+ recognize_thread.join();
+ unregister_thread.join();
+
+ ret = mv_face_recognition_destroy(handle);
+ ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+ RemoveModelResources();
+}
+
+int main(int argc, char **argv)
+{
+ InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}