Переглянути джерело

Move image render to another module.

jcsyshc 1 рік тому
батько
коміт
cd8ee73939

+ 1 - 0
CMakeLists.txt

@@ -9,6 +9,7 @@ add_executable(${PROJECT_NAME} src/main.cpp
         src/impl/object_manager.cpp
         src/module/impl/image_viewer.cpp
         src/render/impl/render_texture.cpp
+        src/render/impl/render_tools.cpp
         src/render/impl/render_utility.cpp)
 
 target_include_directories(${PROJECT_NAME} PRIVATE src)

+ 31 - 27
src/image_utility.hpp

@@ -61,6 +61,27 @@ struct image_info_type {
     }
 };
 
+template<typename T>
+auto create_image_info(cv::Size size, memory_location mem_loc) {
+    auto info = image_info_type<T>();
+    info.ptr = ALLOC_IMG(T, size, mem_loc, &info.pitch);
+    info.loc = mem_loc;
+    info.size = size;
+    return info;
+}
+
+template<typename T>
+auto create_image_info(const cv::Mat &img) {
+    assert(get_cv_type<T>() == img.type());
+    auto info = image_info_type<T>();
+    info.ptr = std::shared_ptr<T>( // extend cv::Mat's lifetime
+            (T *) img.data, [_img = img](void *) {});
+    info.loc = MEM_HOST;
+    info.size = img.size();
+    info.pitch = img.step;
+    return info;
+}
+
 // read-only image type to decrease host-gpu memory copy
 template<typename T>
 class smart_image {
@@ -79,13 +100,11 @@ public:
     image_info_type<T> as_host_info(smart_cuda_stream *stream = nullptr) {
         if (host_info.ptr == nullptr) {
             assert(cuda_info.ptr != nullptr);
-            host_info.ptr = ALLOC_IMG(T, cuda_info.size, MEM_HOST, &host_info.pitch);
+            host_info = create_image_info<T>(cuda_info.size, MEM_HOST);
             CUDA_API_CHECK(cudaMemcpy2DAsync(host_info.ptr.get(), host_info.pitch,
                                              cuda_info.ptr.get(), cuda_info.pitch,
                                              cuda_info.size.width * sizeof(T), cuda_info.size.height,
                                              cudaMemcpyDeviceToHost, stream->cuda));
-            host_info.loc = MEM_HOST;
-            host_info.size = cuda_info.size;
         }
         assert(host_info.ptr != nullptr);
         return host_info;
@@ -94,18 +113,24 @@ public:
     image_info_type<T> as_cuda_info(smart_cuda_stream *stream = nullptr) {
         if (cuda_info.ptr == nullptr) {
             assert(host_info.ptr != nullptr);
-            cuda_info.ptr = ALLOC_IMG(T, host_info.size, MEM_CUDA, &cuda_info.pitch);
+            cuda_info = create_image_info<T>(host_info.size, MEM_CUDA);
             CUDA_API_CHECK(cudaMemcpy2DAsync(cuda_info.ptr.get(), cuda_info.pitch,
                                              host_info.ptr.get(), host_info.pitch,
                                              host_info.size.width * sizeof(T), host_info.size.height,
                                              cudaMemcpyHostToDevice, stream->cuda));
-            cuda_info.loc = MEM_CUDA;
-            cuda_info.size = host_info.size;
         }
         assert(cuda_info.ptr != nullptr);
         return cuda_info;
     }
 
+    image_info_type<T> as_info() { // TODO: select prefer location
+        if (cuda_info.ptr != nullptr) {
+            return cuda_info;
+        }
+        assert(host_info.ptr != nullptr);
+        return host_info;
+    }
+
     cv::Mat as_host(smart_cuda_stream *stream = nullptr) {
         return as_host_info(stream).as_mat();
     }
@@ -127,27 +152,6 @@ private:
     image_info_type<T> cuda_info;
 };
 
-template<typename T>
-auto create_image_info(cv::Size size, memory_location mem_loc) {
-    auto info = image_info_type<T>();
-    info.ptr = ALLOC_IMG(T, size, mem_loc, &info.pitch);
-    info.loc = mem_loc;
-    info.size = size;
-    return info;
-}
-
-template<typename T>
-auto create_image_info(const cv::Mat &img) {
-    assert(get_cv_type<T>() == img.type());
-    auto info = image_info_type<T>();
-    info.ptr = std::shared_ptr<T>( // extend cv::Mat's lifetime
-            (T *) img.data, [_img = img](void *) {});
-    info.loc = MEM_HOST;
-    info.size = img.size();
-    info.pitch = img.step;
-    return info;
-}
-
 template<typename T>
 auto create_image(image_info_type<T> info) {
     return std::make_shared<smart_image<T>>(info);

+ 10 - 0
src/impl/object_manager.cpp

@@ -33,6 +33,12 @@ void *object_manager::impl::query_placeholder(name_type obj_name, std::type_inde
     return obj_st.ptr;
 }
 
+std::type_index object_manager::impl::query_type(obj_name_type obj_name) {
+    auto iter = obj_pool.find(obj_name);
+    assert(iter != obj_pool.end());
+    return iter->second.type;
+}
+
 void object_manager::impl::create_placeholder(name_type obj_name, std::type_index obj_type,
                                               void *ptr, del_func_type del_func) {
     assert(!obj_pool.contains(obj_name));
@@ -81,6 +87,10 @@ void *object_manager::query_placeholder(name_type obj_name, std::type_index obj_
     return pimpl->query_placeholder(obj_name, obj_type);
 }
 
+std::type_index object_manager::query_type(name_type obj_name) {
+    return pimpl->query_type(obj_name);
+}
+
 void object_manager::create_placeholder(name_type obj_name, std::type_index obj_type,
                                         void *ptr, del_func_type del_func) {
     pimpl->create_placeholder(obj_name, obj_type, ptr, del_func);

+ 2 - 0
src/impl/object_manager_impl.h

@@ -35,6 +35,8 @@ struct object_manager::impl {
 
     void *query_placeholder(name_type obj_name, std::type_index obj_type);
 
+    std::type_index query_type(obj_name_type obj_name);
+
     void create_placeholder(name_type obj_name, std::type_index obj_type,
                             void *ptr, del_func_type del_func);
 

+ 19 - 54
src/module/impl/image_viewer.cpp

@@ -2,8 +2,6 @@
 #include "imgui_utility.hpp"
 #include "render/render_texture.h"
 
-#include <opencv2/imgproc.hpp>
-
 void image_viewer::impl::show_color_depth() {
     ImGui::RadioButton("Color", &chose_index, 0);
     ImGui::SameLine();
@@ -12,16 +10,17 @@ void image_viewer::impl::show_color_depth() {
     ImGui::RadioButton("Both", &chose_index, 2);
 
     {
-        auto guard = imgui_disable_guard(!manual_dep_range);
+        auto guard = imgui_disable_guard(!depth_conf.manual_depth_range);
         static constexpr float dep_hard_min = 0.15; // TODO: config value
         static constexpr float dep_hard_max = 10.0;
-        ImGui::DragFloat2("Depth Range", (float *) &dep_range, 0.05f, dep_hard_min, dep_hard_max, "%.2f");
+        ImGui::DragFloat2("Depth Range", (float *) &depth_conf.depth_range, 0.05f,
+                          dep_hard_min, dep_hard_max, "%.2f");
     }
     ImGui::SameLine();
-    ImGui::Checkbox("##manual_dep_range", &manual_dep_range);
+    ImGui::Checkbox("##manual_dep_range", &depth_conf.manual_depth_range);
 
     if (chose_index == 2) { // both
-        ImGui::SliderFloat("Depth Alpha", &dep_alpha, 0.f, 1.f, "%.2f");
+        ImGui::SliderFloat("Depth Alpha", &depth_overlay_alpha, 0.f, 1.f, "%.2f");
     }
 }
 
@@ -37,54 +36,13 @@ void image_viewer::impl::show() {
     }
 }
 
-simple_rect image_viewer::impl::calc_range(cv::Size size) {
-    return simple_rect{-1, -1, 2, 2}
-            .fit_aspect(size.aspectRatio() /
-                        query_viewport_size().aspectRatio());
-}
-
-void image_viewer::impl::render_rgb_image(const image_u8c3 &img, float alpha) {
-    auto img_info = img->as_cuda_info(conf.stream);
-    img_tex.upload(img_info, conf.stream);
-
-    auto info = tex_render_info();
-    info.mode = TEX_COLOR_ONLY;
-    info.flip_y = conf.flip_y;
-    info.range = calc_range(img_info.size);
-    info.color.id = img_tex.id;
-    info.color.alpha = alpha;
-    render_texture(info);
-}
-
-void image_viewer::impl::render_color_obj(obj_name_type name, float alpha) {
-    auto img = OBJ_QUERY(image_u8c3, name);
-    if (img == nullptr) [[unlikely]] return;
-    render_rgb_image(img, alpha);
+void image_viewer::impl::render_color_obj(obj_name_type name) {
+    color_render.render(name, color_conf);
 }
 
 void image_viewer::impl::render_depth_obj(obj_name_type name, float alpha) {
-    auto img = OBJ_QUERY(image_f32c1, name);
-    if (img == nullptr) [[unlikely]] return;
-    auto img_mat = img->as_host(conf.stream);
-
-    // convert to u8c1 // TODO: accelerate with CUDA
-    double min_val, max_val;
-    if (!manual_dep_range) {
-        cv::minMaxLoc(img_mat, &min_val, &max_val, nullptr, nullptr);
-    } else {
-        min_val = dep_range.min * 1000; // m -> mm
-        max_val = dep_range.max * 1000;
-    }
-    auto img_u8 = create_image_info<uchar1>(img_mat.size(), MEM_HOST);
-    img_mat.convertTo(img_u8.as_mat(), CV_8UC1,
-                      255.0 / (max_val - min_val),
-                      -min_val / (max_val - min_val));
-
-    // add false color // TODO: accelerate with CUDA
-    auto img_color = create_image_info<uchar3>(img_mat.size(), MEM_HOST);
-    cv::applyColorMap(img_u8.as_mat(), img_color.as_mat(), cv::COLORMAP_TURBO);
-
-    render_rgb_image(create_image(img_color), alpha);
+    depth_conf.alpha = alpha;
+    depth_render.render(name, depth_conf);
 }
 
 void image_viewer::impl::render_color_depth() {
@@ -100,7 +58,7 @@ void image_viewer::impl::render_color_depth() {
         }
         case 2: { // both
             render_color_obj(info.c_name);
-            render_depth_obj(info.d_name, dep_alpha);
+            render_depth_obj(info.d_name, depth_overlay_alpha);
             break;
         }
         default: {
@@ -121,9 +79,16 @@ void image_viewer::impl::render() {
     }
 }
 
+image_viewer::impl::impl(create_config _conf) {
+    conf = _conf;
+    color_conf.flip_y = conf.flip_y;
+    color_conf.stream = conf.stream;
+    depth_conf.flip_y = conf.flip_y;
+    depth_conf.stream = conf.stream;
+}
+
 image_viewer::image_viewer(create_config conf)
-        : pimpl(std::make_unique<impl>()) {
-    pimpl->conf = conf;
+        : pimpl(std::make_unique<impl>(conf)) {
 }
 
 image_viewer::~image_viewer() = default;

+ 12 - 14
src/module/impl/image_viewer_impl.h

@@ -2,7 +2,7 @@
 #define DEPTHGUIDE_IMAGE_VIEWER_IMPL_H
 
 #include "module/image_viewer.h"
-#include "render/render_utility.h"
+#include "render/render_tools.h"
 
 struct image_viewer::impl {
 
@@ -14,26 +14,22 @@ struct image_viewer::impl {
      *   0 = left, 1 = right */
     int chose_index = 0;
 
-    // for depth false color
-    struct {
-        float min = 0.15, max = 10.0;
-    } dep_range; // depth range
-    bool manual_dep_range = false;
+    using color_conf_type = color_image_render::config_type;
+    using depth_conf_type = depth_image_render::config_type;
 
-    // depth over color alpha
-    float dep_alpha = 0.5;
+    depth_conf_type depth_conf = {};
+    depth_image_render depth_render;
 
-    smart_texture img_tex;
+    color_conf_type color_conf = {};
+    color_image_render color_render;
+
+    float depth_overlay_alpha = 0.5;
 
     void show_color_depth();
 
     void show();
 
-    static simple_rect calc_range(cv::Size size);
-
-    void render_rgb_image(const image_u8c3 &img, float alpha = 1.0);
-
-    void render_color_obj(obj_name_type name, float alpha = 1.0);
+    void render_color_obj(obj_name_type name);
 
     // render depth with false color
     void render_depth_obj(obj_name_type name, float alpha = 1.0);
@@ -42,6 +38,8 @@ struct image_viewer::impl {
 
     void render();
 
+    explicit impl(create_config conf);
+
 };
 
 #endif //DEPTHGUIDE_IMAGE_VIEWER_IMPL_H

+ 5 - 0
src/object_manager.h

@@ -43,6 +43,8 @@ public:
         return *(T *) pl_ptr;
     }
 
+    std::type_index query_type(name_type obj_name);
+
     using priority_type = int;
     using ob_type = std::function<void(name_type)>;
     using de_ob_func_type = std::function<void()>;
@@ -73,6 +75,9 @@ extern object_manager main_ob;
 #define OBJ_QUERY(type, name) \
     main_ob.query<type>(name)
 
+#define OBJ_TYPE(name) \
+    main_ob.query_type(name)
+
 #define OBJ_SAVE(name, val) \
     main_ob.save(name, val)
 

+ 60 - 0
src/render/impl/render_tools.cpp

@@ -0,0 +1,60 @@
+#include "render/render_texture.h"
+#include "render/render_tools.h"
+
+#include <opencv2/imgproc.hpp>
+
+simple_rect calc_render_range(cv::Size img_size) {
+    return simple_rect{-1, -1, 2, 2}
+            .fit_aspect(img_size.aspectRatio() /
+                        query_viewport_size().aspectRatio());
+}
+
+void color_image_render::render_tex(cv::Size img_size, config_type conf) {
+    auto info = tex_render_info();
+    info.mode = TEX_COLOR_ONLY;
+    info.flip_y = conf.flip_y;
+    info.range = calc_render_range(img_size);
+    info.color.id = img_tex.id;
+    info.color.alpha = conf.alpha;
+    render_texture(info);
+}
+
+void color_image_render::render(obj_name_type name, config_type conf) {
+    auto img_type = OBJ_TYPE(name);
+    assert(img_type == typeid(image_u8c3));
+    auto img = OBJ_QUERY(image_u8c3, name);
+    if (img == nullptr) return;
+    render(img->as_info(), conf);
+}
+
+void depth_image_render::render(obj_name_type name, config_type conf) {
+    auto img_type = OBJ_TYPE(name);
+    assert(img_type == typeid(image_f32c1));
+
+    auto img = OBJ_QUERY(image_f32c1, name);
+    if (img == nullptr) [[unlikely]] return;
+    auto img_mat = img->as_host(conf.stream);
+
+    // convert to u8c1 // TODO: accelerate with CUDA
+    double min_val, max_val;
+    if (!conf.manual_depth_range) {
+        cv::minMaxLoc(img_mat, &min_val, &max_val, nullptr, nullptr);
+    } else {
+        min_val = conf.depth_range.min * 1000; // m -> mm
+        max_val = conf.depth_range.max * 1000;
+    }
+    auto img_u8 = create_image_info<uchar1>(img_mat.size(), MEM_HOST);
+    img_mat.convertTo(img_u8.as_mat(), CV_8UC1,
+                      255.0 / (max_val - min_val),
+                      -min_val / (max_val - min_val));
+
+    // add false color // TODO: accelerate with CUDA
+    auto img_color = create_image_info<uchar3>(img_mat.size(), MEM_HOST);
+    cv::applyColorMap(img_u8.as_mat(), img_color.as_mat(), cv::COLORMAP_TURBO);
+
+    auto c_conf = color_image_render::config_type();
+    c_conf.flip_y = conf.flip_y;
+    c_conf.alpha = conf.alpha;
+    c_conf.stream = conf.stream;
+    color_render.render(img_color, c_conf);
+}

+ 55 - 0
src/render/render_tools.h

@@ -0,0 +1,55 @@
+#ifndef DEPTHGUIDE_RENDER_TOOLS_H
+#define DEPTHGUIDE_RENDER_TOOLS_H
+
+#include "object_manager.h"
+#include "render_utility.h"
+
+simple_rect calc_render_range(cv::Size img_size);
+
+class color_image_render {
+public:
+
+    struct config_type {
+        bool flip_y = false;
+        float alpha = 1.0;
+        smart_cuda_stream *stream = nullptr;
+    };
+
+    template<typename T>
+    void render(const image_info_type<T> &img, config_type conf) {
+        img_tex.upload(img, conf.stream);
+        render_tex(img.size, conf);
+    }
+
+    void render(obj_name_type name, config_type conf);
+
+private:
+    smart_texture img_tex;
+
+    void render_tex(cv::Size img_size, config_type conf);
+};
+
+class depth_image_render {
+public:
+
+    struct config_type {
+        bool flip_y = false;
+        float alpha = 1.0;
+
+        bool manual_depth_range = false;
+        struct {
+            float min = 0.15; // unit in meter
+            float max = 10.0; // unit in meter
+        } depth_range;
+
+        smart_cuda_stream *stream = nullptr;
+    };
+
+    void render(obj_name_type name, config_type conf);
+
+private:
+    color_image_render color_render;
+};
+
+
+#endif //DEPTHGUIDE_RENDER_TOOLS_H