mv_machine_larning: add face iris detection
authorInki Dae <inki.dae@samsung.com>
Mon, 5 Dec 2022 06:11:59 +0000 (15:11 +0900)
committerInki Dae <inki.dae@samsung.com>
Wed, 14 Dec 2022 01:58:09 +0000 (10:58 +0900)
This time adds only face detection model support for
face iris task.

Change-Id: I73f88aee16c43ce822e819bbae5d66ea52bded76
Signed-off-by: Inki Dae <inki.dae@samsung.com>
23 files changed:
CMakeLists.txt
include/mv_face_iris_internal.h [new file with mode: 0644]
include/mv_face_iris_type.h [new file with mode: 0644]
mv_machine_learning/CMakeLists.txt
mv_machine_learning/face_iris/CMakeLists.txt [new file with mode: 0644]
mv_machine_learning/face_iris/include/face_detection_front.h [new file with mode: 0644]
mv_machine_learning/face_iris/include/face_detection_front_adapter.h [new file with mode: 0644]
mv_machine_learning/face_iris/include/face_detection_parser.h [new file with mode: 0644]
mv_machine_learning/face_iris/include/face_iris.h [new file with mode: 0644]
mv_machine_learning/face_iris/include/face_iris_type.h [new file with mode: 0644]
mv_machine_learning/face_iris/include/mv_face_iris_config.h [new file with mode: 0644]
mv_machine_learning/face_iris/include/mv_face_iris_open.h [new file with mode: 0644]
mv_machine_learning/face_iris/meta/face_iris.json [new file with mode: 0644]
mv_machine_learning/face_iris/src/face_detection_front.cpp [new file with mode: 0644]
mv_machine_learning/face_iris/src/face_detection_front_adapter.cpp [new file with mode: 0644]
mv_machine_learning/face_iris/src/face_detection_parser.cpp [new file with mode: 0644]
mv_machine_learning/face_iris/src/face_iris.cpp [new file with mode: 0644]
mv_machine_learning/face_iris/src/mv_face_iris.c [new file with mode: 0644]
mv_machine_learning/face_iris/src/mv_face_iris_open.cpp [new file with mode: 0644]
packaging/capi-media-vision.spec
test/testsuites/machine_learning/CMakeLists.txt
test/testsuites/machine_learning/face_iris/CMakeLists.txt [new file with mode: 0644]
test/testsuites/machine_learning/face_iris/test_face_iris.cpp [new file with mode: 0644]

index bc87c9dfab5a30bd70993e738924b6ea7fd94f3d..221f01b67cd64189b5a8493666845067c46efc3f 100644 (file)
@@ -36,6 +36,8 @@ set(MV_ROI_TRACKER_LIB_NAME "mv_roi_tracker" CACHE STRING
        "Name of the library will be built for tracker module (without extension).")
 set(MV_OBJECT_DETECTION_LIB_NAME "mv_object_detection" CACHE STRING
        "Name of the library will be built for object detection module (without extension).")
+set(MV_FACE_IRIS_LIB_NAME "mv_face_iris" CACHE STRING
+       "Name of the library will be built for face iris detection module (without extension).")
 
 include(FindPkgConfig)
 include(GNUInstallDirs)
@@ -170,6 +172,16 @@ configure_file(
 install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}-object-detection.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
 install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/mv_machine_learning/object_detection/meta/object_detection_3d.json DESTINATION ${CMAKE_INSTALL_DATADIR}/${fw_name})
 
+set(PC_NAME ${fw_name}-face-iris)
+set(PC_LDFLAGS "-l${MV_FACE_IRIS_LIB_NAME} -l${MV_COMMON_LIB_NAME}")
+configure_file(
+       ${fw_name}.pc.in
+       ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}-face-iris.pc
+       @ONLY
+)
+install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}-face-iris.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/mv_machine_learning/face_iris/meta/face_iris.json DESTINATION ${CMAKE_INSTALL_DATADIR}/${fw_name})
+
 if (${ENABLE_ML_FACE_RECOGNITION})
     set(PC_NAME ${fw_name}-training)
     set(PC_LDFLAGS "-l${MV_TRAINING_LIB_NAME} -l${MV_COMMON_LIB_NAME}")
diff --git a/include/mv_face_iris_internal.h b/include/mv_face_iris_internal.h
new file mode 100644 (file)
index 0000000..1a70bec
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2022 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.
+ */
+
+#ifndef __TIZEN_MEDIAVISION_FACE_IRIS_INTERNAL_H__
+#define __TIZEN_MEDIAVISION_FACE_IRIS_INTERNAL_H__
+
+#include <mv_common.h>
+#include <mv_face_iris_type.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+int mv_face_iris_create(mv_face_iris_h *infer);
+
+int mv_face_iris_destroy(mv_face_iris_h infer);
+
+int mv_face_iris_configure(mv_face_iris_h infer);
+
+int mv_face_iris_prepare(mv_face_iris_h infer);
+
+int mv_face_iris_inference(mv_face_iris_h infer, mv_source_h source);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __TIZEN_MEDIAVISION_FACE_IRIS_INTERNAL_H__ */
diff --git a/include/mv_face_iris_type.h b/include/mv_face_iris_type.h
new file mode 100644 (file)
index 0000000..03bb263
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022 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.
+ */
+
+#ifndef __TIZEN_MEDIAVISION_FACE_IRIS_TYPE_H__
+#define __TIZEN_MEDIAVISION_FACE_IRIS_TYPE_H__
+
+#include <mv_common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef void *mv_face_iris_h;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __TIZEN_MEDIAVISION_FACE_IRIS_TYPE_H__ */
index 02e1678c9b5698724aeabdb92b4645656a9c07ce..a5767e03fc1177fbc590e434084b53f557355849 100644 (file)
@@ -1,5 +1,6 @@
 add_subdirectory(inference)
 add_subdirectory(object_detection)
+add_subdirectory(face_iris)
 
 if (${ENABLE_ML_FACE_RECOGNITION})
     message("Enabled machine learning face recognition feature.")
diff --git a/mv_machine_learning/face_iris/CMakeLists.txt b/mv_machine_learning/face_iris/CMakeLists.txt
new file mode 100644 (file)
index 0000000..38eb83d
--- /dev/null
@@ -0,0 +1,21 @@
+project(${MV_FACE_IRIS_LIB_NAME})
+cmake_minimum_required(VERSION 2.6...3.13)
+
+pkg_check_modules(${PROJECT_NAME}_DEP REQUIRED inference-engine-interface-common iniparser json-glib-1.0)
+file(GLOB MV_FACE_IRIS_SOURCE_LIST  "${PROJECT_SOURCE_DIR}/src/*.c" "${PROJECT_SOURCE_DIR}/src/*.cpp" "${PROJECT_SOURCE_DIR}/../meta/src/*.cpp")
+
+find_package(OpenCV REQUIRED dnn imgproc)
+if(NOT OpenCV_FOUND)
+       message(SEND_ERROR "OpenCV NOT FOUND")
+       return()
+endif()
+
+if(FORCED_STATIC_BUILD)
+       add_library(${PROJECT_NAME} STATIC ${MV_FACE_IRIS_SOURCE_LIST})
+else()
+       add_library(${PROJECT_NAME} SHARED ${MV_FACE_IRIS_SOURCE_LIST})
+endif()
+
+target_link_libraries(${PROJECT_NAME} ${MV_COMMON_LIB_NAME} ${OpenCV_LIBS} ${${PROJECT_NAME}_DEP_LIBRARIES} mv_inference)
+target_include_directories(${PROJECT_NAME} PRIVATE include ../inference/include ../common/include ../meta/include)
+install(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR})
diff --git a/mv_machine_learning/face_iris/include/face_detection_front.h b/mv_machine_learning/face_iris/include/face_detection_front.h
new file mode 100644 (file)
index 0000000..54a018c
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2022 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.
+ */
+
+#ifndef __FACE_DETECTION_FRONT_H__
+#define __FACE_DETECTION_FRONT_H__
+
+#include <memory>
+#include <list>
+#include <mv_common.h>
+#include "mv_private.h"
+
+#include "face_iris.h"
+#include <mv_inference_type.h>
+#include "EngineConfig.h"
+
+namespace mediavision
+{
+namespace machine_learning
+{
+class FaceDetectionFront : public FaceIris
+{
+private:
+       face_detection_result_s _result;
+       std::vector<fvec2> _anchors;
+       inference_engine_tensor_buffer *_bboxes_tensor;
+       inference_engine_tensor_buffer *_scores_tensor;
+
+       float *GetBboxPtr(unsigned int anchor_idx);
+       unsigned int CreateBlazefaceAnchors(unsigned int input_w, unsigned int input_h);
+
+       void RotVec(fvec2 &vec, float rotation);
+       void ComputeFaceRect(face_t &face);
+       float NormalizeRadians(float angle);
+       void ComputeRotation(face_t &face);
+       void PackFaceResult(face_detection_result_s *facedet_result, std::list<face_t> &face_list);
+       float CalcIntersectionOverUnion(face_t &face0, face_t &face1);
+       void NonMaxSuppression(std::list<face_t> &face_list, std::list<face_t> &face_sel_list,
+                                                  float iou_thresh);
+       void DecodeBoundingBox(std::list<face_t> &face_list, float score_thresh,
+                                                  unsigned int input_img_w, unsigned int input_img_h, const float *scores_ptr);
+
+public:
+       FaceDetectionFront();
+       ~FaceDetectionFront();
+       void parseMetaFile() override;
+       virtual void after_prepare() override;
+       face_detection_result_s &getResult() override;
+};
+
+} // machine_learning
+} // mediavision
+
+#endif
\ No newline at end of file
diff --git a/mv_machine_learning/face_iris/include/face_detection_front_adapter.h b/mv_machine_learning/face_iris/include/face_detection_front_adapter.h
new file mode 100644 (file)
index 0000000..005bc4b
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2022 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.
+ */
+
+#ifndef __FACE_DETECTION_FRONT_ADAPTER_H__
+#define __FACE_DETECTION_FRONT_ADAPTER_H__
+
+#include <dlog.h>
+
+#include "EngineConfig.h"
+#include "itask.h"
+#include "face_detection_front.h"
+
+namespace mediavision
+{
+namespace machine_learning
+{
+
+template<typename T, typename V> class FaceDetectionFrontAdapter : public mediavision::common::ITask<T, V>
+{
+private:
+       std::unique_ptr<FaceIris> _face_detection;
+       T _source;
+
+public:
+       FaceDetectionFrontAdapter();
+       ~FaceDetectionFrontAdapter();
+
+       void create(int type) override;
+
+       void configure() override;
+       void prepare() override;
+       void setInput(T &t) override;
+       void perform() override;
+       V &getOutput() override;
+};
+
+} // machine_learning
+} // mediavision
+
+#endif
\ No newline at end of file
diff --git a/mv_machine_learning/face_iris/include/face_detection_parser.h b/mv_machine_learning/face_iris/include/face_detection_parser.h
new file mode 100644 (file)
index 0000000..d2295a1
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2022 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.
+ */
+
+#ifndef __FACE_IRIS_PARSER_H__
+#define __FACE_IRIS_PARSER_H__
+
+#include "MetaParser.h"
+#include "PostprocessParser.h"
+
+namespace mediavision
+{
+namespace machine_learning
+{
+class FaceDetectionParser : public MetaParser
+{
+private:
+       PostprocessParser _postprocessParser;
+
+protected:
+       void parsePostprocess(std::shared_ptr<MetaInfo> meta_info, JsonObject *in_obj) override;
+
+public:
+       FaceDetectionParser();
+       ~FaceDetectionParser();
+};
+
+}
+}
+
+#endif
\ No newline at end of file
diff --git a/mv_machine_learning/face_iris/include/face_iris.h b/mv_machine_learning/face_iris/include/face_iris.h
new file mode 100644 (file)
index 0000000..724131d
--- /dev/null
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2022 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.
+ */
+
+#ifndef __OBJECT_DETECTION_H__
+#define __OBJECT_DETECTION_H__
+
+#include <mv_common.h>
+#include <mv_inference_type.h>
+#include "mv_private.h"
+
+#include "EngineConfig.h"
+#include "inference_engine_common_impl.h"
+#include "Inference.h"
+#include "face_iris_type.h"
+#include "face_detection_parser.h"
+#include "Preprocess.h"
+
+namespace mediavision
+{
+namespace machine_learning
+{
+class FaceIris
+{
+protected:
+       std::unique_ptr<mediavision::inference::Inference> _inference;
+
+       std::unique_ptr<MediaVision::Common::EngineConfig> _config;
+       std::unique_ptr<MetaParser> _parser;
+       Preprocess _preprocess;
+       std::string _modelFilePath;
+       std::string _modelMetaFilePath;
+       int _backendType;
+       int _targetDeviceType;
+
+public:
+       FaceIris();
+       virtual ~FaceIris() = default;
+       virtual void parseMetaFile() = 0;
+       void configure();
+       void prepare();
+       virtual void after_prepare() { }
+       void preprocess(mv_source_h &mv_src);
+       void inference(mv_source_h source);
+       virtual face_detection_result_s &getResult() = 0;
+};
+
+} // machine_learning
+} // mediavision
+
+#endif
\ No newline at end of file
diff --git a/mv_machine_learning/face_iris/include/face_iris_type.h b/mv_machine_learning/face_iris/include/face_iris_type.h
new file mode 100644 (file)
index 0000000..4f03d32
--- /dev/null
@@ -0,0 +1,111 @@
+/**
+ * Copyright (c) 2022 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.
+ */
+
+#ifndef __FACE_IRIS_TYPE_H__
+#define __FACE_IRIS_TYPE_H__
+
+#include <mv_common.h>
+#include <mv_inference_type.h>
+
+#define MAX_FACE_NUM    10
+#define FACE_KEY_NUM    468
+
+namespace mediavision
+{
+namespace machine_learning
+{
+
+struct face_detection_input_s {
+       mv_source_h inference_src;
+};
+
+struct face_landmark_input_s {
+};
+
+struct face_iris_input_s {
+};
+
+enum class face_iris_task_type_e {
+       FACE_DETECTION_TASK = 1,
+       FACE_LANDMARK_DETECTION_TASK,
+       FACE_IRIS_DETECTION_TASK
+       // TODO
+};
+
+enum face_key_id {
+    kRightEye = 0,  //  0
+    kLeftEye,       //  1
+    kNose,          //  2
+    kMouth,         //  3
+    kRightEar,      //  4
+    kLeftEar,       //  5
+    kFaceKeyNum
+};
+
+struct fvec2 {
+    float x, y;
+};
+
+struct fvec3 {
+    float x, y, z;
+};
+
+struct face_t {
+    float score;
+    fvec2 topleft;
+    fvec2 btmright;
+    fvec2 keys[kFaceKeyNum];
+
+    float rotation;
+    float face_cx;
+    float face_cy;
+    float face_w;
+    float face_h;
+    fvec2 face_pos[4];
+};
+
+struct face_detection_result_s {
+    int num;
+    face_t faces[MAX_FACE_NUM];
+};
+
+struct rect_t {
+    fvec2 topleft;
+    fvec2 btmright;
+};
+
+struct eye_region_t {
+    float rotation;
+    fvec2 center;
+    fvec2 size;
+};
+
+struct face_landmark_result_s {
+    float score;
+    fvec3 joint[FACE_KEY_NUM];
+    eye_region_t    eye_rgn[2];
+    fvec2           eye_pos[2][4];
+};
+
+struct face_iris_result_s {
+    fvec3 eye_landmark[71];
+    fvec3 iris_landmark[5];
+};
+
+}
+}
+
+#endif
\ No newline at end of file
diff --git a/mv_machine_learning/face_iris/include/mv_face_iris_config.h b/mv_machine_learning/face_iris/include/mv_face_iris_config.h
new file mode 100644 (file)
index 0000000..d883199
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2022 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.
+ */
+
+#ifndef __MEDIA_VISION_FACE_IRIS_CONFIG_H__
+#define __MEDIA_VISION_FACE_IRIS_CONFIG_H__
+
+#define MV_FACE_DETECTION_MODEL_FILE_PATH "DETECTION_MODEL_FILE_PATH"
+#define MV_FACE_LANDMARK_MODEL_FILE_PATH "LANDMARK_MODEL_FILE_PATH"
+#define MV_FACE_IRIS_MODEL_FILE_PATH "IRIS_MODEL_FILE_PATH"
+
+#define MV_FACE_DETECTION_MODEL_META_PATH "DETECTION_MODEL_META_FILE_PATH"
+#define MV_FACE_LANDMARK_MODEL_META_PATH "LANDMARK_MODEL_META_FILE_PATH"
+#define MV_FACE_IRIS_MODEL_META_PATH "IRIS_MODEL_META_FILE_PATH"
+
+#define MV_FACE_IRIS_BACKEND_TYPE "BACKEND_TYPE"
+
+#define MV_FACE_IRIS_TARGET_DEVICE_TYPE "TARGET_DEVICE_TYPE"
+
+#define MV_FACE_IRIS_META_FILE_NAME "face_iris.json"
+
+#endif
diff --git a/mv_machine_learning/face_iris/include/mv_face_iris_open.h b/mv_machine_learning/face_iris/include/mv_face_iris_open.h
new file mode 100644 (file)
index 0000000..d80f91d
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2022 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.
+ */
+
+#ifndef __MEDIA_VISION_FACE_IRIS_OPEN_H__
+#define __MEDIA_VISION_FACE_IRIS_OPEN_H__
+
+#include <mv_common.h>
+#include <mv_private.h>
+#include <mv_face_iris_type.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+int mv_face_iris_create_open(mv_face_iris_h *out_handle);
+
+int mv_face_iris_destroy_open(mv_face_iris_h handle);
+
+int mv_face_iris_configure_open(mv_face_iris_h handle);
+
+int mv_face_iris_prepare_open(mv_face_iris_h handle);
+
+int mv_face_iris_inference_open(mv_face_iris_h handle, mv_source_h source);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __MEDIA_VISION_INFERENCE_OPEN_H__ */
diff --git a/mv_machine_learning/face_iris/meta/face_iris.json b/mv_machine_learning/face_iris/meta/face_iris.json
new file mode 100644 (file)
index 0000000..18a010c
--- /dev/null
@@ -0,0 +1,45 @@
+{
+    "attributes":
+    [
+               {
+            "name"  : "DETECTION_MODEL_FILE_PATH",
+            "type"  : "string",
+            "value" : "/home/owner/media/res/face_iris/tflite/face_detection_front.tflite"
+        },
+               {
+            "name"  : "LANDMARK_MODEL_FILE_PATH",
+            "type"  : "string",
+            "value" : "/home/owner/media/res/face_iris/tflite/face_landmark.tflite"
+        },
+               {
+            "name"  : "IRIS_MODEL_FILE_PATH",
+            "type"  : "string",
+            "value" : "/home/owner/media/res/face_iris/tflite/face_iris.tflite"
+        },
+               {
+            "name"  : "DETECTION_MODEL_META_FILE_PATH",
+            "type"  : "string",
+            "value" : "/home/owner/media/res/face_iris/tflite/face_detection_front.json"
+        },
+               {
+            "name"  : "LANDMARK_MODEL_META_FILE_PATH",
+            "type"  : "string",
+            "value" : "/home/owner/media/res/face_iris/tflite/face_landmark.json"
+        },
+               {
+            "name"  : "IRIS_MODEL_META_FILE_PATH",
+            "type"  : "string",
+            "value" : "/home/owner/media/res/face_iris/tflite/face_iris.json"
+        },
+               {
+            "name"  : "BACKEND_TYPE",
+            "type"  : "integer",
+            "value" : 1
+        },
+        {
+            "name"  : "TARGET_DEVICE_TYPE",
+            "type"  : "integer",
+            "value" : 1
+        }
+    ]
+}
diff --git a/mv_machine_learning/face_iris/src/face_detection_front.cpp b/mv_machine_learning/face_iris/src/face_detection_front.cpp
new file mode 100644 (file)
index 0000000..cd2ba36
--- /dev/null
@@ -0,0 +1,414 @@
+/**
+ * Copyright (c) 2022 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 <string.h>
+#include <map>
+#include <algorithm>
+#include <iostream>
+
+#include "machine_learning_exception.h"
+#include "face_detection_front.h"
+#include "mv_face_iris_config.h"
+#include "Postprocess.h"
+
+using namespace std;
+using namespace mediavision::inference;
+using namespace MediaVision::Common;
+using namespace mediavision::machine_learning::exception;
+
+namespace mediavision
+{
+namespace machine_learning
+{
+FaceDetectionFront::FaceDetectionFront() : _result()
+{
+       _inference = make_unique<Inference>();
+       _parser = make_unique<FaceDetectionParser>();
+}
+
+FaceDetectionFront::~FaceDetectionFront()
+{}
+
+static bool IsJsonFile(const string &fileName)
+{
+       return (!fileName.substr(fileName.find_last_of(".") + 1).compare("json"));
+}
+
+void FaceDetectionFront::parseMetaFile()
+{
+       _config = make_unique<EngineConfig>(string(MV_CONFIG_PATH) + string(MV_FACE_IRIS_META_FILE_NAME));
+
+       int ret = _config->getIntegerAttribute(string(MV_FACE_IRIS_BACKEND_TYPE), &_backendType);
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to get backend engine type.");
+
+       ret = _config->getIntegerAttribute(string(MV_FACE_IRIS_TARGET_DEVICE_TYPE), &_targetDeviceType);
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to get target device type.");
+
+       ret = _config->getStringAttribute(MV_FACE_DETECTION_MODEL_FILE_PATH, &_modelFilePath);
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to get model file path");
+
+       ret = _config->getStringAttribute(MV_FACE_DETECTION_MODEL_META_PATH, &_modelMetaFilePath);
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to get model meta file path");
+
+       if (_modelMetaFilePath.empty())
+               throw InvalidOperation("Model meta file doesn't exist.");
+
+       if (!IsJsonFile(_modelMetaFilePath))
+               throw InvalidOperation("Model meta file should be json");
+
+       _parser->load(_modelMetaFilePath);
+}
+
+void FaceDetectionFront::after_prepare()
+{
+       CreateBlazefaceAnchors(_inference->getInputWidth(), _inference->getInputHeight());
+}
+
+float *FaceDetectionFront::GetBboxPtr(unsigned int anchor_idx)
+{
+       int idx = 16 * anchor_idx;
+       float *bboxes_ptr = reinterpret_cast<float *>(_bboxes_tensor->buffer);
+
+       return &bboxes_ptr[idx];
+}
+
+unsigned int FaceDetectionFront::CreateBlazefaceAnchors(unsigned int input_w, unsigned int input_h)
+{
+    /* ANCHORS_CONFIG  */
+    int strides[2] = {8, 16};
+    int anchors[2] = {2,  6};
+    int numtotal = 0;
+
+    for (int idx = 0; idx < 2; idx++) {
+        int stride = strides[idx];
+        int gridCols = (input_w + stride -1) / stride;
+        int gridRows = (input_h + stride -1) / stride;
+        int anchorNum = anchors[idx];
+        fvec2 anchor;
+
+        for (int gridY = 0; gridY < gridRows; gridY++) {
+            anchor.y = stride * (gridY + 0.5f);
+
+            for (int gridX = 0; gridX < gridCols; gridX++) {
+                anchor.x = stride * (gridX + 0.5f);
+
+                for (int n = 0; n < anchorNum; n++) {
+                    _anchors.push_back(anchor);
+                    numtotal++;
+                }
+            }
+        }
+    }
+
+    return numtotal;
+}
+
+static bool SortRightMajor(face_t &v1, face_t &v2)
+{
+    if (v1.keys[kRightEye].x > v2.keys[kRightEye].x)
+        return true;
+    else
+        return false;
+}
+
+void FaceDetectionFront::RotVec(fvec2 &vec, float rotation)
+{
+    float sx = vec.x;
+    float sy = vec.y;
+    vec.x = sx * std::cos(rotation) - sy * std::sin(rotation);
+    vec.y = sx * std::sin(rotation) + sy * std::cos(rotation);
+}
+
+void FaceDetectionFront::ComputeFaceRect(face_t &face)
+{
+       float width    = face.btmright.x - face.topleft.x;
+       float height   = face.btmright.y - face.topleft.y;
+       float palm_cx  = face.topleft.x + width  * 0.5f;
+       float palm_cy  = face.topleft.y + height * 0.5f;
+       float face_cx;
+       float face_cy;
+       float rotation = face.rotation;
+       float shift_x = 0;// 0.0f;
+       float shift_y = 0;//-0.5f;
+
+       if (rotation == 0.0f) {
+               face_cx = palm_cx + (width  * shift_x);
+               face_cy = palm_cy + (height * shift_y);
+       } else {
+               float dx = (width  * shift_x) * std::cos(rotation) -
+                                       (height * shift_y) * std::sin(rotation);
+               float dy = (width  * shift_x) * std::sin(rotation) +
+                                       (height * shift_y) * std::cos(rotation);
+               face_cx = palm_cx + dx;
+               face_cy = palm_cy + dy;
+       }
+
+       float long_side = std::max(width, height);
+       width  = long_side;
+       height = long_side;
+       float face_w = width  * 1.5f;
+       float face_h = height * 1.5f;
+
+       face.face_cx = face_cx;
+       face.face_cy = face_cy;
+       face.face_w  = face_w;
+       face.face_h  = face_h;
+
+       float dx = face_w * 0.5f;
+       float dy = face_h * 0.5f;
+
+       face.face_pos[0].x = - dx;  face.face_pos[0].y = - dy;
+       face.face_pos[1].x = + dx;  face.face_pos[1].y = - dy;
+       face.face_pos[2].x = + dx;  face.face_pos[2].y = + dy;
+       face.face_pos[3].x = - dx;  face.face_pos[3].y = + dy;
+
+       for (int i = 0; i < 4; i ++) {
+               RotVec(face.face_pos[i], rotation);
+               face.face_pos[i].x += face_cx;
+               face.face_pos[i].y += face_cy;
+       }
+}
+
+float FaceDetectionFront::NormalizeRadians(float angle)
+{
+    return angle - 2 * M_PI * std::floor((angle - (-M_PI)) / (2 * M_PI));
+}
+
+void FaceDetectionFront::ComputeRotation(face_t &face)
+{
+       float x0 = face.keys[kRightEye].x;
+       float y0 = face.keys[kRightEye].y;
+       float x1 = face.keys[kLeftEye].x;
+       float y1 = face.keys[kLeftEye].y;
+
+       float target_angle = 0;//M_PI * 0.5f;
+       float rotation = target_angle - std::atan2(-(y1 - y0), x1 - x0);
+
+       face.rotation = NormalizeRadians(rotation);
+}
+
+void FaceDetectionFront::PackFaceResult(face_detection_result_s *facedet_result, list<face_t> &face_list)
+{
+       face_list.sort(SortRightMajor);
+
+       int num_faces = 0;
+       for (auto itr = face_list.begin(); itr != face_list.end(); itr ++) {
+               face_t face = *itr;
+
+               ComputeRotation(face);
+               ComputeFaceRect(face);
+
+               memcpy (&facedet_result->faces[num_faces], &face, sizeof (face));
+               num_faces ++;
+               facedet_result->num = num_faces;
+
+               if (num_faces >= MAX_FACE_NUM)
+                       break;
+       }
+}
+
+float FaceDetectionFront::CalcIntersectionOverUnion(face_t &face0, face_t &face1)
+{
+       float sx0 = face0.topleft.x;
+       float sy0 = face0.topleft.y;
+       float ex0 = face0.btmright.x;
+       float ey0 = face0.btmright.y;
+       float sx1 = face1.topleft.x;
+       float sy1 = face1.topleft.y;
+       float ex1 = face1.btmright.x;
+       float ey1 = face1.btmright.y;
+
+       float xmin0 = std::min (sx0, ex0);
+       float ymin0 = std::min (sy0, ey0);
+       float xmax0 = std::max (sx0, ex0);
+       float ymax0 = std::max (sy0, ey0);
+       float xmin1 = std::min (sx1, ex1);
+       float ymin1 = std::min (sy1, ey1);
+       float xmax1 = std::max (sx1, ex1);
+       float ymax1 = std::max (sy1, ey1);
+
+       float area0 = (ymax0 - ymin0) * (xmax0 - xmin0);
+       float area1 = (ymax1 - ymin1) * (xmax1 - xmin1);
+       if (area0 <= 0 || area1 <= 0)
+               return 0.0f;
+
+       float intersect_xmin = std::max (xmin0, xmin1);
+       float intersect_ymin = std::max (ymin0, ymin1);
+       float intersect_xmax = std::min (xmax0, xmax1);
+       float intersect_ymax = std::min (ymax0, ymax1);
+
+       float intersect_area = std::max (intersect_ymax - intersect_ymin, 0.0f) *
+                                                  std::max (intersect_xmax - intersect_xmin, 0.0f);
+
+       return intersect_area / (area0 + area1 - intersect_area);
+}
+
+static bool Compare(face_t &v1, face_t &v2)
+{
+    if (v1.score > v2.score)
+        return true;
+    else
+        return false;
+}
+
+void FaceDetectionFront::NonMaxSuppression(list<face_t> &face_list, list<face_t> &face_sel_list,
+                                                                                  float iou_thresh)
+{
+       face_list.sort(Compare);
+
+       for (auto itr = face_list.begin(); itr != face_list.end(); itr ++) {
+               face_t face_candidate = *itr;
+
+               int ignore_candidate = false;
+               for (auto itr_sel = face_sel_list.rbegin(); itr_sel != face_sel_list.rend(); itr_sel ++) {
+                       face_t face_sel = *itr_sel;
+
+                       float iou = CalcIntersectionOverUnion(face_candidate, face_sel);
+                       if (iou >= iou_thresh) {
+                               ignore_candidate = true;
+                               break;
+                       }
+               }
+
+               if (!ignore_candidate) {
+                       face_sel_list.push_back(face_candidate);
+                       if (face_sel_list.size() >= MAX_FACE_NUM)
+                               break;
+               }
+       }
+}
+
+void FaceDetectionFront::DecodeBoundingBox(list<face_t> &face_list, float score_thresh, unsigned int input_img_w,
+                                                                                  unsigned int input_img_h, const float *scores_ptr)
+{
+       face_t face_item;
+       int idx = 0;
+
+       if (_anchors.empty())
+               throw InvalidOperation("anchors is empty.");
+
+       for (auto itr = _anchors.begin(); itr != _anchors.end(); idx++, itr++)
+       {
+               fvec2 anchor = *itr;
+               float score0 = scores_ptr[idx];
+               float score = 1.0f / (1.0f + exp(-score0));
+
+               if (score > score_thresh)
+               {
+                       float *p = GetBboxPtr(idx);
+
+                       /* boundary box */
+                       float sx = p[0];
+                       float sy = p[1];
+                       float w  = p[2];
+                       float h  = p[3];
+
+                       float cx = sx + anchor.x;
+                       float cy = sy + anchor.y;
+
+                       cx /= (float)input_img_w;
+                       cy /= (float)input_img_h;
+                       w  /= (float)input_img_w;
+                       h  /= (float)input_img_h;
+
+                       fvec2 topleft, btmright;
+                       topleft.x  = cx - w * 0.5f;
+                       topleft.y  = cy - h * 0.5f;
+                       btmright.x = cx + w * 0.5f;
+                       btmright.y = cy + h * 0.5f;
+
+                       face_item.score    = score;
+                       face_item.topleft  = topleft;
+                       face_item.btmright = btmright;
+
+                       /* landmark positions (6 keys) */
+                       for (int j = 0; j < kFaceKeyNum; j ++)
+                       {
+                               float lx = p[4 + (2 * j) + 0];
+                               float ly = p[4 + (2 * j) + 1];
+                               lx += anchor.x;
+                               ly += anchor.y;
+                               lx /= (float)input_img_w;
+                               ly /= (float)input_img_h;
+
+                               face_item.keys[j].x = lx;
+                               face_item.keys[j].y = ly;
+                       }
+
+                       face_list.push_back(face_item);
+               }
+       }
+}
+
+face_detection_result_s &FaceDetectionFront::getResult()
+{
+       TensorBuffer &tensor_buffer_obj = _inference->GetOutputTensorBuffer();
+       IETensorBuffer &ie_tensor_buffer = tensor_buffer_obj.getIETensorBuffer();
+
+       for (IETensorBuffer::iterator it = ie_tensor_buffer.begin(); it != ie_tensor_buffer.end(); it++) {
+               if (it->first.compare("regressors") == 0) {
+                       _bboxes_tensor = tensor_buffer_obj.getTensorBuffer(it->first);
+                       if (!_bboxes_tensor)
+                               throw InvalidOperation("Fail to get regressors tensor buffer.");
+               }
+
+               if (it->first.compare("classificators") == 0) {
+                       _scores_tensor = tensor_buffer_obj.getTensorBuffer(it->first);
+                       if (!_scores_tensor)
+                               throw InvalidOperation("Fail to get classificators tensor buffer.");
+               }
+       }
+
+       if (!_bboxes_tensor || !_scores_tensor)
+               throw InvalidOperation("Invalid output tensor.");
+
+       list<face_t> face_list;
+       float score_thresh = 0.75f;
+       unsigned int input_img_w = _inference->getInputWidth();
+       unsigned int input_img_h = _inference->getInputHeight();
+
+       DecodeBoundingBox(face_list, score_thresh, input_img_w, input_img_h,
+                                         reinterpret_cast<float *>(_scores_tensor->buffer));
+
+       float iou_thresh = 0.3f;
+       list<face_t> face_nms_list;
+
+       NonMaxSuppression(face_list, face_nms_list,iou_thresh);
+
+       face_detection_result_s facedet_result;
+
+       PackFaceResult(&facedet_result, face_nms_list);
+       // TODO.
+
+       for (unsigned int idx = 0; idx < facedet_result.num; ++idx) {
+               face_t &face = facedet_result.faces[idx];
+
+               cout << "score = " << face.score << endl;
+               cout << "topleft = " << face.topleft.x << " : " << face.topleft.y << endl;
+               cout << "btmright = " << face.btmright.x << " : " << face.btmright.y << endl;
+               cout << "face_cx = " << face.face_cx << " face_cy = " << face.face_cy << endl;
+               cout << "face_w = " << face.face_w << " face_h = " << face.face_h << endl;
+       }
+
+       return _result;
+}
+
+}
+}
diff --git a/mv_machine_learning/face_iris/src/face_detection_front_adapter.cpp b/mv_machine_learning/face_iris/src/face_detection_front_adapter.cpp
new file mode 100644 (file)
index 0000000..689fc35
--- /dev/null
@@ -0,0 +1,89 @@
+/**
+ * Copyright (c) 2022 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 "machine_learning_exception.h"
+#include "face_detection_front_adapter.h"
+
+using namespace std;
+using namespace MediaVision::Common;
+using namespace mediavision::machine_learning;
+using namespace mediavision::machine_learning::exception;
+
+namespace mediavision
+{
+namespace machine_learning
+{
+template<typename T, typename V> FaceDetectionFrontAdapter<T, V>::FaceDetectionFrontAdapter() : _source()
+{}
+
+template<typename T, typename V> FaceDetectionFrontAdapter<T, V>::~FaceDetectionFrontAdapter()
+{}
+
+template<typename T, typename V> void FaceDetectionFrontAdapter<T, V>::create(int type)
+{
+       switch (type) {
+       case static_cast<int>(face_iris_task_type_e::FACE_DETECTION_TASK):
+               _face_detection = make_unique<FaceDetectionFront>();
+               break;
+       default:
+               throw InvalidParameter("Invalid face detection task type.");
+       }
+}
+
+template<typename T, typename V> void FaceDetectionFrontAdapter<T, V>::configure()
+{
+       try {
+               _face_detection->parseMetaFile();
+               _face_detection->configure();
+       } catch (const BaseException &e) {
+               throw e;
+       }
+}
+
+template<typename T, typename V> void FaceDetectionFrontAdapter<T, V>::prepare()
+{
+       try {
+               _face_detection->prepare();
+               _face_detection->after_prepare();
+       } catch (const BaseException &e) {
+               throw e;
+       }
+}
+
+template<typename T, typename V> void FaceDetectionFrontAdapter<T, V>::setInput(T &t)
+{
+       _source = t;
+}
+
+template<typename T, typename V> void FaceDetectionFrontAdapter<T, V>::perform()
+{
+       try {
+               _face_detection->preprocess(_source.inference_src);
+               _face_detection->inference(_source.inference_src);
+               _face_detection->getResult(); //
+       } catch (const BaseException &e) {
+               throw e;
+       }
+}
+
+template<typename T, typename V> V &FaceDetectionFrontAdapter<T, V>::getOutput()
+{
+       return _face_detection->getResult();
+}
+
+template class FaceDetectionFrontAdapter<face_detection_input_s, face_detection_result_s>;
+}
+}
\ No newline at end of file
diff --git a/mv_machine_learning/face_iris/src/face_detection_parser.cpp b/mv_machine_learning/face_iris/src/face_detection_parser.cpp
new file mode 100644 (file)
index 0000000..4c8c86b
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2022 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 <iostream>
+#include "machine_learning_exception.h"
+#include "face_detection_parser.h"
+
+using namespace std;
+using namespace mediavision::machine_learning::exception;
+
+namespace mediavision
+{
+namespace machine_learning
+{
+FaceDetectionParser::FaceDetectionParser()
+{
+       LOGI("ENTER");
+       LOGI("LEAVE");
+}
+
+FaceDetectionParser::~FaceDetectionParser()
+{}
+
+void FaceDetectionParser::parsePostprocess(shared_ptr<MetaInfo> meta_info, JsonObject *in_obj)
+{
+       LOGI("ENTER");
+
+       LOGI("tensor name : %s", meta_info->name.c_str());
+
+       if (json_object_has_member(in_obj, "box"))
+               _postprocessParser.parseBox(meta_info, in_obj);
+
+       LOGI("LEAVE");
+}
+
+}
+}
\ No newline at end of file
diff --git a/mv_machine_learning/face_iris/src/face_iris.cpp b/mv_machine_learning/face_iris/src/face_iris.cpp
new file mode 100644 (file)
index 0000000..0ec0152
--- /dev/null
@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) 2022 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 <string.h>
+#include <map>
+#include <memory>
+#include <algorithm>
+
+#include "machine_learning_exception.h"
+#include "face_iris.h"
+
+using namespace std;
+using namespace mediavision::inference;
+using namespace mediavision::machine_learning::exception;
+
+namespace mediavision
+{
+namespace machine_learning
+{
+FaceIris::FaceIris() : _backendType(), _targetDeviceType()
+{
+}
+
+void FaceIris::configure()
+{
+       int ret = _inference->Bind(_backendType, _targetDeviceType);
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to bind a backend engine.");
+}
+
+void FaceIris::prepare()
+{
+       int ret = _inference->configureInputMetaInfo(_parser->getInputMetaMap());
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to configure input tensor info from meta file.");
+
+       ret = _inference->configureOutputMetaInfo(_parser->getOutputMetaMap());
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to configure output tensor info from meta file.");
+
+       _inference->ConfigureModelFiles("", _modelFilePath, "");
+
+       // Request to load model files to a backend engine.
+       ret = _inference->Load();
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to load model files.");
+}
+void FaceIris::preprocess(mv_source_h &mv_src)
+{
+       LOGI("ENTER");
+
+       TensorBuffer &tensor_buffer_obj = _inference->getInputTensorBuffer();
+       IETensorBuffer &ie_tensor_buffer = tensor_buffer_obj.getIETensorBuffer();
+       vector<mv_source_h> mv_srcs = { mv_src };
+
+       _preprocess.run(mv_srcs, _parser->getInputMetaMap(), ie_tensor_buffer);
+
+       LOGI("LEAVE");
+}
+
+void FaceIris::inference(mv_source_h source)
+{
+       LOGI("ENTER");
+
+       vector<mv_source_h> sources;
+
+       sources.push_back(source);
+
+       int ret = _inference->Run();
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to run inference");
+
+       LOGI("LEAVE");
+}
+
+}
+}
\ No newline at end of file
diff --git a/mv_machine_learning/face_iris/src/mv_face_iris.c b/mv_machine_learning/face_iris/src/mv_face_iris.c
new file mode 100644 (file)
index 0000000..77821f0
--- /dev/null
@@ -0,0 +1,101 @@
+/**
+ * Copyright (c) 2022 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 "mv_private.h"
+#include "mv_face_iris_internal.h"
+#include "mv_face_iris_open.h"
+
+/**
+ * @file  mv_face_iris.c
+ * @brief This file contains Media Vision inference module.
+ */
+
+int mv_face_iris_create(mv_face_iris_h *infer)
+{
+       MEDIA_VISION_SUPPORT_CHECK(_mv_inference_check_system_info_feature_supported());
+       MEDIA_VISION_NULL_ARG_CHECK(infer);
+
+       MEDIA_VISION_FUNCTION_ENTER();
+
+       int ret = MEDIA_VISION_ERROR_NONE;
+
+       ret = mv_face_iris_create_open(infer);
+
+       MEDIA_VISION_FUNCTION_LEAVE();
+       return ret;
+}
+
+int mv_face_iris_destroy(mv_face_iris_h infer)
+{
+       MEDIA_VISION_SUPPORT_CHECK(_mv_inference_check_system_info_feature_supported());
+       MEDIA_VISION_INSTANCE_CHECK(infer);
+
+       MEDIA_VISION_FUNCTION_ENTER();
+
+       int ret = MEDIA_VISION_ERROR_NONE;
+
+       ret = mv_face_iris_destroy_open(infer);
+
+       MEDIA_VISION_FUNCTION_LEAVE();
+       return ret;
+}
+
+int mv_face_iris_configure(mv_face_iris_h infer)
+{
+       MEDIA_VISION_SUPPORT_CHECK(_mv_inference_check_system_info_feature_supported());
+       MEDIA_VISION_INSTANCE_CHECK(infer);
+
+       MEDIA_VISION_FUNCTION_ENTER();
+
+       int ret = MEDIA_VISION_ERROR_NONE;
+
+       ret = mv_face_iris_configure_open(infer);
+
+       MEDIA_VISION_FUNCTION_LEAVE();
+       return ret;
+}
+
+int mv_face_iris_prepare(mv_face_iris_h infer)
+{
+       MEDIA_VISION_SUPPORT_CHECK(_mv_inference_check_system_info_feature_supported());
+       MEDIA_VISION_INSTANCE_CHECK(infer);
+
+       MEDIA_VISION_FUNCTION_ENTER();
+
+       int ret = MEDIA_VISION_ERROR_NONE;
+
+       ret = mv_face_iris_prepare_open(infer);
+
+       MEDIA_VISION_FUNCTION_LEAVE();
+       return ret;
+}
+
+int mv_face_iris_inference(mv_face_iris_h infer, mv_source_h source)
+{
+       MEDIA_VISION_SUPPORT_CHECK(_mv_inference_image_check_system_info_feature_supported());
+       MEDIA_VISION_INSTANCE_CHECK(source);
+       MEDIA_VISION_INSTANCE_CHECK(infer);
+
+       MEDIA_VISION_FUNCTION_ENTER();
+
+       int ret = MEDIA_VISION_ERROR_NONE;
+
+       ret = mv_face_iris_inference_open(infer, source);
+
+       MEDIA_VISION_FUNCTION_LEAVE();
+
+       return ret;
+}
\ No newline at end of file
diff --git a/mv_machine_learning/face_iris/src/mv_face_iris_open.cpp b/mv_machine_learning/face_iris/src/mv_face_iris_open.cpp
new file mode 100644 (file)
index 0000000..af473e3
--- /dev/null
@@ -0,0 +1,170 @@
+/**
+ * Copyright (c) 2022 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 "mv_private.h"
+#include "itask.h"
+#include "mv_face_iris_open.h"
+#include "face_detection_front_adapter.h"
+#include "machine_learning_exception.h"
+#include "face_iris_type.h"
+#include "context.h"
+
+#include <new>
+#include <unistd.h>
+#include <string>
+#include <algorithm>
+
+using namespace std;
+using namespace mediavision::inference;
+using namespace mediavision::common;
+using namespace mediavision::machine_learning;
+using namespace MediaVision::Common;
+using namespace mediavision::machine_learning::exception;
+
+using FaceDetectionTask = ITask<face_detection_input_s, face_detection_result_s>;
+using FaceLandmarkTask = ITask<face_landmark_input_s, face_landmark_result_s>;
+using FaceIrisTask = ITask<face_iris_input_s, face_iris_result_s>;
+
+int mv_face_iris_create_open(mv_face_iris_h *out_handle)
+{
+       if (!out_handle) {
+               LOGE("Handle can't be created because handle pointer is NULL");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       Context *context = new (nothrow) Context();
+       if (!context) {
+               LOGE("Fail to allocate a context.");
+               return MEDIA_VISION_ERROR_OUT_OF_MEMORY;
+       }
+
+       FaceDetectionTask *task = new (nothrow)
+                       FaceDetectionFrontAdapter<face_detection_input_s, face_detection_result_s>();
+       if (!task) {
+               delete context;
+               LOGE("Fail to allocate a task.");
+               return MEDIA_VISION_ERROR_OUT_OF_MEMORY;
+       }
+
+       try {
+               task->create(static_cast<int>(face_iris_task_type_e::FACE_DETECTION_TASK));
+       } catch (const BaseException &e) {
+               return e.getError();
+       }
+
+       context->__tasks.insert(make_pair("face_detection", task));
+       *out_handle = static_cast<mv_face_iris_h>(context);
+
+       LOGD("face iris handle [%p] has been created", *out_handle);
+
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+int mv_face_iris_destroy_open(mv_face_iris_h handle)
+{
+       if (!handle) {
+               LOGE("Handle is NULL.");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       auto context = static_cast<Context *>(handle);
+
+       for (auto &m : context->__tasks) {
+               if (m.first.compare("face_detection") == 0)
+                       delete static_cast<FaceDetectionTask *>(m.second);
+       }
+
+       delete context;
+
+       LOGD("face iris handle has been destroyed.");
+
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+int mv_face_iris_configure_open(mv_face_iris_h handle)
+{
+       LOGD("ENTER");
+
+       if (!handle) {
+               LOGE("Handle is NULL.");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       try {
+               auto context = static_cast<Context *>(handle);
+               auto task = static_cast<FaceDetectionTask *>(context->__tasks["face_detection"]);
+
+               task->configure();
+       } catch (const BaseException &e) {
+               LOGE("%s", e.what());
+               return e.getError();
+       }
+
+       LOGD("LEAVE");
+
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+int mv_face_iris_prepare_open(mv_face_iris_h handle)
+{
+       LOGD("ENTER");
+
+       if (!handle) {
+               LOGE("Handle is NULL.");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       try {
+               auto context = static_cast<Context *>(handle);
+               auto task = static_cast<FaceDetectionTask *>(context->__tasks["face_detection"]);
+
+               task->prepare();
+       } catch (const BaseException &e) {
+               LOGE("%s", e.what());
+               return e.getError();
+       }
+
+       LOGD("LEAVE");
+
+       return MEDIA_VISION_ERROR_NONE;
+}
+
+int mv_face_iris_inference_open(mv_face_iris_h handle, mv_source_h source)
+{
+       LOGD("ENTER");
+
+       if (!handle) {
+               LOGE("Handle is NULL.");
+               return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+       }
+
+       try {
+               auto context = static_cast<Context *>(handle);
+               auto task = static_cast<FaceDetectionTask *>(context->__tasks["face_detection"]);
+
+               face_detection_input_s input = { source };
+
+               task->setInput(input);
+               task->perform();
+       } catch (const BaseException &e) {
+               LOGE("%s", e.what());
+               return e.getError();
+       }
+
+       LOGD("LEAVE");
+
+       return MEDIA_VISION_ERROR_NONE;
+}
\ No newline at end of file
index 1d6cfa21079234f0503c30628eea03106c582740..2fce6df6e644972842b7450c1ac99332c5c74be8 100644 (file)
@@ -408,6 +408,8 @@ find . -name '*.gcno' -exec cp --parents '{}' "$gcno_obj_dir" ';'
 %{_libdir}/libmv_inference*.so
 %{_datadir}/%{name}/object_detection_3d.json
 %{_libdir}/libmv_object_detection*.so
+%{_datadir}/%{name}/face_iris.json
+%{_libdir}/libmv_face_iris*.so
 %if "%{enable_ml_face_recognition}" == "1"
 %{_datadir}/%{name}/face_recognition.json
 %{_libdir}/libmv_training.so
@@ -417,8 +419,10 @@ find . -name '*.gcno' -exec cp --parents '{}' "$gcno_obj_dir" ';'
 %files machine_learning-devel
 %{_includedir}/media/mv_infer*.h
 %{_includedir}/media/mv_object_detection_3d*.h
+%{_includedir}/media/mv_face_iris*.h
 %{_libdir}/pkgconfig/*inference.pc
 %{_libdir}/pkgconfig/*object-detection.pc
+%{_libdir}/pkgconfig/*face-iris.pc
 %if "%{enable_ml_face_recognition}" == "1"
 %{_includedir}/media/mv_face_recognition*.h
 %{_libdir}/pkgconfig/*training.pc
@@ -446,6 +450,7 @@ find . -name '*.gcno' -exec cp --parents '{}' "$gcno_obj_dir" ';'
 %{_libdir}/libmv_testsuite*.so
 %{_bindir}/mv_*
 %{_bindir}/test_object_detection_3d
+%{_bindir}/test_face_iris
 %if "%{enable_ml_face_recognition}" == "1"
 %{_bindir}/test_face_recognition
 %{_bindir}/measure_face_recognition
index 288a2ef13044f796412f90226eabfebf24941827..584eba0ba5fcbbd8183d95c57ed2ac15a2ab0d80 100644 (file)
@@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 2.6...3.13)
 
 add_subdirectory(${PROJECT_SOURCE_DIR}/inference)
 add_subdirectory(${PROJECT_SOURCE_DIR}/object_detection)
+add_subdirectory(${PROJECT_SOURCE_DIR}/face_iris)
 
 if (${ENABLE_ML_FACE_RECOGNITION})
     message("Enabled machine learning face recognition test cases.")
diff --git a/test/testsuites/machine_learning/face_iris/CMakeLists.txt b/test/testsuites/machine_learning/face_iris/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d8ab79a
--- /dev/null
@@ -0,0 +1,14 @@
+project(mv_face_iris_suite)
+cmake_minimum_required(VERSION 2.6...3.13)
+
+set(TEST_FACE_IRIS test_face_iris)
+
+add_executable(${TEST_FACE_IRIS} test_face_iris.cpp)
+
+target_link_libraries(${TEST_FACE_IRIS} gtest gtest_main
+                      mv_inference
+                      mv_face_iris
+                      mv_image_helper
+)
+
+install(TARGETS ${TEST_FACE_IRIS} DESTINATION ${CMAKE_INSTALL_BINDIR})
\ No newline at end of file
diff --git a/test/testsuites/machine_learning/face_iris/test_face_iris.cpp b/test/testsuites/machine_learning/face_iris/test_face_iris.cpp
new file mode 100644 (file)
index 0000000..3aa6c53
--- /dev/null
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2022 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 <iostream>
+#include <string.h>
+#include <map>
+
+#include "gtest/gtest.h"
+
+#include "ImageHelper.h"
+#include "mv_face_iris_internal.h"
+
+#define IMAGE_PATH "/res/inference/images/face_iris.jpeg"
+
+using namespace testing;
+using namespace std;
+
+using namespace MediaVision::Common;
+
+TEST(FaceIrisTest, InferenceShouldBeOk)
+{
+       mv_face_iris_h handle;
+
+       int ret = mv_face_iris_create(&handle);
+       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+       ret = mv_face_iris_configure(handle);
+       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+       ret = mv_face_iris_prepare(handle);
+       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+       const string image_path = IMAGE_PATH;
+       mv_source_h mv_source = NULL;
+
+       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_iris_inference(handle, mv_source);
+       ASSERT_EQ(ret, 0);
+
+       ret = mv_destroy_source(mv_source);
+       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+
+       ret = mv_face_iris_destroy(handle);
+       ASSERT_EQ(ret, MEDIA_VISION_ERROR_NONE);
+}
\ No newline at end of file