diff options
Diffstat (limited to 'src/ipa/raspberrypi/controller/rpi/awb.hpp')
-rw-r--r-- | src/ipa/raspberrypi/controller/rpi/awb.hpp | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/src/ipa/raspberrypi/controller/rpi/awb.hpp b/src/ipa/raspberrypi/controller/rpi/awb.hpp new file mode 100644 index 00000000..36925252 --- /dev/null +++ b/src/ipa/raspberrypi/controller/rpi/awb.hpp @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2019, Raspberry Pi (Trading) Limited + * + * awb.hpp - AWB control algorithm + */ +#pragma once + +#include <mutex> +#include <condition_variable> +#include <thread> + +#include "../awb_algorithm.hpp" +#include "../pwl.hpp" +#include "../awb_status.h" + +namespace RPi { + +// Control algorithm to perform AWB calculations. + +struct AwbMode { + void Read(boost::property_tree::ptree const ¶ms); + double ct_lo; // low CT value for search + double ct_hi; // high CT value for search +}; + +struct AwbPrior { + void Read(boost::property_tree::ptree const ¶ms); + double lux; // lux level + Pwl prior; // maps CT to prior log likelihood for this lux level +}; + +struct AwbConfig { + AwbConfig() : default_mode(nullptr) {} + void Read(boost::property_tree::ptree const ¶ms); + // Only repeat the AWB calculation every "this many" frames + uint16_t frame_period; + // number of initial frames for which speed taken as 1.0 (maximum) + uint16_t startup_frames; + double speed; // IIR filter speed applied to algorithm results + bool fast; // "fast" mode uses a 16x16 rather than 32x32 grid + Pwl ct_r; // function maps CT to r (= R/G) + Pwl ct_b; // function maps CT to b (= B/G) + // table of illuminant priors at different lux levels + std::vector<AwbPrior> priors; + // AWB "modes" (determines the search range) + std::map<std::string, AwbMode> modes; + AwbMode *default_mode; // mode used if no mode selected + // minimum proportion of pixels counted within AWB region for it to be + // "useful" + double min_pixels; + // minimum G value of those pixels, to be regarded a "useful" + uint16_t min_G; + // number of AWB regions that must be "useful" in order to do the AWB + // calculation + uint32_t min_regions; + // clamp on colour error term (so as not to penalise non-grey excessively) + double delta_limit; + // step size control in coarse search + double coarse_step; + // how far to wander off CT curve towards "more purple" + double transverse_pos; + // how far to wander off CT curve towards "more green" + double transverse_neg; + // red sensitivity ratio (set to canonical sensor's R/G divided by this + // sensor's R/G) + double sensitivity_r; + // blue sensitivity ratio (set to canonical sensor's B/G divided by this + // sensor's B/G) + double sensitivity_b; + // The whitepoint (which we normally "aim" for) can be moved. + double whitepoint_r; + double whitepoint_b; + bool bayes; // use Bayesian algorithm +}; + +class Awb : public AwbAlgorithm +{ +public: + Awb(Controller *controller = NULL); + ~Awb(); + char const *Name() const override; + void Initialise() override; + void Read(boost::property_tree::ptree const ¶ms) override; + void SetMode(std::string const &name) override; + void SetManualGains(double manual_r, double manual_b) override; + void Prepare(Metadata *image_metadata) override; + void Process(StatisticsPtr &stats, Metadata *image_metadata) override; + struct RGB { + RGB(double _R = INVALID, double _G = INVALID, + double _B = INVALID) + : R(_R), G(_G), B(_B) + { + } + double R, G, B; + static const double INVALID; + bool Valid() const { return G != INVALID; } + bool Invalid() const { return G == INVALID; } + RGB &operator+=(RGB const &other) + { + R += other.R, G += other.G, B += other.B; + return *this; + } + RGB Square() const { return RGB(R * R, G * G, B * B); } + }; + +private: + // configuration is read-only, and available to both threads + AwbConfig config_; + std::thread async_thread_; + void asyncFunc(); // asynchronous thread function + std::mutex mutex_; + // condvar for async thread to wait on + std::condition_variable async_signal_; + // condvar for synchronous thread to wait on + std::condition_variable sync_signal_; + // for sync thread to check if async thread finished (requires mutex) + bool async_finished_; + // for async thread to check if it's been told to run (requires mutex) + bool async_start_; + // for async thread to check if it's been told to quit (requires mutex) + bool async_abort_; + + // The following are only for the synchronous thread to use: + // for sync thread to note its has asked async thread to run + bool async_started_; + // counts up to frame_period before restarting the async thread + int frame_phase_; + int frame_count_; // counts up to startup_frames + int frame_count2_; // counts up to startup_frames for Process method + AwbStatus sync_results_; + AwbStatus prev_sync_results_; + std::string mode_name_; + std::mutex settings_mutex_; + // The following are for the asynchronous thread to use, though the main + // thread can set/reset them if the async thread is known to be idle: + void restartAsync(StatisticsPtr &stats, std::string const &mode_name, + double lux); + // copy out the results from the async thread so that it can be restarted + void fetchAsyncResults(); + StatisticsPtr statistics_; + AwbMode *mode_; + double lux_; + AwbStatus async_results_; + void doAwb(); + void awbBayes(); + void awbGrey(); + void prepareStats(); + double computeDelta2Sum(double gain_r, double gain_b); + Pwl interpolatePrior(); + double coarseSearch(Pwl const &prior); + void fineSearch(double &t, double &r, double &b, Pwl const &prior); + std::vector<RGB> zones_; + std::vector<Pwl::Point> points_; + // manual r setting + double manual_r_; + // manual b setting + double manual_b_; +}; + +static inline Awb::RGB operator+(Awb::RGB const &a, Awb::RGB const &b) +{ + return Awb::RGB(a.R + b.R, a.G + b.G, a.B + b.B); +} +static inline Awb::RGB operator-(Awb::RGB const &a, Awb::RGB const &b) +{ + return Awb::RGB(a.R - b.R, a.G - b.G, a.B - b.B); +} +static inline Awb::RGB operator*(double d, Awb::RGB const &rgb) +{ + return Awb::RGB(d * rgb.R, d * rgb.G, d * rgb.B); +} +static inline Awb::RGB operator*(Awb::RGB const &rgb, double d) +{ + return d * rgb; +} + +} // namespace RPi |