cebe04148d39cbe2ba0f79a8c9caab1ad65eec24
[platform/core/api/mediavision.git] / mv_machine_learning / face_recognition / src / facenet.cpp
1 /**
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <string.h>
18 #include <map>
19 #include <memory>
20 #include <algorithm>
21
22 #include "machine_learning_exception.h"
23 #include "facenet.h"
24 #include "face_recognition_type.h"
25
26 using namespace std;
27 using namespace mediavision::inference;
28 using namespace MediaVision::Common;
29 using namespace mediavision::machine_learning::exception;
30
31 namespace mediavision
32 {
33 namespace machine_learning
34 {
35 Facenet::Facenet() : _backendType(), _targetDeviceType()
36 {
37         _inference = make_unique<Inference>();
38         _parser = make_unique<FacenetParser>();
39 }
40
41 static bool IsJsonFile(const string &fileName)
42 {
43         return (!fileName.substr(fileName.find_last_of(".") + 1).compare("json"));
44 }
45
46 void Facenet::parseMetaFile()
47 {
48         _config = make_unique<EngineConfig>(string(MV_CONFIG_PATH) + string(FACE_RECOGNITION_META_FILE_NAME));
49
50         int ret = _config->getIntegerAttribute(string(MV_FACENET_BACKEND_TYPE), &_backendType);
51         if (ret != MEDIA_VISION_ERROR_NONE)
52                 throw InvalidOperation("Fail to get backend engine type.");
53
54         ret = _config->getIntegerAttribute(string(MV_FACENET_TARGET_DEVICE_TYPE), &_targetDeviceType);
55         if (ret != MEDIA_VISION_ERROR_NONE)
56                 throw InvalidOperation("Fail to get target device type.");
57
58         ret = _config->getStringAttribute(MV_FACENET_MODEL_FILE_PATH, &_modelFilePath);
59         if (ret != MEDIA_VISION_ERROR_NONE)
60                 throw InvalidOperation("Fail to get model file path.");
61
62         ret = _config->getStringAttribute(MV_FACENET_MODEL_META_FILE_PATH, &_modelMetaFilePath);
63         if (ret != MEDIA_VISION_ERROR_NONE)
64                 throw InvalidOperation("Fail to get model meta file path.");
65
66         ret = _config->getStringAttribute(MV_FACENET_OUTPUT_TENSOR_NAME, &_facenetOutputTensorName);
67         if (ret != MEDIA_VISION_ERROR_NONE)
68                 throw InvalidOperation("Fail to get facenet output tensor name.");
69
70         if (_modelMetaFilePath.empty())
71                 throw InvalidOperation("Model meta file doesn't exist.");
72
73         if (!IsJsonFile(_modelMetaFilePath))
74                 throw InvalidOperation("Model meta file should be json.");
75
76         _parser->load(_modelMetaFilePath);
77 }
78
79 void Facenet::configure()
80 {
81         int ret = _inference->Bind(_backendType, _targetDeviceType);
82         if (ret != MEDIA_VISION_ERROR_NONE)
83                 throw InvalidOperation("Fail to bind a backend engine.");
84 }
85
86 void Facenet::prepare()
87 {
88         int ret = _inference->configureInputMetaInfo(_parser->getInputMetaMap());
89         if (ret != MEDIA_VISION_ERROR_NONE)
90                 throw InvalidOperation("Fail to configure input tensor info from meta file.");
91
92         ret = _inference->configureOutputMetaInfo(_parser->getOutputMetaMap());
93         if (ret != MEDIA_VISION_ERROR_NONE)
94                 throw InvalidOperation("Fail to configure output tensor info from meta file.");
95
96         _inference->ConfigureModelFiles("", _modelFilePath, "");
97
98         // Request to load model files to a backend engine.
99         ret = _inference->Load();
100         if (ret != MEDIA_VISION_ERROR_NONE)
101                 throw InvalidOperation("Fail to load model files.");
102 }
103
104 void Facenet::preprocess(mv_source_h &mv_src)
105 {
106         LOGI("ENTER");
107
108         TensorBuffer &tensor_buffer_obj = _inference->getInputTensorBuffer();
109         IETensorBuffer &ie_tensor_buffer = tensor_buffer_obj.getIETensorBuffer();
110         vector<mv_source_h> mv_srcs = { mv_src };
111
112         _preprocess.run(mv_srcs, _parser->getInputMetaMap(), ie_tensor_buffer);
113
114         LOGI("LEAVE");
115 }
116
117 void Facenet::inference(mv_source_h source)
118 {
119         LOGI("ENTER");
120
121         int ret = _inference->Run();
122         if (ret != MEDIA_VISION_ERROR_NONE)
123                 throw InvalidOperation("Fail to run inference");
124
125         LOGI("LEAVE");
126 }
127
128 facenet_output_s &Facenet::result()
129 {
130         TensorBuffer &tensor_buffer_obj = _inference->GetOutputTensorBuffer();
131
132         // Make sure to clear _result.outputs vectors because if not clear then other output_vector will be pushed to _result.outputs
133         // and it results in sending wrong output vector to face recognition framework.
134         _result.outputs.clear();
135
136         _outputTensorBuffer = tensor_buffer_obj.getTensorBuffer(_facenetOutputTensorName);
137         if (!_outputTensorBuffer)
138                 throw InvalidOperation("No output tensor.");
139
140         float *buffer = reinterpret_cast<float *>(_outputTensorBuffer->buffer);
141
142         _result.outputs.push_back(vector<float>(buffer, buffer + _outputTensorBuffer->size / sizeof(float)));
143
144         return _result;
145 }
146
147 }
148 }