|
|
@@ -0,0 +1,98 @@
|
|
|
+#include "image_enhance.h"
|
|
|
+#include "cuda_impl/image_enhance.cuh"
|
|
|
+
|
|
|
+namespace impl = image_enhance_impl;
|
|
|
+
|
|
|
+sp_image image_enhance(sp_image img, const image_enhance_options opts) {
|
|
|
+ assert(img.cv_type() == CV_8UC3);
|
|
|
+ img = create_dense(img);
|
|
|
+ const auto read_helper = read_access_helper(img.cuda());
|
|
|
+ float lum_mean = 0;
|
|
|
+ if (true) {
|
|
|
+ const auto buf = sp_image::create_like(img, CV_32FC1);
|
|
|
+ const auto write_helper = write_access_helper(buf.cuda());
|
|
|
+ lum_mean = impl::call_reduce_lum_mean(
|
|
|
+ (uchar3 *) read_helper.ptr(), (float *) write_helper.ptr(),
|
|
|
+ img.elem_count(), opts.black_eps_factor, current_cuda_stream());
|
|
|
+ }
|
|
|
+
|
|
|
+ const auto lum_factor = opts.luminance_target / lum_mean;
|
|
|
+ auto ret = sp_image::create_like(img);
|
|
|
+ const auto write_helper = write_access_helper(ret.cuda());
|
|
|
+ impl::call_aces_enhance(
|
|
|
+ (uchar3 *) read_helper.ptr(), (uchar3 *) write_helper.ptr(),
|
|
|
+ img.elem_count(), lum_factor, current_cuda_stream());
|
|
|
+ ret.merge_meta(img);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+#include "core/imgui_utility.hpp"
|
|
|
+
|
|
|
+struct image_enhance_ui::impl {
|
|
|
+ create_config conf;
|
|
|
+ obj_conn_type conn;
|
|
|
+
|
|
|
+ struct ui_config {
|
|
|
+ image_enhance_options opts;
|
|
|
+ bool passthrough = false;
|
|
|
+ };
|
|
|
+
|
|
|
+ std::shared_ptr<ui_config> ui_conf;
|
|
|
+
|
|
|
+ static void image_callback_impl(create_config conf) {
|
|
|
+ const auto img = OBJ_QUERY(sp_image, conf.in_name);
|
|
|
+ const auto ret_img = image_enhance(img, conf.opts);
|
|
|
+ OBJ_SAVE(conf.out_name, ret_img);
|
|
|
+ }
|
|
|
+
|
|
|
+ void image_callback() {
|
|
|
+ conf.opts = ui_conf->opts;
|
|
|
+ if (ui_conf->passthrough) {
|
|
|
+ OBJ_SAVE(conf.out_name, OBJ_QUERY(sp_image, conf.in_name));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ auto task = [conf=conf] {
|
|
|
+ try {
|
|
|
+ image_callback_impl(conf);
|
|
|
+ } catch (...) { (void) 0; }
|
|
|
+ };
|
|
|
+ TP_DETACH(task);
|
|
|
+ }
|
|
|
+
|
|
|
+ void show_ui() const {
|
|
|
+ ImGui::Checkbox("Passthrough", &ui_conf->passthrough);
|
|
|
+ auto disable_guard = imgui_disable_guard(ui_conf->passthrough);
|
|
|
+ ImGui::DragFloat("Luminance Target", &ui_conf->opts.luminance_target,
|
|
|
+ 0.002, 0, 2, "%.3f");
|
|
|
+ float eps_db = 10 * log10f(ui_conf->opts.black_eps_factor);
|
|
|
+ if (ImGui::DragFloat("Black Level (dB)", &eps_db,
|
|
|
+ 0.5, -70, -10, "%.1f")) {
|
|
|
+ ui_conf->opts.black_eps_factor = exp10f(eps_db / 10);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ explicit impl(const create_config _conf) : conf(_conf) {
|
|
|
+ ui_conf = std::make_shared<ui_config>();
|
|
|
+ ui_conf->opts = conf.opts;
|
|
|
+ conn = OBJ_SIG(conf.in_name)->connect(
|
|
|
+ [this](auto _) { image_callback(); });
|
|
|
+ }
|
|
|
+
|
|
|
+ ~impl() {
|
|
|
+ conn.disconnect();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+image_enhance_ui::image_enhance_ui(create_config conf)
|
|
|
+ : pimpl(std::make_unique<impl>(conf)) { (void) 0; }
|
|
|
+
|
|
|
+image_enhance_ui::~image_enhance_ui() = default;
|
|
|
+
|
|
|
+void image_enhance_ui::show_ui() const {
|
|
|
+ pimpl->show_ui();
|
|
|
+}
|
|
|
+
|
|
|
+void image_enhance_ui::sync_with(const image_enhance_ui *other) const {
|
|
|
+ pimpl->ui_conf = other->pimpl->ui_conf;
|
|
|
+}
|