display camera preview image in application
authorInki Dae <inki.dae@samsung.com>
Tue, 26 Mar 2024 02:53:44 +0000 (11:53 +0900)
committerInki Dae <inki.dae@samsung.com>
Tue, 26 Mar 2024 04:01:27 +0000 (13:01 +0900)
Display camera preview image mixed with bounding box for debug in application
instead of singleo service framework-internally.

Regarding this, this patch introduces Context structure so that
the test application can manage camera preview image and bounding box.

Signed-off-by: Inki Dae <inki.dae@samsung.com>
services/auto_zoom/src/AutoZoom.cpp
test/services/test_autozoom_on_screen.cpp

index 1a55f4c01d7e065bfe4569679dc1ebfa8a16ab9c..33aad0aeb3e7c31cc69b4cb8f91d07c779515ffd 100644 (file)
@@ -73,8 +73,12 @@ void AutoZoom::inputServiceCb(BaseDataType &data, void *user_data)
        memcpy(copied.ptr, preprocessed.ptr, buffer_size);
 
        // Make sure to release copied buffer if incoming queue isn't empty so skipped pushing the buffer.
-       if (auto_zoom->getAsyncManager()->pushInput(copied) != SINGLEO_ERROR_NONE)
+       if (auto_zoom->getAsyncManager()->pushInput(copied) != SINGLEO_ERROR_NONE) {
+               if (auto_zoom->_user_cb)
+                       auto_zoom->_user_cb(copied.ptr, copied.width, copied.height, copied.byte_per_pixel, auto_zoom->_user_data);
+
                delete copied.ptr;
+       }
 }
 
 bool AutoZoom::isKeyValid(std::string key)
@@ -109,7 +113,8 @@ void AutoZoom::perform()
 {
        ImagePreprocessor preprocessor;
 
-       // If input service is not set, input data is from file.
+       // If input service is not set, input data comes from user.
+       // In this case, get input data from queue, _input_image_data.
        if (!_input_service) {
                shared_ptr<BaseDataType> result = _input_image_data.dequeue();
                auto data = dynamic_pointer_cast<FileDataType>(result);
@@ -175,25 +180,11 @@ void AutoZoom::updateResult(BaseDataType &in_data)
                }
        }
 
-       // For debug
-       ImagePreprocessor preprocessed_result(in_data);
-
-       // If detected object exists then draw a box on captured image.
-       if (result_cnt > 0)
-               preprocessed_result.drawBox(rect, 0, 0, 255);
-
        // TODO. implement Postprocessor which calculates Autozoom position using above 'result' vector.
 
        SINGLEO_LOGD("result cnt = %zu", result_cnt);
        _result.num_of_result = result_cnt;
 
-       // If user callback exists then call it. This callback is used for the debug.
-       if (_user_cb) {
-               auto &imageData = dynamic_cast<ImageDataType &>(preprocessed_result.getData());
-
-               _user_cb(imageData.ptr, imageData.width, imageData.height, imageData.byte_per_pixel, _user_data);
-       }
-
        if (result_cnt == 0) {
                SINGLEO_LOGW("No detected objects.");
                return;
index ab4149022b1da477966090f2696aad1b6b62b97f..15802cbef1df8e74d1ac2a81086ca5cab9e105b5 100644 (file)
@@ -19,6 +19,7 @@
 #include <memory>
 #include <string.h>
 #include <thread>
+#include <mutex>
 
 #include <opencv2/opencv.hpp>
 
 using namespace testing;
 using namespace std;
 
+struct Rect {
+       int left;
+       int top;
+       int right;
+       int bottom;
+};
+
+struct Rgb {
+       int r;
+       int g;
+       int b;
+};
+
+struct Context {
+       singleo_service_h handle {};
+       std::mutex mutex;
+       Rect rect {};
+       Rgb rgb {};
+};
+
 void autozoom_callback(void *user_data)
 {
-       singleo_service_h handle = static_cast<singleo_service_h>(user_data);
+       Context *context = static_cast<Context *>(user_data);
+       singleo_service_h handle = static_cast<singleo_service_h>(context->handle);
        bool is_loop_exit = false;
        unsigned long frame_number = 0;
 
@@ -58,6 +80,13 @@ void autozoom_callback(void *user_data)
                        ASSERT_EQ(ret, SINGLEO_ERROR_NONE);
 
                        cout << x << " x " << y << " ~ " << w << " x " << h << endl;
+
+                       context->mutex.lock();
+                       context->rect.left = x;
+                       context->rect.top = y;
+                       context->rect.bottom = h;
+                       context->rect.right = w;
+                       context->mutex.unlock();
                }
 
                if (++frame_number > 500 && cnt > 0)
@@ -68,9 +97,20 @@ void autozoom_callback(void *user_data)
 void user_callback(unsigned char *buffer, unsigned int width, unsigned int height, unsigned int bytes_per_pixel,
                                   void *user_data)
 {
+       Context *context = static_cast<Context *>(user_data);
+       Rgb *rgb = &context->rgb;
+
+       context->mutex.lock();
+       Rect rect = context->rect;
+       context->mutex.unlock();
+
        cv::Mat cv_image(cv::Size(width, height), CV_MAKETYPE(CV_8U, 3), buffer);
 
+       cv::Point leftTop(rect.left, rect.top);
+       cv::Point rightBottom(rect.right, rect.bottom);
+
        cv::cvtColor(cv_image, cv_image, cv::COLOR_BGR2RGBA);
+       cv::rectangle(cv_image, cv::Rect(leftTop, rightBottom), cv::Scalar(rgb->r, rgb->g, rgb->b));
 
        cv::Mat resized_image(cv::Size(1600, 900), CV_8UC4, cv::Scalar(0, 0, 0, 0));
        cv::resize(cv_image, resized_image, resized_image.size());
@@ -80,24 +120,29 @@ void user_callback(unsigned char *buffer, unsigned int width, unsigned int heigh
 
 TEST(AutoZoomAsyncOnScreenTest, InferenceRequestWithCameraInputFeedShouldBeOk)
 {
-       singleo_service_h handle;
+       Context context {};
+
+       context.rgb.r = 255;
+       context.rgb.g = 0;
+       context.rgb.b = 0;
 
-       int ret = singleo_service_create("service=auto_zoom, input_feed=camera, camera_id=0, fps=30, async=1", &handle);
+       int ret = singleo_service_create("service=auto_zoom, input_feed=camera, camera_id=0, fps=30, async=1",
+                                                                        &context.handle);
        ASSERT_EQ(ret, SINGLEO_ERROR_NONE);
 
-       ret = singleo_service_register_user_callback(handle, user_callback, nullptr);
+       ret = singleo_service_register_user_callback(context.handle, user_callback, &context);
        ASSERT_EQ(ret, SINGLEO_ERROR_NONE);
 
-       ret = singleo_service_perform(handle);
+       ret = singleo_service_perform(context.handle);
        ASSERT_EQ(ret, SINGLEO_ERROR_NONE);
 
-       unique_ptr<thread> thread_handle = make_unique<thread>(&autozoom_callback, static_cast<void *>(handle));
+       unique_ptr<thread> thread_handle = make_unique<thread>(&autozoom_callback, static_cast<void *>(&context));
 
        thread_handle->join();
 
-       ret = singleo_service_unregister_user_callback(handle);
+       ret = singleo_service_unregister_user_callback(context.handle);
        ASSERT_EQ(ret, SINGLEO_ERROR_NONE);
 
-       ret = singleo_service_destroy(handle);
+       ret = singleo_service_destroy(context.handle);
        ASSERT_EQ(ret, SINGLEO_ERROR_NONE);
 }