From 9f3cc4df74bfb1035e085120eb19364ee0e43310 Mon Sep 17 00:00:00 2001 From: Nicolas Pope <nicolas.pope@utu.fi> Date: Sat, 22 Jun 2019 21:35:01 +0300 Subject: [PATCH] Implements #41 colour correction --- components/rgbd-sources/CMakeLists.txt | 1 + components/rgbd-sources/src/colour.cpp | 73 +++++++++++++++++++ components/rgbd-sources/src/colour.hpp | 15 ++++ components/rgbd-sources/src/net.cpp | 8 ++ components/rgbd-sources/src/net.hpp | 2 + .../rgbd-sources/src/snapshot_source.cpp | 7 ++ 6 files changed, 106 insertions(+) create mode 100644 components/rgbd-sources/src/colour.cpp create mode 100644 components/rgbd-sources/src/colour.hpp diff --git a/components/rgbd-sources/CMakeLists.txt b/components/rgbd-sources/CMakeLists.txt index 19aaf7458..96c709b6e 100644 --- a/components/rgbd-sources/CMakeLists.txt +++ b/components/rgbd-sources/CMakeLists.txt @@ -6,6 +6,7 @@ set(RGBDSRC src/stereovideo.cpp src/net.cpp src/streamer.cpp + src/colour.cpp # src/algorithms/rtcensus.cpp # src/algorithms/rtcensus_sgm.cpp # src/algorithms/opencv_sgbm.cpp diff --git a/components/rgbd-sources/src/colour.cpp b/components/rgbd-sources/src/colour.cpp new file mode 100644 index 000000000..c476ee8e2 --- /dev/null +++ b/components/rgbd-sources/src/colour.cpp @@ -0,0 +1,73 @@ +#include "colour.hpp" + +#include <vector> +#include <tuple> + +using std::vector; + +static void gammaCorrection(const cv::Mat &img, const double gamma_){ + using namespace cv; + + Mat lookUpTable(1, 256, CV_8U); + uchar* p = lookUpTable.ptr(); + for( int i = 0; i < 256; ++i) + p[i] = saturate_cast<uchar>(pow(i / 255.0, gamma_) * 255.0); + + Mat res = img.clone(); + LUT(img, lookUpTable, img); +} + +static const std::vector<std::tuple<uchar,uchar,uchar>> kelvin_table = { + {255,56,0}, // 1000 + {255,109,0}, // 1500 + {255,137,18}, // 2000 + {255,161,72}, // 2500 + {255,180,107}, // 3000 + {255,196,137}, // 3500 + {255,209,163}, // 4000 + {255,219,186}, // 4500 + {255,228,206}, // 5000 + {255,236,224}, // 5500 + {255,243,239}, // 6000 + {255,249,253}, // 6500 + {245,243,255}, // 7000 + {235,238,255}, // 7500 + {227,233,255}, // 8000 + {220,229,255}, // 8500 + {214,225,255}, // 9000 + {208,222,255}, // 9500 + {204,219,255}}; // 10000 + +template <int C> +inline float kelvinFactor(int temp) { + int index = (temp / 500) - 2; + if (index >= kelvin_table.size()) index = kelvin_table.size(); + else if (index < 0) index = 0; + return (float)std::get<C>(kelvin_table[index]) / 255.0f; +} + +void ftl::rgbd::colourCorrection(cv::Mat &img, float gamma, int temp) { + using namespace cv; + + Mat lutRed(1, 256, CV_8U); + Mat lutGreen(1, 256, CV_8U); + Mat lutBlue(1, 256, CV_8U); + + // TODO(Nick): Cache these lookup tables if used every frame... + uchar* pr = lutRed.ptr(); + uchar* pg = lutGreen.ptr(); + uchar* pb = lutBlue.ptr(); + for( int i = 0; i < 256; ++i) { + float g = pow(i / 255.0f, gamma) * 255.0f; + pr[i] = saturate_cast<uchar>(g * kelvinFactor<2>(temp)); + pg[i] = saturate_cast<uchar>(g * kelvinFactor<1>(temp)); + pb[i] = saturate_cast<uchar>(g * kelvinFactor<0>(temp)); + } + + vector<Mat> channels(3); + split(img, channels); + LUT(channels[0], lutBlue, channels[0]); + LUT(channels[1], lutGreen, channels[1]); + LUT(channels[2], lutRed, channels[2]); + merge(channels, img); +} diff --git a/components/rgbd-sources/src/colour.hpp b/components/rgbd-sources/src/colour.hpp new file mode 100644 index 000000000..be88853a5 --- /dev/null +++ b/components/rgbd-sources/src/colour.hpp @@ -0,0 +1,15 @@ +#ifndef _FTL_RGBD_COLOUR_HPP_ +#define _FTL_RGBD_COLOUR_HPP_ + +#include <opencv2/opencv.hpp> + +namespace ftl { +namespace rgbd { + +void colourCorrection(cv::Mat &img, float gamma, int temp); +// void colourCorrection(cv::GpuMat &img, float gamma, int temp); + +} +} + +#endif // _FTL_RGBD_COLOUR_HPP_ diff --git a/components/rgbd-sources/src/net.cpp b/components/rgbd-sources/src/net.cpp index 674bc2471..6f915f127 100644 --- a/components/rgbd-sources/src/net.cpp +++ b/components/rgbd-sources/src/net.cpp @@ -4,6 +4,8 @@ #include <chrono> #include <shared_mutex> +#include "colour.hpp" + #include <ftl/rgbd/streamer.hpp> using ftl::rgbd::detail::NetSource; @@ -46,6 +48,9 @@ bool NetSource::_getCalibration(Universe &net, const UUID &peer, const string &s NetSource::NetSource(ftl::rgbd::Source *host) : ftl::rgbd::detail::Source(host), active_(false) { + gamma_ = host->value("gamma", 1.0f); + temperature_ = host->value("temperature", 6500); + _updateURI(); h_ = host_->getNet()->onConnect([this](ftl::net::Peer *p) { @@ -90,6 +95,9 @@ void NetSource::_recvChunk(int frame, int chunk, bool delta, const vector<unsign cv::imdecode(jpg, cv::IMREAD_COLOR, &tmp_rgb); cv::imdecode(d, cv::IMREAD_UNCHANGED, &tmp_depth); + // Apply colour correction to chunk + ftl::rgbd::colourCorrection(tmp_rgb, gamma_, temperature_); + // Build chunk head int cx = (chunk % chunks_dim_) * chunk_width_; int cy = (chunk / chunks_dim_) * chunk_height_; diff --git a/components/rgbd-sources/src/net.hpp b/components/rgbd-sources/src/net.hpp index ce88d10c3..5a5639273 100644 --- a/components/rgbd-sources/src/net.hpp +++ b/components/rgbd-sources/src/net.hpp @@ -41,6 +41,8 @@ class NetSource : public detail::Source { int chunk_width_; int chunk_height_; cv::Mat idepth_; + float gamma_; + int temperature_; bool _getCalibration(ftl::net::Universe &net, const ftl::UUID &peer, const std::string &src, ftl::rgbd::Camera &p); void _recv(const std::vector<unsigned char> &jpg, const std::vector<unsigned char> &d); diff --git a/components/rgbd-sources/src/snapshot_source.cpp b/components/rgbd-sources/src/snapshot_source.cpp index 367fc2861..686e55b93 100644 --- a/components/rgbd-sources/src/snapshot_source.cpp +++ b/components/rgbd-sources/src/snapshot_source.cpp @@ -1,16 +1,23 @@ #include "snapshot_source.hpp" +#include "colour.hpp" +#include <loguru.hpp> #include <opencv2/opencv.hpp> #include <Eigen/Eigen> #include <opencv2/core/eigen.hpp> +#include <vector> using namespace ftl::rgbd; using ftl::rgbd::detail::SnapshotSource; using std::string; +using std::vector; SnapshotSource::SnapshotSource(ftl::rgbd::Source *host, SnapshotReader &reader, const string &id) : detail::Source(host) { Eigen::Matrix4d pose; reader.getCameraRGBD(id, rgb_, depth_, pose, params_); + + ftl::rgbd::colourCorrection(rgb_, host->value("gamma", 1.0f), host->value("temperature", 6500)); + setPose(pose); } -- GitLab