*/
int singleo_service_get_result_int(singleo_service_h handle, unsigned int idx, const char *key, unsigned int *value);
+/**
+ * @internal
+ * @brief Gets float type of result corresponding to a given index value.
+ *
+ * @since_tizen 9.0
+ *
+ * @param[in] handle The handle to the service.
+ * @param[in] idx Index value to results.
+ * @param[in] key Key string to a certain member of the result.
+ * @param[out] value Pointer to the float variable to be stored.
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #SINGLEO_SERVICE_ERROR_NONE Successful
+ * @retval #SINGLEO_SERVICE_ERROR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SINGLEO_SERVICE_ERROR_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre Create a source handle by calling singleo_service_create()
+ * @pre Perform a requested service by
+ * calling singleo_service_perform(),
+ * singleo_service_perform_with_file(),
+ * singleo_service_perform_with_image_data(),
+ * or singleo_service_perform_with_raw_data()
+ */
+int singleo_service_get_result_float(singleo_service_h handle, unsigned int idx, const char *key, float *value);
+
/**
* @internal
* @brief Gets string type of result corresponding to a given index value.
throw invalid_argument("Input type not support.");
}
+ SINGLEO_LOGD("PrivateInferenceFaceService: invoke");
ImageDataType &data = dynamic_cast<ImageDataType &>(input);
// cv::Mat cvData(cv::Size(data.width, data.height), CV_MAKE_TYPE(CV_8U, data.byte_per_pixel), data.ptr);
cv::Mat cvData_(cv::Size(data.width, data.height), CV_MAKE_TYPE(CV_8U, data.byte_per_pixel), data.ptr);
void OpencvBackend::threadLoop()
{
- SINGLEO_LOGD("OpencvBackend: stream off.");
-
ImageDataType data;
while (!_exit_thread) {
void OpencvBackend::streamOff()
{
+ SINGLEO_LOGD("OpencvBackend: stream off.");
+
_exit_thread = true;
_thread_handle->join();
}
void performAsync() override;
void getResultCnt(unsigned int *cnt) override;
void getResultInt(unsigned int idx, std::string key, unsigned int *value) override;
+ void getResultFloat(unsigned int idx, std::string key, float *value) override;
void registerUserCallback(singleo_user_cb_t user_cb, void *user_data) override;
void unregisterUserCallback() override;
}
}
+void AutoZoom::getResultFloat(unsigned int idx, std::string key, float *value)
+{
+}
+
void AutoZoom::registerUserCallback(singleo_user_cb_t user_cb, void *user_data)
{
_user_cb = user_cb;
virtual void performAsync() = 0;
virtual void getResultCnt(unsigned int *cnt) = 0;
virtual void getResultInt(unsigned int idx, std::string key, unsigned int *value) = 0;
+ virtual void getResultFloat(unsigned int idx, std::string key, float *value) = 0;
virtual void registerUserCallback(singleo_user_cb_t user_cb, void *user_data) = 0;
virtual void unregisterUserCallback() = 0;
};
{
// TODO
-enum class ServiceResultType { NONE, AUTO_ZOOM };
+enum class ServiceResultType { NONE, AUTO_ZOOM, SMART_POINTER };
struct ServiceBaseResultType {
ServiceResultType _result_type { ServiceResultType::NONE };
return SINGLEO_ERROR_NONE;
}
+int singleo_service_get_result_float(singleo_service_h handle, unsigned int idx, const char *key, float *value)
+{
+ try {
+ auto context = static_cast<Context *>(handle);
+ context->_service_handle->getResultFloat(idx, key, value);
+ } catch (const BaseException &e) {
+ return e.getError();
+ }
+
+ return SINGLEO_ERROR_NONE;
+}
+
int singleo_service_register_user_callback(singleo_service_h handle, singleo_user_cb_t user_cb, void *user_data)
{
try {
#include "SingleoInputManager.h"
#include "GazeEstimator.h"
#include "InputCamera.h"
+#include "AsyncManager.h"
+#include "SmartPointerDataType.h"
namespace singleo
{
std::unique_ptr<singleo::input::IInputService> _data_feeder;
SingleoInputManager _input_image_data;
PoseVector _head_pose;
+ PointerPosition _pointerPosition;
+ std::map<std::string, PoseAngle> _result_keys = { { "PITCH", PoseAngle::PITCH },
+ { "YAW", PoseAngle::YAW },
+ { "ROLL", PoseAngle::ROLL } };
+ bool _async_mode;
+ std::unique_ptr<AsyncManager<ImageDataType, PointerPosition> > _async_manager;
singleo_user_cb_t _user_cb {};
- static void internalDataFeederCb(BaseDataType &data, void *user_data);
void *_user_data {};
+ static void internalDataFeederCb(BaseDataType &data, void *user_data);
+ void updateResult(PoseVector &result);
+
public:
explicit SmartPointer(input::InputConfigBase &config);
virtual ~SmartPointer();
void performAsync() override;
void getResultCnt(unsigned int *cnt) override;
void getResultInt(unsigned int idx, std::string key, unsigned int *value) override;
+ void getResultFloat(unsigned int idx, std::string key, float *value) override;
void registerUserCallback(singleo_user_cb_t user_cb, void *user_data) override;
void unregisterUserCallback() override;
+
+ std::unique_ptr<AsyncManager<ImageDataType, PointerPosition> > &getAsyncManager()
+ {
+ return _async_manager;
+ }
+
+ std::unique_ptr<GazeEstimator> &getGazeEstimator()
+ {
+ return _gaze_estimator;
+ }
};
} // smartpointer
} // services
--- /dev/null
+/**
+ * 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 __SMART_POINTER_DATA_TYPES_H__
+#define __SMART_POINTER_DATA_TYPES_H__
+
+#include <vector>
+#include "SingleoCommonTypes.h"
+#include "ServiceDataType.h"
+#include "PoseVector.h"
+
+namespace singleo
+{
+namespace services
+{
+namespace smartpointer
+{
+enum class PoseAngle { PITCH, YAW, ROLL };
+
+struct PointerPosition : public ServiceBaseResultType {
+ PointerPosition() : ServiceBaseResultType(ServiceResultType::SMART_POINTER)
+ {}
+ unsigned int frame_number {};
+ PoseVector pose;
+};
+
+}
+}
+}
+
+#endif
\ No newline at end of file
PoseVector &GazeEstimator::estimateHeadpose(BaseDataType &input)
{
- _face_estimator->invoke(input);
-
- auto &result = _face_estimator->result();
-
+ _face_estimator->invoke(input);
+ auto &result = _face_estimator->result();
+
if (result._rects.empty())
return _headPose;
-
- _headPose = _head_pose_estimator->estimate(result._landmarks[0]);
- vector<Point2f> poseAxes = _head_pose_estimator->getPoseAxes();
- ImageDataType &data = dynamic_cast<ImageDataType &>(input);
- cv::Mat _dump(cv::Size(data.width, data.height), CV_MAKETYPE(CV_8U, data.byte_per_pixel), data.ptr);
- cv::line(_dump, cv::Point(poseAxes[0].x, poseAxes[0].y), cv::Point(poseAxes[1].x, poseAxes[1].y), cv::Scalar(0, 0, 255), 2); // x - red
- cv::line(_dump, cv::Point(poseAxes[0].x, poseAxes[0].y), cv::Point(poseAxes[2].x, poseAxes[2].y), cv::Scalar(0, 255, 0), 2); // y - green
- cv::line(_dump, cv::Point(poseAxes[0].x, poseAxes[0].y), cv::Point(poseAxes[3].x, poseAxes[3].y), cv::Scalar(255, 0, 0), 2); // z - blue
+ _headPose = _head_pose_estimator->estimate(result._landmarks[0]);
+ // vector<Point2f> poseAxes = _head_pose_estimator->getPoseAxes();
+
+ // ImageDataType &data = dynamic_cast<ImageDataType &>(input);
+ // cv::Mat _dump(cv::Size(data.width, data.height), CV_MAKETYPE(CV_8U, data.byte_per_pixel), data.ptr);
+ // cv::line(_dump, cv::Point(poseAxes[0].x, poseAxes[0].y), cv::Point(poseAxes[1].x, poseAxes[1].y), cv::Scalar(0, 0, 255), 2); // x - red
+ // cv::line(_dump, cv::Point(poseAxes[0].x, poseAxes[0].y), cv::Point(poseAxes[2].x, poseAxes[2].y), cv::Scalar(0, 255, 0), 2); // y - green
+ // cv::line(_dump, cv::Point(poseAxes[0].x, poseAxes[0].y), cv::Point(poseAxes[3].x, poseAxes[3].y), cv::Scalar(255, 0, 0), 2); // z - blue
- cv::imwrite("dump_headpose.jpg", _dump);
+ // cv::imwrite("dump_headpose.jpg", _dump);
return _headPose;
}
SINGLEO_LOGD("Camera input service has been initialized.");
}
+ _async_mode = false;
+
}
SmartPointer::~SmartPointer()
{
+ if (_async_mode)
+ _data_feeder->streamOff();
}
void SmartPointer::internalDataFeederCb(BaseDataType &data, void *user_data)
{
auto smart_pointer = static_cast<SmartPointer *>(user_data);
- ImagePreprocessor preprocessor(data);
- ImageDataType preprocessed = dynamic_cast<ImageDataType &>(preprocessor.getData());
- ImageDataType copied = preprocessed;
- size_t buffer_size = copied.width * copied.height * copied.byte_per_pixel;
+ ImageDataType &image_data = dynamic_cast<ImageDataType &>(data);
+ size_t buffer_size = image_data.width * image_data.height * image_data.byte_per_pixel;
+ ImageDataType copied = image_data;
// We have to avoid from grapping input feed stream so copy the captured data to new one.
// Ps. This allocated buffer should be released as soon as the completion of invoke in async manager's thread loop.
copied.ptr = new unsigned char[buffer_size];
- memcpy(copied.ptr, preprocessed.ptr, buffer_size);
+ memcpy(copied.ptr, image_data.ptr, buffer_size);
if (smart_pointer->_user_cb) {
smart_pointer->_user_cb(copied.ptr, copied.width, copied.height, copied.byte_per_pixel, smart_pointer->_user_data);
}
- // delete copied.ptr;
+ if (smart_pointer->getAsyncManager()->pushInput(copied) != SINGLEO_ERROR_NONE)
+ delete [] copied.ptr;
}
void SmartPointer::add_input(BaseDataType &input_data)
}
_head_pose = _gaze_estimator->estimateHeadpose(preprocessor.getData());
+ updateResult(_head_pose);
}
void SmartPointer::performAsync()
{
+ if (!_data_feeder) {
+ SINGLEO_LOGE("This API is valid only the case that data feed service is used.");
+ throw InvalidOperation("Invalid API request.");
+ }
+
+ _data_feeder->streamOn();
+ // asynchronous handling
+ _async_mode = true;
+ _async_manager = make_unique<AsyncManager<ImageDataType, PointerPosition> >();
+ _async_manager->registerInvokeCb(this, [this](IService *service, BaseDataType &data) {
+ auto smart_pointer = static_cast<SmartPointer *>(service);
+
+ auto head_pose = smart_pointer->getGazeEstimator()->estimateHeadpose(data);
+ smart_pointer->updateResult(head_pose);
+ auto alloc_data = dynamic_cast<ImageDataType &>(data);
+ delete [] alloc_data.ptr;
+ });
+}
+
+void SmartPointer::updateResult(PoseVector &result)
+{
+ PointerPosition pos;
+ pos.pose = result;
+
+ if (_async_mode)
+ _async_manager->pushOutput(pos);
+ else
+ _pointerPosition = pos;
}
void SmartPointer::getResultCnt(unsigned int *cnt)
{
- *cnt = 1;
+ if (_async_mode) {
+ _pointerPosition = _async_manager->popOutput();
+ }
+ *cnt = 1;
}
void SmartPointer::getResultInt(unsigned int idx, std::string key, unsigned int *value)
{
}
+
+void SmartPointer::getResultFloat(unsigned int idx, std::string key, float *value)
+{
+ switch (_result_keys[key]) {
+ case PoseAngle::PITCH:
+ *value = _pointerPosition.pose._rot_vec.x;
+ break;
+ case PoseAngle::YAW:
+ *value = _pointerPosition.pose._rot_vec.y;
+ break;
+ case PoseAngle::ROLL:
+ *value = _pointerPosition.pose._rot_vec.z;
+ break;
+ }
+}
+
void SmartPointer::registerUserCallback(singleo_user_cb_t user_cb, void *user_data)
{
_user_cb = user_cb;
SET(TEST_CAMERA_DUMMY test_camera_dummy.cpp)
ADD_EXECUTABLE(test_camera_dummy ${TEST_CAMERA_DUMMY})
TARGET_INCLUDE_DIRECTORIES(test_camera_dummy PRIVATE ../../capi/ ../../common/include ../../visualizer/include)
-TARGET_LINK_LIBRARIES(test_camera_dummy gtest gtest_main pthread singleo_service singleo_visualizer)
+TARGET_LINK_LIBRARIES(test_camera_dummy gtest gtest_main pthread singleo_service singleo_visualizer opencv_imgcodecs)
INSTALL(TARGETS test_camera_dummy DESTINATION ${CMAKE_INSTALL_BINDIR})
static singleo_service_h handle;
+void user_callback(void *user_data)
+{
+ singleo_service_h context = static_cast<singleo_service_h>(user_data);
+ bool is_loop_exit = false;
+ unsigned long frame_number = 0;
+
+ while (!is_loop_exit) {
+ unsigned int cnt;
+ int ret = singleo_service_get_result_cnt(handle, &cnt);
+ if (ret != SINGLEO_ERROR_NONE)
+ continue;
+
+ float pitch, yaw, roll;
+ singleo_service_get_result_float(handle, 0, "PITCH", &pitch);
+ singleo_service_get_result_float(handle, 0, "YAW", &yaw);
+ singleo_service_get_result_float(handle, 0, "ROLL", &roll);
+
+ cout << "[Pitch, Yaw, Roll]: [ " << pitch << ", " << yaw << ", " << roll << " ]" << endl;
+ }
+}
+
+void data_feeder_cb(unsigned char *buffer, unsigned int width, unsigned int height, unsigned int bytes_per_pixel,
+ void *user_data)
+{
+ cv::Mat result(cv::Size(width, height), CV_MAKETYPE(CV_8U, bytes_per_pixel), buffer);
+ cv::Mat vizData;
+ cv::cvtColor(result, vizData, cv::COLOR_RGB2RGBA);
+
+ singleo_util_visualizer_2d(vizData, NULL);
+}
TEST(CameraDummyTest, CameraDisplayed)
{
- int ret = singleo_service_create("service=smart_pointer, input_feed=camera, camera_id=4, fps=30, async=0",
+ int ret = singleo_service_create("service=smart_pointer, input_feed=camera, camera_id=4, fps=15, async=1",
&handle);
ASSERT_EQ(ret, SINGLEO_ERROR_NONE);
- for (int i = 0; i < 10; ++i) {
- ret = singleo_service_perform(handle);
- ASSERT_EQ(ret, SINGLEO_ERROR_NONE);
- }
+ ret = singleo_service_register_user_callback(handle, data_feeder_cb, &handle);
+ ASSERT_EQ(ret, SINGLEO_ERROR_NONE);
+
+ ret = singleo_service_perform(handle);
+ ASSERT_EQ(ret, SINGLEO_ERROR_NONE);
+
+ unique_ptr<thread> thread_handle = make_unique<thread>(&user_callback, static_cast<void *>(handle));
+
+ thread_handle->join();
+
+ ret = singleo_service_unregister_user_callback(handle);
+ ASSERT_EQ(ret, SINGLEO_ERROR_NONE);
ret = singleo_service_destroy(handle);
ASSERT_EQ(ret, SINGLEO_ERROR_NONE);