From: Inki Dae Date: Tue, 16 Jul 2024 07:52:18 +0000 (+0900) Subject: mv_machine_learning: add hand landmark detection model support X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2fe67749dbfed812359a08932724428e498f407c;p=platform%2Fcore%2Fapi%2Fmediavision.git mv_machine_learning: add hand landmark detection model support Change-Id: I997373757edb91bb6ef08dee4a7e3320df4837ba Signed-off-by: Inki Dae --- diff --git a/CMakeLists.txt b/CMakeLists.txt index efa3523a..d86eecba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -259,6 +259,7 @@ if (${ENABLE_ML_LANDMARK_DETECTION}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${fw_name}-landmark-detection.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/mv_machine_learning/landmark_detection/meta/facial_landmark.json DESTINATION ${CMAKE_INSTALL_DATADIR}/${fw_name}) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/mv_machine_learning/landmark_detection/meta/pose_landmark.json DESTINATION ${CMAKE_INSTALL_DATADIR}/${fw_name}) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/mv_machine_learning/landmark_detection/meta/hand_landmark.json DESTINATION ${CMAKE_INSTALL_DATADIR}/${fw_name}) list(APPEND TOTAL_REQUIRED ${PC_NAME}) list(APPEND TOTAL_LDFLAGS ${PC_LDFLAGS}) endif() diff --git a/include/mv_hand_landmark.h b/include/mv_hand_landmark.h new file mode 100644 index 00000000..6f8d1132 --- /dev/null +++ b/include/mv_hand_landmark.h @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2024 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_MV_HAND_LANDMARK_H__ +#define __TIZEN_MEDIAVISION_MV_HAND_LANDMARK_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @file mv_hand_landmark.h + * @internal + * @brief This file contains the Inference based Media Vision API. + */ + +/** + * @addtogroup CAPI_MEDIA_VISION_HAND_LANDMARK_MODULE + * @{ + */ + +/** + * @internal + * @brief Creates a inference handle for hand landmark object. + * @details Use this function to create a inference handle. After the creation + * the hand landmark task has to be prepared with + * mv_hand_landmark_prepare() function to prepare a network + * for the inference. + * + * @since_tizen 9.0 + * + * @remarks The @a handle should be released using mv_hand_landmark_destroy(). + * + * @param[out] handle The handle to the inference to be created. + * + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIA_VISION_ERROR_NONE Successful + * @retval #MEDIA_VISION_ERROR_NOT_SUPPORTED Not supported + * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIA_VISION_ERROR_OUT_OF_MEMORY Out of memory + * + * @code + * #include + * ... + * mv_hand_landmark_h handle = NULL; + * mv_hand_landmark_create(&handle); + * ... + * mv_hand_landmark_destroy(handle); + * @endcode + * + * @see mv_hand_landmark_destroy() + * @see mv_hand_landmark_prepare() + */ +int mv_hand_landmark_create(mv_hand_landmark_h *handle); + +/** + * @internal + * @brief Destroys inference handle and releases all its resources. + * + * @since_tizen 9.0 + * + * @param[in] handle The handle to the inference to be destroyed. + * + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIA_VISION_ERROR_NONE Successful + * @retval #MEDIA_VISION_ERROR_NOT_SUPPORTED Not supported + * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter + * + * @pre Create inference handle by using mv_hand_landmark_create() + * + * @see mv_hand_landmark_create() + */ +int mv_hand_landmark_destroy(mv_hand_landmark_h handle); + +/** + * @internal + * @brief Configures the backend for the hand landmark inference. + * + * @since_tizen 9.0 + * + * @param[in] handle The handle to the inference + * + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIA_VISION_ERROR_NONE Successful + * @retval #MEDIA_VISION_ERROR_NOT_SUPPORTED Not supported + * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation + * @retval #MEDIA_VISION_ERROR_OUT_OF_MEMORY Out of memory + */ +int mv_hand_landmark_configure(mv_hand_landmark_h handle); + +/** + * @internal + * @brief Prepares the hand landmark inference. + * @details Use this function to prepare the hand landmark inference based on + * the configured network. + * + * @since_tizen 9.0 + * + * @param[in] handle The handle to the inference. + * + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIA_VISION_ERROR_NONE Successful + * @retval #MEDIA_VISION_ERROR_NOT_SUPPORTED Not supported + * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIA_VISION_ERROR_INVALID_DATA Invalid model data + * @retval #MEDIA_VISION_ERROR_OUT_OF_MEMORY Out of memory + * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation + * @retval #MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT Not supported format + */ +int mv_hand_landmark_prepare(mv_hand_landmark_h handle); + +/** + * @internal + * @brief Performs the hand landmark inference on the @a source. + * + * @since_tizen 9.0 + * @remarks This function is synchronous and may take considerable time to run. + * + * @param[in] handle The handle to the inference + * @param[in] source The handle to the source of the media + * + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIA_VISION_ERROR_NONE Successful + * @retval #MEDIA_VISION_ERROR_NOT_SUPPORTED Not supported + * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIA_VISION_ERROR_INTERNAL Internal error + * @retval #MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT Source colorspace + * isn't supported + * + * @pre Create a source handle by calling mv_create_source() + * @pre Create an inference handle by calling mv_hand_landmark_create() + * @pre Prepare an inference by calling mv_hand_landmark_configure() + * @pre Prepare an inference by calling mv_hand_landmark_prepare() + * + * @par Inference Example + * @snippet hand_landmark_sync.c FLD sync + */ +int mv_hand_landmark_inference(mv_hand_landmark_h handle, mv_source_h source); + +/** + * @internal + * @brief Performs asynchronously the hand landmark inference on the @a source. + * + * @since_tizen 9.0 + * @remarks This function operates asynchronously, so it returns immediately upon invocation. + * The inference results are inserted into the outgoing queue within the framework + * in the order of processing, and the results can be obtained through mv_hand_landmark_get_position(). + * + * @param[in] handle The handle to the inference + * @param[in] source The handle to the source of the media + * + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIA_VISION_ERROR_NONE Successful + * @retval #MEDIA_VISION_ERROR_NOT_SUPPORTED Not supported + * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIA_VISION_ERROR_INTERNAL Internal error + * @retval #MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT Source colorspace + * isn't supported + * + * @pre Create a source handle by calling mv_create_source() + * @pre Create an inference handle by calling mv_hand_landmark_create() + * @pre Prepare an inference by calling mv_hand_landmark_configure() + * @pre Prepare an inference by calling mv_hand_landmark_prepare() + * + * @par Async Inference Example + * @snippet hand_landmark_async.c FLD async + */ +int mv_hand_landmark_inference_async(mv_hand_landmark_h handle, mv_source_h source); + +/** + * @internal + * @brief Gets the result count to objects. + * + * @since_tizen 9.0 + * + * @param[in] handle The handle to the inference + * @param[out] frame_number A frame number inferenced. + * @param[out] result_cnt A number of results. + * + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIA_VISION_ERROR_NONE Successful + * @retval #MEDIA_VISION_ERROR_NOT_SUPPORTED Not supported + * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIA_VISION_ERROR_INTERNAL Internal error + * + * @pre Create a source handle by calling mv_create_source() + * @pre Create an inference handle by calling mv_hand_landmark_create() + * @pre Prepare an inference by calling mv_hand_landmark_configure() + * @pre Prepare an inference by calling mv_hand_landmark_prepare() + * @pre Request an inference by calling mv_hand_landmark_inference() + */ +int mv_hand_landmark_get_result_count(mv_hand_landmark_h handle, unsigned long *frame_number, unsigned int *result_cnt); + +/** + * @internal + * @brief Gets the hand landmark position values to a given index. + * + * @since_tizen 9.0 + * @remarks pos_x and pos_y arrays are allocated internally by the framework and will remain valid + * until the handle is released. + * Please do not deallocate them directly, and if you want to use them after the handle is released, + * please copy them to user memory and use the copy. + * + * This function operates differently depending on the inference request method. + * - After mv_hand_landmark_inference() calls, this function returns hand landmark positions immediately. + * - After mv_hand_landmark_inference_async() calls, this function can be blocked until the asynchronous inference request is completed + * or the timeout occurs if no result within 3 seconds. + * + * Additionally, after calling the mv_hand_landmark_inference_async() function, the function operates + * in asynchronous mode until the handle is released. + * + * @param[in] handle The handle to the inference + * @param[in] index A result index. + * @param[out] pos_x An array containing x-coordinate values. + * @param[out] pos_y An array containing y-coordinate values. + * + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIA_VISION_ERROR_NONE Successful + * @retval #MEDIA_VISION_ERROR_NOT_SUPPORTED Not supported + * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIA_VISION_ERROR_INTERNAL Internal error + * + * @pre Create a source handle by calling mv_create_source() + * @pre Create an inference handle by calling mv_hand_landmark_create() + * @pre Prepare an inference by calling mv_hand_landmark_configure() + * @pre Prepare an inference by calling mv_hand_landmark_prepare() + * @pre Prepare an inference by calling mv_hand_landmark_inference() + * @pre Get result count by calling mv_hand_landmark_get_result_count() + */ +int mv_hand_landmark_get_position(mv_hand_landmark_h handle, unsigned int index, unsigned int *pos_x, + unsigned int *pos_y); +/** + * @} + */ +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __TIZEN_MEDIAVISION_MV_HAND_LANDMARK_H__ */ diff --git a/include/mv_hand_landmark_internal.h b/include/mv_hand_landmark_internal.h new file mode 100644 index 00000000..e65b5a6f --- /dev/null +++ b/include/mv_hand_landmark_internal.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2024 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_HAND_LANDMARK_INTERNAL_H__ +#define __TIZEN_MEDIAVISION_HAND_LANDMARK_INTERNAL_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @file mv_hand_landmark_internal.h + * @internal + * @brief This file contains the Inference based Media Vision API. + */ + +/** + * @addtogroup CAPI_MEDIA_VISION_INFERENCE_MODULE + * @{ + */ + +/** + * @internal + * @brief Sets user-given model information. + * @details Use this function to change the model information instead of default one after calling @ref mv_hand_landmark_create(). + * + * @since_tizen 9.0 + * + * @param[in] handle The handle to the hand landmark object. + * @param[in] model_file Model file name. + * @param[in] meta_file Model meta file name. + * @param[in] label_file Label file name. + * @param[in] model_name Model name. + * + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIA_VISION_ERROR_NONE Successful + * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create a hand landmark handle by calling @ref mv_hand_landmark_create() + */ +int mv_hand_landmark_set_model(mv_hand_landmark_h handle, const char *model_file, const char *meta_file, + const char *label_file, const char *model_name); + +/** + * @internal + * @brief Sets user-given inference engine and device types for inference. + * @details Use this function to change the inference engine and device types for inference instead of default ones after calling @ref mv_hand_landmark_create(). + * + * @since_tizen 9.0 + * + * @param[in] handle The handle to the hand landmark object. + * @param[in] engine_type A string of inference engine type. + * @param[in] device_type A string of device type. + * + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIA_VISION_ERROR_NONE Successful + * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create a hand landmark handle by calling @ref mv_hand_landmark_create() + */ +int mv_hand_landmark_set_engine(mv_hand_landmark_h handle, const char *engine_type, const char *device_type); + +/** + * @internal + * @brief Gets a number of inference engines available for hand landmark task API. + * @details Use this function to get how many inference engines are supported for hand landmark after calling @ref mv_hand_landmark_create(). + * + * @since_tizen 9.0 + * + * @param[in] handle The handle to the hand landmark object. + * @param[out] engine_count A number of inference engines available for hand landmark API. + * + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIA_VISION_ERROR_NONE Successful + * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create a hand landmark handle by calling @ref mv_hand_landmark_create() + */ +int mv_hand_landmark_get_engine_count(mv_hand_landmark_h handle, unsigned int *engine_count); + +/** + * @internal + * @brief Gets engine type to a given inference engine index. + * @details Use this function to get inference engine type with a given engine index after calling @ref mv_hand_landmark_get_engine_count(). + * + * @since_tizen 9.0 + * + * @param[in] handle The handle to the hand landmark object. + * @param[in] engine_index A inference engine index for getting the inference engine type. + * @param[out] engine_type A string to inference engine. + * + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIA_VISION_ERROR_NONE Successful + * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Get a number of inference engines available for hand landmark task API by calling @ref mv_hand_landmark_get_engine_count() + */ +int mv_hand_landmark_get_engine_type(mv_hand_landmark_h handle, const unsigned int engine_index, char **engine_type); + +/** + * @internal + * @brief Gets a number of device types available to a given inference engine. + * @details Use this function to get how many device types are supported for a given inference engine after calling @ref mv_hand_landmark_create(). + * + * @since_tizen 9.0 + * + * @param[in] handle The handle to the hand landmark object. + * @param[in] engine_type A inference engine string. + * @param[out] device_count A number of device types available for a given inference engine. + * + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIA_VISION_ERROR_NONE Successful + * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create a hand landmark handle by calling @ref mv_hand_landmark_create() + */ +int mv_hand_landmark_get_device_count(mv_hand_landmark_h handle, const char *engine_type, unsigned int *device_count); + +/** + * @internal + * @brief Gets device type list available. + * @details Use this function to get what device types are supported for current inference engine type after calling @ref mv_hand_landmark_configure(). + * + * @since_tizen 9.0 + * + * @param[in] handle The handle to the hand landmark object. + * @param[in] engine_type A inference engine string. + * @param[in] device_index A device index for getting the device type. + * @param[out] device_type A string to device type. + * + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIA_VISION_ERROR_NONE Successful + * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create a hand landmark handle by calling @ref mv_hand_landmark_create() + * @pre Configure hand landmark task by calling @ref mv_hand_landmark_configure() + */ +int mv_hand_landmark_get_device_type(mv_hand_landmark_h handle, const char *engine_type, + const unsigned int device_index, char **device_type); +/** + * @} + */ +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __TIZEN_MEDIAVISION_HAND_LANDMARK_INTERNAL_H__ */ diff --git a/include/mv_hand_landmark_type.h b/include/mv_hand_landmark_type.h new file mode 100644 index 00000000..c97105d2 --- /dev/null +++ b/include/mv_hand_landmark_type.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 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_MV_HAND_LANDMARK_TYPE_H__ +#define __TIZEN_MEDIAVISION_MV_HAND_LANDMARK_TYPE_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @file mv_hand_landmark_type.h + * @brief This file contains the hand landmark handle for Mediavision. + */ + +/** + * @addtogroup CAPI_MEDIA_VISION_HAND_LANDMARK_MODULE + * @{ + */ + +/** + * @brief The hand landmark object handle. + * + * @since_tizen 9.0 + */ +typedef void *mv_hand_landmark_h; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __TIZEN_MEDIAVISION_MV_HAND_LANDMARK_TYPE_H__ */ diff --git a/mv_machine_learning/common/meta/include/types.h b/mv_machine_learning/common/meta/include/types.h index 75699838..0e356c82 100644 --- a/mv_machine_learning/common/meta/include/types.h +++ b/mv_machine_learning/common/meta/include/types.h @@ -39,7 +39,7 @@ enum class BoxCoordinateType { RATIO, PIXEL }; enum class BoxType { LEFTTOP, CENTER }; -enum class LandmarkType { SINGLE_2D, MULTI_2D }; +enum class LandmarkType { SINGLE_2D, SINGLE_3D, MULTI_2D }; enum class BoxNmsMode { NONE = -1, STANDARD }; diff --git a/mv_machine_learning/common/meta/src/PostprocessParser.cpp b/mv_machine_learning/common/meta/src/PostprocessParser.cpp index 984acf53..b7541ec3 100644 --- a/mv_machine_learning/common/meta/src/PostprocessParser.cpp +++ b/mv_machine_learning/common/meta/src/PostprocessParser.cpp @@ -42,6 +42,7 @@ std::map gSupportedBoxDecodingTypes = { { "BYPASS" std::map gSupportedScoreTypes = { { "NORMAL", ScoreType::NORMAL }, { "SIGMOID", ScoreType::SIGMOID } }; std::map gSupportedLandmarkTypes = { { "2D_SINGLE", LandmarkType::SINGLE_2D }, + { "3D_SINGLE", LandmarkType::SINGLE_3D }, { "2D_MULTI", LandmarkType::MULTI_2D } }; std::map gSupportedLandmarkCoordinateTypes = { { "RATIO", LandmarkCoordinateType::RATIO }, diff --git a/mv_machine_learning/landmark_detection/CMakeLists.txt b/mv_machine_learning/landmark_detection/CMakeLists.txt index 43cf88e7..eda67fcf 100644 --- a/mv_machine_learning/landmark_detection/CMakeLists.txt +++ b/mv_machine_learning/landmark_detection/CMakeLists.txt @@ -23,4 +23,7 @@ install( PATTERN "mv_pose_landmark_internal.h" PATTERN "mv_pose_landmark.h" PATTERN "mv_pose_landmark_type.h" + PATTERN "mv_hand_landmark_internal.h" + PATTERN "mv_hand_landmark.h" + PATTERN "mv_hand_landmark_type.h" ) diff --git a/mv_machine_learning/landmark_detection/include/HandLander.h b/mv_machine_learning/landmark_detection/include/HandLander.h new file mode 100644 index 00000000..b698afe4 --- /dev/null +++ b/mv_machine_learning/landmark_detection/include/HandLander.h @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2024 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 __HLD_HAND_LANDER_H__ +#define __HLD_HAND_LANDER_H__ + +#include +#include + +#include "LandmarkDetection.h" +#include + +namespace mediavision +{ +namespace machine_learning +{ +template class HandLander : public LandmarkDetection +{ + using LandmarkDetection::_config; + using LandmarkDetection::_preprocess; + using LandmarkDetection::_inference; + +private: + LandmarkDetectionResult _result; + +public: + HandLander(LandmarkDetectionTaskType task_type, std::shared_ptr config); + ~HandLander(); + + LandmarkDetectionResult &result() override; +}; + +} // machine_learning +} // mediavision + +#endif \ No newline at end of file diff --git a/mv_machine_learning/landmark_detection/include/HandLandmarkAdapter.h b/mv_machine_learning/landmark_detection/include/HandLandmarkAdapter.h new file mode 100644 index 00000000..fa6907d7 --- /dev/null +++ b/mv_machine_learning/landmark_detection/include/HandLandmarkAdapter.h @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2024 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 __HAND_LANDMARK_ADAPTER_H__ +#define __HAND_LANDMARK_ADAPTER_H__ + +#include + +#include "EngineConfig.h" +#include "ILandmarkDetection.h" +#include "ITask.h" +#include "MvMlConfig.h" + +namespace mediavision +{ +namespace machine_learning +{ +class HandLandmarkAdapter : public mediavision::common::ITask +{ +private: + std::unique_ptr _landmark_detection; + std::shared_ptr _config; + const std::string _config_file_name = "hand_landmark.json"; + + void create(const std::string &model_name); + template void create(LandmarkDetectionTaskType task_type); + LandmarkDetectionTaskType convertToTaskType(std::string model_name); + +public: + HandLandmarkAdapter(); + ~HandLandmarkAdapter(); + + void setModelInfo(const std::string &model_file, const std::string &meta_file, const std::string &label_file, + const std::string &model_name) override; + void setEngineInfo(const std::string &engine_type, const std::string &device_type) override; + void configure() override; + unsigned int getNumberOfEngines() override; + const std::string &getEngineType(unsigned int engine_index) override; + unsigned int getNumberOfDevices(const std::string &engine_type) override; + const std::string &getDeviceType(const std::string &engine_type, unsigned int device_index) override; + void prepare() override; + void perform(InputBaseType &input) override; + void performAsync(InputBaseType &input) override; + OutputBaseType &getOutput() override; + OutputBaseType &getOutputCache() override; +}; + +} // machine_learning +} // mediavision + +#endif \ No newline at end of file diff --git a/mv_machine_learning/landmark_detection/include/landmark_detection_type.h b/mv_machine_learning/landmark_detection/include/landmark_detection_type.h index 23d3bf38..19685342 100644 --- a/mv_machine_learning/landmark_detection/include/landmark_detection_type.h +++ b/mv_machine_learning/landmark_detection/include/landmark_detection_type.h @@ -40,7 +40,13 @@ struct LandmarkDetectionResult : public OutputBaseType { std::vector labels; }; -enum class LandmarkDetectionTaskType { LANDMARK_DETECTION_TASK_NONE = 0, FLD_TWEAK_CNN, FLD_U2NET, PLD_CPM }; +enum class LandmarkDetectionTaskType { + LANDMARK_DETECTION_TASK_NONE = 0, + FLD_TWEAK_CNN, + FLD_U2NET, + PLD_CPM, + HAND_LANDER +}; } } diff --git a/mv_machine_learning/landmark_detection/meta/hand_landmark.json b/mv_machine_learning/landmark_detection/meta/hand_landmark.json new file mode 100644 index 00000000..4028e1b9 --- /dev/null +++ b/mv_machine_learning/landmark_detection/meta/hand_landmark.json @@ -0,0 +1,40 @@ +{ + "attributes": + [ + { + "name" : "MODEL_DEFAULT_PATH", + "type" : "string", + "value" : "/opt/usr/globalapps/mediavision.landmark.detection/models/tflite/" + }, + { + "name" : "MODEL_FILE_NAME", + "type" : "string", + "value" : "hld_hand_lander_256_int8_quant.tflite" + }, + { + "name" : "DEFAULT_MODEL_NAME", + "type" : "string", + "value" : "HAND_LANDER" + }, + { + "name" : "MODEL_META_FILE_NAME", + "type" : "string", + "value" : "hld_hand_lander_256_int8_quant.json" + }, + { + "name" : "MODEL_LABEL_FILE_NAME", + "type" : "string", + "value" : "" + }, + { + "name" : "BACKEND_TYPE", + "type" : "integer", + "value" : 1 + }, + { + "name" : "TARGET_DEVICE_TYPE", + "type" : "integer", + "value" : 1 + } + ] +} diff --git a/mv_machine_learning/landmark_detection/src/HandLander.cpp b/mv_machine_learning/landmark_detection/src/HandLander.cpp new file mode 100644 index 00000000..422c0b9a --- /dev/null +++ b/mv_machine_learning/landmark_detection/src/HandLander.cpp @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2024 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 +#include +#include + +#include "HandLander.h" +#include "MvMlException.h" +#include "Postprocess.h" + +using namespace std; +using namespace mediavision::inference; +using namespace mediavision::machine_learning::exception; + +namespace mediavision +{ +namespace machine_learning +{ +template +HandLander::HandLander(LandmarkDetectionTaskType task_type, std::shared_ptr config) + : LandmarkDetection(task_type, config), _result() +{} + +template HandLander::~HandLander() +{} + +template LandmarkDetectionResult &HandLander::result() +{ + // Clear _result object because result() function can be called every time user wants + // so make sure to clear existing result data before getting the data again. + _result = LandmarkDetectionResult(); + + vector names; + + LandmarkDetection::getOutputNames(names); + + vector tensor1, tensor2; + + LandmarkDetection::getOutputTensor(names[0], tensor1); + LandmarkDetection::getOutputTensor(names[1], tensor2); + + auto ori_src_width = static_cast(_preprocess.getImageWidth()[0]); + auto ori_src_height = static_cast(_preprocess.getImageHeight()[0]); + auto input_tensor_width = static_cast(_inference->getInputWidth()); + auto input_tensor_height = static_cast(_inference->getInputHeight()); + + // Calculate the ratio[A] between the original image size and the input tensor size. + auto width_ratio = ori_src_width / input_tensor_width; + auto height_ratio = ori_src_height / input_tensor_height; + + _result.number_of_landmarks = static_cast(tensor1.size()) / 3; + + for (size_t idx = 0; idx < tensor1.size(); idx += 3) { + _result.x_pos.push_back(tensor1[idx] * width_ratio); + _result.y_pos.push_back(tensor1[idx + 1] * height_ratio); + } + + _result.scores.push_back(tensor2[0]); + + for (auto &name : names) + LOGD("%s", name.c_str()); + + return _result; +} + +template class HandLander; +template class HandLander; + +} +} \ No newline at end of file diff --git a/mv_machine_learning/landmark_detection/src/HandLandmarkAdapter.cpp b/mv_machine_learning/landmark_detection/src/HandLandmarkAdapter.cpp new file mode 100644 index 00000000..ee33fcd2 --- /dev/null +++ b/mv_machine_learning/landmark_detection/src/HandLandmarkAdapter.cpp @@ -0,0 +1,160 @@ +/** + * Copyright (c) 2024 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 "HandLandmarkAdapter.h" +#include "HandLander.h" +#include "MvMlException.h" +#include "mv_landmark_detection_config.h" + +using namespace std; +using namespace MediaVision::Common; +using namespace mediavision::machine_learning; +using namespace mediavision::machine_learning::exception; + +namespace mediavision +{ +namespace machine_learning +{ +HandLandmarkAdapter::HandLandmarkAdapter() +{ + _config = make_shared(); + _config->parseConfigFile(_config_file_name); + + create(_config->getDefaultModelName()); +} + +HandLandmarkAdapter::~HandLandmarkAdapter() +{ + _landmark_detection->preDestroy(); +} + +template void HandLandmarkAdapter::create(LandmarkDetectionTaskType task_type) +{ + switch (task_type) { + case LandmarkDetectionTaskType::HAND_LANDER: + _landmark_detection = make_unique >(task_type, _config); + break; + default: + throw InvalidOperation("Invalid landmark detection task type."); + } +} + +void HandLandmarkAdapter::create(const string &model_name) +{ + auto task_type = convertToTaskType(model_name.empty() ? _config->getDefaultModelName() : model_name); + + _config->loadMetaFile(make_unique(static_cast(task_type))); + mv_inference_data_type_e dataType = _config->getInputMetaMap().begin()->second->dataType; + + switch (dataType) { + case MV_INFERENCE_DATA_UINT8: + create(task_type); + break; + case MV_INFERENCE_DATA_FLOAT32: + create(task_type); + break; + default: + throw InvalidOperation("Invalid landmark detection data type."); + } +} + +LandmarkDetectionTaskType HandLandmarkAdapter::convertToTaskType(string 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 == "HAND_LANDER") + return LandmarkDetectionTaskType::HAND_LANDER; + // TODO. + + throw InvalidParameter("Invalid hand detection model name."); +} + +void HandLandmarkAdapter::setModelInfo(const string &model_file, const string &meta_file, const string &label_file, + const string &model_name) +{ + try { + _config->setUserModel(model_file, meta_file, label_file); + create(model_name); + } catch (const BaseException &e) { + LOGW("A given model name is invalid so default task type will be used."); + } + + if (model_file.empty() && meta_file.empty()) { + LOGW("Given model info is invalid so default model info will be used instead."); + return; + } +} + +void HandLandmarkAdapter::setEngineInfo(const string &engine_type, const string &device_type) +{ + _landmark_detection->setEngineInfo(string(engine_type), string(device_type)); +} + +void HandLandmarkAdapter::configure() +{ + _landmark_detection->configure(); +} + +unsigned int HandLandmarkAdapter::getNumberOfEngines() +{ + return _landmark_detection->getNumberOfEngines(); +} + +const string &HandLandmarkAdapter::getEngineType(unsigned int engine_index) +{ + return _landmark_detection->getEngineType(engine_index); +} + +unsigned int HandLandmarkAdapter::getNumberOfDevices(const string &engine_type) +{ + return _landmark_detection->getNumberOfDevices(engine_type); +} + +const string &HandLandmarkAdapter::getDeviceType(const string &engine_type, unsigned int device_index) +{ + return _landmark_detection->getDeviceType(engine_type, device_index); +} + +void HandLandmarkAdapter::prepare() +{ + _landmark_detection->prepare(); +} + +void HandLandmarkAdapter::perform(InputBaseType &input) +{ + _landmark_detection->perform(input.inference_src); +} + +void HandLandmarkAdapter::performAsync(InputBaseType &input) +{ + _landmark_detection->performAsync(static_cast(input)); +} + +OutputBaseType &HandLandmarkAdapter::getOutput() +{ + return _landmark_detection->getOutput(); +} + +OutputBaseType &HandLandmarkAdapter::getOutputCache() +{ + return _landmark_detection->getOutputCache(); +} + +} +} \ No newline at end of file diff --git a/mv_machine_learning/landmark_detection/src/mv_hand_landmark.cpp b/mv_machine_learning/landmark_detection/src/mv_hand_landmark.cpp new file mode 100644 index 00000000..93467261 --- /dev/null +++ b/mv_machine_learning/landmark_detection/src/mv_hand_landmark.cpp @@ -0,0 +1,352 @@ +/** + * Copyright (c) 2024 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_hand_landmark.h" +#include "Context.h" +#include "HandLandmarkAdapter.h" +#include "ITask.h" +#include "MvMlException.h" +#include "landmark_detection_type.h" +#include "mv_feature_key.h" +#include "mv_hand_landmark_internal.h" +#include "mv_private.h" +#include "native_capi.h" + +#include +#include +#include +#include +#include + +#define TASK_NAME "hand_landmark" + +using namespace std; +using namespace mediavision::common; +using namespace mediavision::machine_learning; +using namespace MediaVision::Common; +using namespace mediavision::machine_learning::exception; + +static const char *feature_keys[] = { "http://tizen.org/feature/vision.inference", + "http://tizen.org/feature/vision.inference.face" }; +static const size_t num_keys = sizeof(feature_keys) / sizeof(char *); + +int mv_hand_landmark_create(mv_hand_landmark_h *handle) +{ + MEDIA_VISION_SUPPORT_CHECK(mv_check_feature_key(feature_keys, num_keys, true)); + MEDIA_VISION_NULL_ARG_CHECK(handle); + + MEDIA_VISION_FUNCTION_ENTER(); + + mv_hand_landmark_h ctx = nullptr; + + try { + ctx = machine_learning_native_create(); + machine_learning_native_add(ctx, TASK_NAME, new HandLandmarkAdapter()); + } catch (const BaseException &e) { + LOGE("%s", e.what()); + return e.getError(); + } catch (const std::exception &e) { + LOGE("%s", e.what()); + return MEDIA_VISION_ERROR_INTERNAL; + } + + *handle = ctx; + MEDIA_VISION_FUNCTION_LEAVE(); + + return MEDIA_VISION_ERROR_NONE; +} + +int mv_hand_landmark_destroy(mv_hand_landmark_h handle) +{ + MEDIA_VISION_SUPPORT_CHECK(mv_check_feature_key(feature_keys, num_keys, true)); + MEDIA_VISION_INSTANCE_CHECK(handle); + + MEDIA_VISION_FUNCTION_ENTER(); + + machine_learning_native_destroy(handle); + + MEDIA_VISION_FUNCTION_LEAVE(); + + return MEDIA_VISION_ERROR_NONE; +} + +int mv_hand_landmark_set_model(mv_hand_landmark_h handle, const char *model_file, const char *meta_file, + const char *label_file, const char *model_name) +{ + MEDIA_VISION_SUPPORT_CHECK(mv_check_feature_key(feature_keys, num_keys, true)); + + MEDIA_VISION_INSTANCE_CHECK(handle); + MEDIA_VISION_NULL_ARG_CHECK(model_file); + MEDIA_VISION_NULL_ARG_CHECK(meta_file); + MEDIA_VISION_NULL_ARG_CHECK(label_file); + + MEDIA_VISION_FUNCTION_ENTER(); + + try { + machine_learning_native_set_model(handle, TASK_NAME, model_file, meta_file, label_file, model_name); + } catch (const BaseException &e) { + LOGE("%s", e.what()); + return e.getError(); + } + + MEDIA_VISION_FUNCTION_LEAVE(); + + return MEDIA_VISION_ERROR_NONE; +} + +int mv_hand_landmark_set_engine(mv_hand_landmark_h handle, const char *backend_type, const char *device_type) +{ + MEDIA_VISION_SUPPORT_CHECK(mv_check_feature_key(feature_keys, num_keys, true)); + + MEDIA_VISION_INSTANCE_CHECK(handle); + MEDIA_VISION_NULL_ARG_CHECK(backend_type); + MEDIA_VISION_NULL_ARG_CHECK(device_type); + + MEDIA_VISION_FUNCTION_ENTER(); + + try { + machine_learning_native_set_engine(handle, TASK_NAME, backend_type, device_type); + } catch (const BaseException &e) { + LOGE("%s", e.what()); + return e.getError(); + } + + MEDIA_VISION_FUNCTION_LEAVE(); + + return MEDIA_VISION_ERROR_NONE; +} + +int mv_hand_landmark_get_engine_count(mv_hand_landmark_h handle, unsigned int *engine_count) +{ + MEDIA_VISION_SUPPORT_CHECK(mv_check_feature_key(feature_keys, num_keys, true)); + + MEDIA_VISION_INSTANCE_CHECK(handle); + MEDIA_VISION_NULL_ARG_CHECK(engine_count); + + MEDIA_VISION_FUNCTION_ENTER(); + + try { + machine_learning_native_get_engine_count(handle, TASK_NAME, engine_count); + } catch (const BaseException &e) { + LOGE("%s", e.what()); + return e.getError(); + } + + MEDIA_VISION_FUNCTION_LEAVE(); + + return MEDIA_VISION_ERROR_NONE; +} + +int mv_hand_landmark_get_engine_type(mv_hand_landmark_h handle, const unsigned int engine_index, char **engine_type) +{ + MEDIA_VISION_SUPPORT_CHECK(mv_check_feature_key(feature_keys, num_keys, true)); + + MEDIA_VISION_INSTANCE_CHECK(handle); + MEDIA_VISION_NULL_ARG_CHECK(engine_type); + + MEDIA_VISION_FUNCTION_ENTER(); + + try { + machine_learning_native_get_engine_type(handle, TASK_NAME, engine_index, engine_type); + } catch (const BaseException &e) { + LOGE("%s", e.what()); + return e.getError(); + } + + MEDIA_VISION_FUNCTION_LEAVE(); + + return MEDIA_VISION_ERROR_NONE; +} + +int mv_hand_landmark_get_device_count(mv_hand_landmark_h handle, const char *engine_type, unsigned int *device_count) +{ + MEDIA_VISION_SUPPORT_CHECK(mv_check_feature_key(feature_keys, num_keys, true)); + + MEDIA_VISION_INSTANCE_CHECK(handle); + MEDIA_VISION_NULL_ARG_CHECK(device_count); + + MEDIA_VISION_FUNCTION_ENTER(); + + try { + machine_learning_native_get_device_count(handle, TASK_NAME, engine_type, device_count); + } catch (const BaseException &e) { + LOGE("%s", e.what()); + return e.getError(); + } + + MEDIA_VISION_FUNCTION_LEAVE(); + + return MEDIA_VISION_ERROR_NONE; +} + +int mv_hand_landmark_get_device_type(mv_hand_landmark_h handle, const char *engine_type, + const unsigned int device_index, char **device_type) +{ + MEDIA_VISION_SUPPORT_CHECK(mv_check_feature_key(feature_keys, num_keys, true)); + + MEDIA_VISION_INSTANCE_CHECK(handle); + MEDIA_VISION_NULL_ARG_CHECK(engine_type); + MEDIA_VISION_NULL_ARG_CHECK(device_type); + + MEDIA_VISION_FUNCTION_ENTER(); + + try { + machine_learning_native_get_device_type(handle, TASK_NAME, engine_type, device_index, device_type); + } catch (const BaseException &e) { + LOGE("%s", e.what()); + return e.getError(); + } + + MEDIA_VISION_FUNCTION_LEAVE(); + + return MEDIA_VISION_ERROR_NONE; +} + +int mv_hand_landmark_configure(mv_hand_landmark_h handle) +{ + MEDIA_VISION_SUPPORT_CHECK(mv_check_feature_key(feature_keys, num_keys, true)); + MEDIA_VISION_INSTANCE_CHECK(handle); + + MEDIA_VISION_FUNCTION_ENTER(); + + try { + machine_learning_native_configure(handle, TASK_NAME); + } catch (const BaseException &e) { + LOGE("%s", e.what()); + return e.getError(); + } + + MEDIA_VISION_FUNCTION_LEAVE(); + + return MEDIA_VISION_ERROR_NONE; +} + +int mv_hand_landmark_prepare(mv_hand_landmark_h handle) +{ + MEDIA_VISION_SUPPORT_CHECK(mv_check_feature_key(feature_keys, num_keys, true)); + MEDIA_VISION_INSTANCE_CHECK(handle); + + MEDIA_VISION_FUNCTION_ENTER(); + + try { + machine_learning_native_prepare(handle, TASK_NAME); + } catch (const BaseException &e) { + LOGE("%s", e.what()); + return e.getError(); + } + + MEDIA_VISION_FUNCTION_LEAVE(); + + return MEDIA_VISION_ERROR_NONE; +} + +int mv_hand_landmark_inference(mv_hand_landmark_h handle, mv_source_h source) +{ + MEDIA_VISION_SUPPORT_CHECK(mv_check_feature_key(feature_keys, num_keys, true)); + MEDIA_VISION_INSTANCE_CHECK(handle); + MEDIA_VISION_INSTANCE_CHECK(source); + + MEDIA_VISION_FUNCTION_ENTER(); + + try { + LandmarkDetectionInput input(source); + + machine_learning_native_inference(handle, TASK_NAME, input); + } catch (const BaseException &e) { + LOGE("%s", e.what()); + return e.getError(); + } + + MEDIA_VISION_FUNCTION_LEAVE(); + + return MEDIA_VISION_ERROR_NONE; +} + +int mv_hand_landmark_inference_async(mv_hand_landmark_h handle, mv_source_h source) +{ + MEDIA_VISION_SUPPORT_CHECK(mv_check_feature_key(feature_keys, num_keys, true)); + MEDIA_VISION_INSTANCE_CHECK(handle); + MEDIA_VISION_INSTANCE_CHECK(source); + + MEDIA_VISION_FUNCTION_ENTER(); + + try { + LandmarkDetectionInput input(source); + + machine_learning_native_inference_async(handle, TASK_NAME, input); + } catch (const BaseException &e) { + LOGE("%s", e.what()); + return e.getError(); + } + + MEDIA_VISION_FUNCTION_LEAVE(); + + return MEDIA_VISION_ERROR_NONE; +} + +int mv_hand_landmark_get_result_count(mv_hand_landmark_h handle, unsigned long *frame_number, unsigned int *result_cnt) +{ + MEDIA_VISION_SUPPORT_CHECK(mv_check_feature_key(feature_keys, num_keys, true)); + MEDIA_VISION_INSTANCE_CHECK(handle); + MEDIA_VISION_INSTANCE_CHECK(frame_number); + MEDIA_VISION_INSTANCE_CHECK(result_cnt); + + MEDIA_VISION_FUNCTION_ENTER(); + + try { + auto &result = static_cast(machine_learning_native_get_result(handle, TASK_NAME)); + + *frame_number = result.frame_number; + *result_cnt = result.number_of_landmarks; + } catch (const BaseException &e) { + LOGE("%s", e.what()); + return e.getError(); + } + + MEDIA_VISION_FUNCTION_LEAVE(); + + return MEDIA_VISION_ERROR_NONE; +} + +int mv_hand_landmark_get_position(mv_hand_landmark_h handle, unsigned int index, unsigned int *pos_x, + unsigned int *pos_y) +{ + MEDIA_VISION_SUPPORT_CHECK(mv_check_feature_key(feature_keys, num_keys, true)); + MEDIA_VISION_INSTANCE_CHECK(handle); + MEDIA_VISION_INSTANCE_CHECK(pos_x); + MEDIA_VISION_INSTANCE_CHECK(pos_y); + + MEDIA_VISION_FUNCTION_ENTER(); + + try { + auto &result = + static_cast(machine_learning_native_get_result_cache(handle, TASK_NAME)); + if (index >= result.number_of_landmarks) { + LOGE("Invalid index(index = %u, result count = %u).", index, result.number_of_landmarks); + return MEDIA_VISION_ERROR_INVALID_PARAMETER; + } + + *pos_x = result.x_pos[index]; + *pos_y = result.y_pos[index]; + } catch (const BaseException &e) { + LOGE("%s", e.what()); + return e.getError(); + } + + MEDIA_VISION_FUNCTION_LEAVE(); + + return MEDIA_VISION_ERROR_NONE; +} \ No newline at end of file diff --git a/packaging/capi-media-vision.spec b/packaging/capi-media-vision.spec index f68dc5c7..c309a647 100644 --- a/packaging/capi-media-vision.spec +++ b/packaging/capi-media-vision.spec @@ -401,6 +401,7 @@ find . -name '*.gcno' -not -path "./test/*" -not -path "./mv_machine_learning/*" %if "%{enable_ml_landmark_detection}" == "1" %{_datadir}/%{name}/facial_landmark.json %{_datadir}/%{name}/pose_landmark.json +%{_datadir}/%{name}/hand_landmark.json %{_libdir}/libmv_landmark_detection.so %endif %if "%{enable_ml_image_segmentation}" == "1" @@ -450,6 +451,9 @@ find . -name '*.gcno' -not -path "./test/*" -not -path "./mv_machine_learning/*" %{_includedir}/media/mv_pose_landmark_internal.h %{_includedir}/media/mv_pose_landmark.h %{_includedir}/media/mv_pose_landmark_type.h +%{_includedir}/media/mv_hand_landmark_internal.h +%{_includedir}/media/mv_hand_landmark.h +%{_includedir}/media/mv_hand_landmark_type.h %{_libdir}/pkgconfig/*landmark-detection.pc %endif %if "%{enable_ml_image_segmentation}" == "1"