From 475e9b34ff85cf6058ac639fde4b73264e350195 Mon Sep 17 00:00:00 2001 From: "xun.zhang" Date: Fri, 20 Sep 2024 19:23:37 +0800 Subject: [PATCH] ENH: add module flush vol predictor jira:NONE Signed-off-by: xun.zhang Change-Id: Ie1b0d4c443df4a26ff1b010e73d589162a0fbff7 --- resources/flush/flush_data.txt | 96 +++++++++++++++++++++++++++++ src/libslic3r/CMakeLists.txt | 2 + src/libslic3r/FlushVolCalc.cpp | 87 +++++++++++++++----------- src/libslic3r/FlushVolCalc.hpp | 5 ++ src/libslic3r/FlushVolPredictor.cpp | 96 +++++++++++++++++++++++++++++ src/libslic3r/FlushVolPredictor.hpp | 22 +++++++ 6 files changed, 272 insertions(+), 36 deletions(-) create mode 100644 resources/flush/flush_data.txt create mode 100644 src/libslic3r/FlushVolPredictor.cpp create mode 100644 src/libslic3r/FlushVolPredictor.hpp diff --git a/resources/flush/flush_data.txt b/resources/flush/flush_data.txt new file mode 100644 index 000000000..e7f9f638e --- /dev/null +++ b/resources/flush/flush_data.txt @@ -0,0 +1,96 @@ +src dst flush +#000000 #545454 236 +#000000 #F4EE2A 386 +#000000 #5E43B7 266 +#000000 #0A2989 236 +#C12E1F #000000 26 +#C12E1F #00AE42 326 +#C12E1F #F4EE2A 356 +#C12E1F #FF6A13 146 +#00AE42 #000000 26 +#00AE42 #C12E1F 146 +#00AE42 #545454 56 +#00AE42 #D1D3D5 266 +#00AE42 #F4EE2A 176 +#00AE42 #9D432C 86 +#00AE42 #FF6A13 206 +#00AE42 #8E9089 206 +#545454 #C12E1F 146 +#545454 #00AE42 116 +#545454 #D1D3D5 176 +#545454 #5B6579 86 +#545454 #F4EE2A 206 +#545454 #9D432C 86 +#545454 #5E43B7 56 +#545454 #FF6A13 236 +#545454 #8E9089 56 +#D1D3D5 #C12E1F 116 +#D1D3D5 #00AE42 116 +#D1D3D5 #F4EE2A 56 +#D1D3D5 #9D432C 86 +#D1D3D5 #5E43B7 86 +#D1D3D5 #FF6A13 86 +#5B6579 #000000 26 +#5B6579 #C12E1F 56 +#5B6579 #00AE42 26 +#5B6579 #545454 26 +#5B6579 #D1D3D5 56 +#5B6579 #F4EE2A 116 +#5B6579 #9D432C 56 +#5B6579 #5E43B7 26 +#5B6579 #0A2989 26 +#5B6579 #FF6A13 116 +#5B6579 #8E9089 26 +#F4EE2A #000000 56 +#F4EE2A #C12E1F 26 +#F4EE2A #00AE42 86 +#F4EE2A #545454 146 +#F4EE2A #9D432C 86 +#F4EE2A #5E43B7 146 +#F4EE2A #FF6A13 26 +#9D432C #000000 56 +#9D432C #C12E1F 56 +#9D432C #00AE42 176 +#9D432C #545454 86 +#9D432C #D1D3D5 236 +#9D432C #F4EE2A 206 +#9D432C #5E43B7 116 +#9D432C #0A2989 86 +#9D432C #FF6A13 116 +#9D432C #8E9089 146 +#5E43B7 #C12E1F 176 +#5E43B7 #00AE42 116 +#5E43B7 #545454 56 +#5E43B7 #D1D3D5 206 +#5E43B7 #5B6579 116 +#5E43B7 #F4EE2A 206 +#5E43B7 #9D432C 86 +#5E43B7 #0A2989 56 +#5E43B7 #FF6A13 206 +#5E43B7 #8E9089 146 +#0A2989 #000000 26 +#0A2989 #C12E1F 266 +#0A2989 #00AE42 146 +#0A2989 #545454 86 +#0A2989 #D1D3D5 386 +#0A2989 #5B6579 176 +#0A2989 #F4EE2A 566 +#0A2989 #9D432C 206 +#0A2989 #5E43B7 116 +#0A2989 #FF6A13 326 +#0A2989 #8E9089 206 +#FF6A13 #000000 56 +#FF6A13 #C12E1F 26 +#FF6A13 #545454 86 +#FF6A13 #D1D3D5 146 +#FF6A13 #F4EE2A 146 +#FF6A13 #9D432C 56 +#FF6A13 #5E43B7 146 +#FF6A13 #0A2989 146 +#FF6A13 #8E9089 116 +#8E9089 #C12E1F 86 +#8E9089 #00AE42 56 +#8E9089 #D1D3D5 86 +#8E9089 #F4EE2A 206 +#8E9089 #9D432C 86 +#8E9089 #FF6A13 86 \ No newline at end of file diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 1751e25bd..591639685 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -426,6 +426,8 @@ set(lisbslic3r_sources RegionExpansion.hpp RegionExpansion.cpp ClipperZUtils.hpp + FlushVolPredictor.hpp + FlushVolPredictor.cpp ) if (APPLE) diff --git a/src/libslic3r/FlushVolCalc.cpp b/src/libslic3r/FlushVolCalc.cpp index 29cbcbe40..d8862ae23 100644 --- a/src/libslic3r/FlushVolCalc.cpp +++ b/src/libslic3r/FlushVolCalc.cpp @@ -1,7 +1,7 @@ #include #include #include "slic3r/Utils/ColorSpaceConvert.hpp" - +#include "Utils.hpp" #include "FlushVolCalc.hpp" @@ -44,6 +44,55 @@ FlushVolCalculator::FlushVolCalculator(int min, int max, float multiplier) { } +int FlushVolCalculator::calc_flush_vol_rgb(unsigned char src_r, unsigned char src_g, unsigned char src_b, + unsigned char dst_r, unsigned char dst_g, unsigned char dst_b) +{ + auto& pd = FlushVolPredictor::get_instance(); + float ret_flush_volume = 0; + bool success = pd.predict(src_r, src_g, src_b, dst_r, dst_g, dst_b, ret_flush_volume); + // if we could find the color pair from dataset, we need to recalculate + if (!success) { + float src_r_f, src_g_f, src_b_f, dst_r_f, dst_g_f, dst_b_f; + float from_hsv_h, from_hsv_s, from_hsv_v; + float to_hsv_h, to_hsv_s, to_hsv_v; + + src_r_f = (float)src_r / 255.f; + src_g_f = (float)src_g / 255.f; + src_b_f = (float)src_b / 255.f; + dst_r_f = (float)dst_r / 255.f; + dst_g_f = (float)dst_g / 255.f; + dst_b_f = (float)dst_b / 255.f; + + // Calculate color distance in HSV color space + RGB2HSV(src_r_f, src_g_f,src_b_f, &from_hsv_h, &from_hsv_s, &from_hsv_v); + RGB2HSV(dst_r_f, dst_g_f, dst_b_f, &to_hsv_h, &to_hsv_s, &to_hsv_v); + float hs_dist = DeltaHS_BBS(from_hsv_h, from_hsv_s, from_hsv_v, to_hsv_h, to_hsv_s, to_hsv_v); + + // 1. Color difference is more obvious if the dest color has high luminance + // 2. Color difference is more obvious if the source color has low luminance + float from_lumi = get_luminance(src_r_f, src_g_f, src_b_f); + float to_lumi = get_luminance(dst_r_f, dst_g_f, dst_b_f); + float lumi_flush = 0.f; + if (to_lumi >= from_lumi) { + lumi_flush = std::pow(to_lumi - from_lumi, 0.7f) * 560.f; + } + else { + lumi_flush = (from_lumi - to_lumi) * 80.f; + + float inter_hsv_v = 0.67 * to_hsv_v + 0.33 * from_hsv_v; + hs_dist = std::min(inter_hsv_v, hs_dist); + } + float hs_flush = 230.f * hs_dist; + + float flush_volume = calc_triangle_3rd_edge(hs_flush, lumi_flush, 120.f); + flush_volume = std::max(flush_volume, 60.f); + + ret_flush_volume = flush_volume; + } + + return ret_flush_volume; +} + int FlushVolCalculator::calc_flush_vol(unsigned char src_a, unsigned char src_r, unsigned char src_g, unsigned char src_b, unsigned char dst_a, unsigned char dst_r, unsigned char dst_g, unsigned char dst_b) { @@ -55,42 +104,8 @@ int FlushVolCalculator::calc_flush_vol(unsigned char src_a, unsigned char src_r, dst_r = dst_g = dst_b = 255; } - float src_r_f, src_g_f, src_b_f, dst_r_f, dst_g_f, dst_b_f; - float from_hsv_h, from_hsv_s, from_hsv_v; - float to_hsv_h, to_hsv_s, to_hsv_v; + float flush_volume = calc_flush_vol_rgb(src_r, src_g, src_b, dst_r, dst_g, dst_b); - src_r_f = (float)src_r / 255.f; - src_g_f = (float)src_g / 255.f; - src_b_f = (float)src_b / 255.f; - dst_r_f = (float)dst_r / 255.f; - dst_g_f = (float)dst_g / 255.f; - dst_b_f = (float)dst_b / 255.f; - - // Calculate color distance in HSV color space - RGB2HSV(src_r_f, src_g_f,src_b_f, &from_hsv_h, &from_hsv_s, &from_hsv_v); - RGB2HSV(dst_r_f, dst_g_f, dst_b_f, &to_hsv_h, &to_hsv_s, &to_hsv_v); - float hs_dist = DeltaHS_BBS(from_hsv_h, from_hsv_s, from_hsv_v, to_hsv_h, to_hsv_s, to_hsv_v); - - // 1. Color difference is more obvious if the dest color has high luminance - // 2. Color difference is more obvious if the source color has low luminance - float from_lumi = get_luminance(src_r_f, src_g_f, src_b_f); - float to_lumi = get_luminance(dst_r_f, dst_g_f, dst_b_f); - float lumi_flush = 0.f; - if (to_lumi >= from_lumi) { - lumi_flush = std::pow(to_lumi - from_lumi, 0.7f) * 560.f; - } - else { - lumi_flush = (from_lumi - to_lumi) * 80.f; - - float inter_hsv_v = 0.67 * to_hsv_v + 0.33 * from_hsv_v; - hs_dist = std::min(inter_hsv_v, hs_dist); - } - float hs_flush = 230.f * hs_dist; - - float flush_volume = calc_triangle_3rd_edge(hs_flush, lumi_flush, 120.f); - flush_volume = std::max(flush_volume, 60.f); - - //float flush_multiplier = std::atof(m_flush_multiplier_ebox->GetValue().c_str()); flush_volume += m_min_flush_vol; return std::min((int)flush_volume, m_max_flush_vol); } diff --git a/src/libslic3r/FlushVolCalc.hpp b/src/libslic3r/FlushVolCalc.hpp index 630b11c6a..ed9da60b1 100644 --- a/src/libslic3r/FlushVolCalc.hpp +++ b/src/libslic3r/FlushVolCalc.hpp @@ -3,6 +3,7 @@ #include "libslic3r.h" #include "Config.hpp" +#include "FlushVolPredictor.hpp" namespace Slic3r { @@ -22,6 +23,10 @@ public: int calc_flush_vol(unsigned char src_a, unsigned char src_r, unsigned char src_g, unsigned char src_b, unsigned char dst_a, unsigned char dst_r, unsigned char dst_g, unsigned char dst_b); + + int calc_flush_vol_rgb(unsigned char src_r,unsigned char src_g,unsigned char src_b, + unsigned char dst_r, unsigned char dst_g, unsigned char dst_b); + private: int m_min_flush_vol; int m_max_flush_vol; diff --git a/src/libslic3r/FlushVolPredictor.cpp b/src/libslic3r/FlushVolPredictor.cpp new file mode 100644 index 000000000..d79fefb07 --- /dev/null +++ b/src/libslic3r/FlushVolPredictor.cpp @@ -0,0 +1,96 @@ +#include "FlushVolPredictor.hpp" +#include "Utils.hpp" +#include +#include + + +static bool rgb_hex_to_dec(const std::string& hexstr, unsigned char& r, unsigned char& g, unsigned char& b) +{ + if (hexstr.empty() || hexstr.length() != 7 || hexstr[0] != '#') + { + assert(false); + r = 0, g = 0, b = 0; + return false; + } + + auto hexToByte = [](const std::string& hex)->int + { + unsigned int byte; + std::istringstream(hex) >> std::hex >> byte; + return byte; + }; + r = hexToByte(hexstr.substr(1, 2)); + g = hexToByte(hexstr.substr(3, 2)); + b = hexToByte(hexstr.substr(5, 2)); + return true; +} + + +FlushVolPredictor::FlushVolPredictor(const std::string& data_file) +{ + std::ifstream in(data_file); + if (!in.is_open()) { + m_valid = false; + return; + } + std::string line; + getline(in, line); // skip the first line + while (std::getline(in, line)) { + std::istringstream iss(line); + std::string rgb_src, rgb_dst; + float value; + if (iss >> rgb_src >> rgb_dst >> value) { + unsigned char r_src = 0, g_src = 0, b_src = 0; + unsigned char r_dst = 0, g_dst = 0, b_dst = 0; + if (!rgb_hex_to_dec(rgb_src, r_src, g_src, b_src)) { + m_valid = false; + return; + } + if (!rgb_hex_to_dec(rgb_dst, r_dst, g_dst, b_dst)) { + m_valid = false; + return; + } + uint64_t key = 0; + key |= (static_cast(r_src) << 40); + key |= (static_cast(g_src) << 32); + key |= (static_cast(b_src) << 24); + key |= (static_cast(r_dst) << 16); + key |= (static_cast(g_dst) << 8); + key |= static_cast(b_dst); + m_flush_map.emplace(key, value); + } + else { + m_valid = false; + return; + } + } + m_valid = true; +} + +bool FlushVolPredictor::predict(const unsigned char src_r, const unsigned char src_g, const unsigned char src_b, const unsigned char dst_r, const unsigned char dst_g, const unsigned char dst_b, float& flush) +{ + if (!m_valid) + return false; + + uint64_t key = 0; + key |= (static_cast(src_r) << 40); + key |= (static_cast(src_g) << 32); + key |= (static_cast(src_b) << 24); + key |= (static_cast(dst_r) << 16); + key |= (static_cast(dst_g) << 8); + key |= static_cast(dst_b); + + auto iter = m_flush_map.find(key); + if (iter == m_flush_map.end()) + return false; + + flush = iter->second; + return true; +} + +FlushVolPredictor& FlushVolPredictor::get_instance() +{ + static std::string prefix = Slic3r::resources_dir(); + static FlushVolPredictor instance(prefix + "/flush/flush_data.txt"); + return instance; +} diff --git a/src/libslic3r/FlushVolPredictor.hpp b/src/libslic3r/FlushVolPredictor.hpp new file mode 100644 index 000000000..44a0d7caf --- /dev/null +++ b/src/libslic3r/FlushVolPredictor.hpp @@ -0,0 +1,22 @@ +#ifndef FLUSH_VOL_PREDICTOR_HPP +#define FLUSH_VOL_PREDICTOR_HPP + +#include + +class FlushVolPredictor +{ +public: + bool predict(const unsigned char src_r, const unsigned char src_g, const unsigned char src_b, + const unsigned char dst_r, const unsigned char dst_g, const unsigned char dst_b, float& flush); + static FlushVolPredictor& get_instance(); +private: + FlushVolPredictor(const std::string& data_file); + FlushVolPredictor(const FlushVolPredictor&) = delete; + FlushVolPredictor& operator=(const FlushVolPredictor&) = delete; + ~FlushVolPredictor() = default; +private: + std::unordered_map m_flush_map; + bool m_valid; +}; + +#endif \ No newline at end of file