[libcamera-devel] [PATCH 07/15] DNI: ipa: raspberrypi: Code refactoring to match style guidelines
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Mon Jul 25 22:31:30 CEST 2022
Hi Naush,
Thank you for the patch.
On Mon, Jul 25, 2022 at 02:46:31PM +0100, Naushir Patuck via libcamera-devel wrote:
> Refactor the source files under src/ipa/raspberrypi/controller/rpi/a* to match the
> recommended formatting guidelines for the libcamera project. The vast majority
> of changes in this commit comprise of switching from snake_case to CamelCase,
> and starting class member functions with a lower case character.
>
> Signed-off-by: Naushir Patuck <naush at raspberrypi.com>
>
> Signed-off-by: Naushir Patuck <naush at raspberrypi.com>
One is enough.
> ---
> src/ipa/raspberrypi/controller/rpi/agc.cpp | 722 ++++++++++----------
> src/ipa/raspberrypi/controller/rpi/agc.hpp | 130 ++--
> src/ipa/raspberrypi/controller/rpi/alsc.cpp | 639 ++++++++---------
> src/ipa/raspberrypi/controller/rpi/alsc.hpp | 86 +--
> src/ipa/raspberrypi/controller/rpi/awb.cpp | 562 ++++++++-------
> src/ipa/raspberrypi/controller/rpi/awb.hpp | 110 +--
> 6 files changed, 1089 insertions(+), 1160 deletions(-)
>
> diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp
> index f6a9cb0a2cd8..738cf56c6be0 100644
> --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp
> +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp
> @@ -30,7 +30,7 @@ LOG_DEFINE_CATEGORY(RPiAgc)
>
> #define PIPELINE_BITS 13 // seems to be a 13-bit pipeline
This could also be switched to static constexpr.
> -void AgcMeteringMode::Read(boost::property_tree::ptree const ¶ms)
> +void AgcMeteringMode::read(boost::property_tree::ptree const ¶ms)
> {
> int num = 0;
> for (auto &p : params.get_child("weights")) {
> @@ -43,265 +43,260 @@ void AgcMeteringMode::Read(boost::property_tree::ptree const ¶ms)
> }
>
> static std::string
> -read_metering_modes(std::map<std::string, AgcMeteringMode> &metering_modes,
> - boost::property_tree::ptree const ¶ms)
> +readMeteringModes(std::map<std::string, AgcMeteringMode> &meteringModes,
> + boost::property_tree::ptree const ¶ms)
> {
> std::string first;
> for (auto &p : params) {
> - AgcMeteringMode metering_mode;
> - metering_mode.Read(p.second);
> - metering_modes[p.first] = std::move(metering_mode);
> + AgcMeteringMode meteringMode;
> + meteringMode.read(p.second);
> + meteringModes[p.first] = std::move(meteringMode);
> if (first.empty())
> first = p.first;
> }
> return first;
> }
>
> -static int read_list(std::vector<double> &list,
> - boost::property_tree::ptree const ¶ms)
> +static int readList(std::vector<double> &list,
> + boost::property_tree::ptree const ¶ms)
> {
> for (auto &p : params)
> list.push_back(p.second.get_value<double>());
> return list.size();
> }
>
> -static int read_list(std::vector<Duration> &list,
> - boost::property_tree::ptree const ¶ms)
> +static int readList(std::vector<Duration> &list,
> + boost::property_tree::ptree const ¶ms)
> {
> for (auto &p : params)
> list.push_back(p.second.get_value<double>() * 1us);
> return list.size();
> }
>
> -void AgcExposureMode::Read(boost::property_tree::ptree const ¶ms)
> +void AgcExposureMode::read(boost::property_tree::ptree const ¶ms)
> {
> - int num_shutters = read_list(shutter, params.get_child("shutter"));
> - int num_ags = read_list(gain, params.get_child("gain"));
> - if (num_shutters < 2 || num_ags < 2)
> + int numShutters = readList(shutter, params.get_child("shutter"));
> + int numAgs = readList(gain, params.get_child("gain"));
> + if (numShutters < 2 || numAgs < 2)
> throw std::runtime_error(
> "AgcConfig: must have at least two entries in exposure profile");
> - if (num_shutters != num_ags)
> + if (numShutters != numAgs)
> throw std::runtime_error(
> "AgcConfig: expect same number of exposure and gain entries in exposure profile");
> }
>
> static std::string
> -read_exposure_modes(std::map<std::string, AgcExposureMode> &exposure_modes,
> - boost::property_tree::ptree const ¶ms)
> +readExposureModes(std::map<std::string, AgcExposureMode> &exposureModes,
> + boost::property_tree::ptree const ¶ms)
> {
> std::string first;
> for (auto &p : params) {
> - AgcExposureMode exposure_mode;
> - exposure_mode.Read(p.second);
> - exposure_modes[p.first] = std::move(exposure_mode);
> + AgcExposureMode exposureMode;
> + exposureMode.read(p.second);
> + exposureModes[p.first] = std::move(exposureMode);
> if (first.empty())
> first = p.first;
> }
> return first;
> }
>
> -void AgcConstraint::Read(boost::property_tree::ptree const ¶ms)
> +void AgcConstraint::read(boost::property_tree::ptree const ¶ms)
> {
> - std::string bound_string = params.get<std::string>("bound", "");
> - transform(bound_string.begin(), bound_string.end(),
> - bound_string.begin(), ::toupper);
> - if (bound_string != "UPPER" && bound_string != "LOWER")
> + std::string boundString = params.get<std::string>("bound", "");
> + transform(boundString.begin(), boundString.end(),
> + boundString.begin(), ::toupper);
> + if (boundString != "UPPER" && boundString != "LOWER")
> throw std::runtime_error(
> "AGC constraint type should be UPPER or LOWER");
> - bound = bound_string == "UPPER" ? Bound::UPPER : Bound::LOWER;
> - q_lo = params.get<double>("q_lo");
> - q_hi = params.get<double>("q_hi");
> - Y_target.Read(params.get_child("y_target"));
> + bound = boundString == "UPPER" ? Bound::UPPER : Bound::LOWER;
> + qLo = params.get<double>("q_lo");
> + qHi = params.get<double>("q_hi");
> + yTarget.read(params.get_child("y_target"));
> }
>
> static AgcConstraintMode
> -read_constraint_mode(boost::property_tree::ptree const ¶ms)
> +readConstraintMode(boost::property_tree::ptree const ¶ms)
> {
> AgcConstraintMode mode;
> for (auto &p : params) {
> AgcConstraint constraint;
> - constraint.Read(p.second);
> + constraint.read(p.second);
> mode.push_back(std::move(constraint));
> }
> return mode;
> }
>
> -static std::string read_constraint_modes(
> - std::map<std::string, AgcConstraintMode> &constraint_modes,
> - boost::property_tree::ptree const ¶ms)
> +static std::string readConstraintModes(std::map<std::string, AgcConstraintMode> &constraintModes,
> + boost::property_tree::ptree const ¶ms)
> {
> std::string first;
> for (auto &p : params) {
> - constraint_modes[p.first] = read_constraint_mode(p.second);
> + constraintModes[p.first] = readConstraintMode(p.second);
> if (first.empty())
> first = p.first;
> }
> return first;
> }
>
> -void AgcConfig::Read(boost::property_tree::ptree const ¶ms)
> +void AgcConfig::read(boost::property_tree::ptree const ¶ms)
> {
> LOG(RPiAgc, Debug) << "AgcConfig";
> - default_metering_mode = read_metering_modes(
> - metering_modes, params.get_child("metering_modes"));
> - default_exposure_mode = read_exposure_modes(
> - exposure_modes, params.get_child("exposure_modes"));
> - default_constraint_mode = read_constraint_modes(
> - constraint_modes, params.get_child("constraint_modes"));
> - Y_target.Read(params.get_child("y_target"));
> + defaultMeteringMode = readMeteringModes(meteringModes, params.get_child("metering_modes"));
> + defaultExposureMode = readExposureModes(exposureModes, params.get_child("exposure_modes"));
> + defaultConstraintMode = readConstraintModes(constraintModes, params.get_child("constraint_modes"));
> + yTarget.read(params.get_child("y_target"));
> speed = params.get<double>("speed", 0.2);
> - startup_frames = params.get<uint16_t>("startup_frames", 10);
> - convergence_frames = params.get<unsigned int>("convergence_frames", 6);
> - fast_reduce_threshold =
> - params.get<double>("fast_reduce_threshold", 0.4);
> - base_ev = params.get<double>("base_ev", 1.0);
> + startupFrames = params.get<uint16_t>("startup_frames", 10);
> + convergenceFrames = params.get<unsigned int>("convergence_frames", 6);
> + fastReduceThreshold = params.get<double>("fast_reduce_threshold", 0.4);
> + baseEv = params.get<double>("base_ev", 1.0);
> // Start with quite a low value as ramping up is easier than ramping down.
> - default_exposure_time = params.get<double>("default_exposure_time", 1000) * 1us;
> - default_analogue_gain = params.get<double>("default_analogue_gain", 1.0);
> + defaultExposureTime = params.get<double>("default_exposure_time", 1000) * 1us;
> + defaultAnalogueGain = params.get<double>("default_analogueGain", 1.0);
> }
>
> Agc::ExposureValues::ExposureValues()
> - : shutter(0s), analogue_gain(0),
> - total_exposure(0s), total_exposure_no_dg(0s)
> + : shutter(0s), analogueGain(0),
> + totalExposure(0s), totalExposureNoDG(0s)
> {
> }
>
> Agc::Agc(Controller *controller)
> - : AgcAlgorithm(controller), metering_mode_(nullptr),
> - exposure_mode_(nullptr), constraint_mode_(nullptr),
> - frame_count_(0), lock_count_(0),
> - last_target_exposure_(0s), last_sensitivity_(0.0),
> - ev_(1.0), flicker_period_(0s),
> - max_shutter_(0s), fixed_shutter_(0s), fixed_analogue_gain_(0.0)
> + : AgcAlgorithm(controller), meteringMode_(nullptr),
> + exposureMode_(nullptr), constraintMode_(nullptr),
> + frameCount_(0), lockCount_(0),
> + lastTargetExposure_(0s), lastSensitivity_(0.0),
> + ev_(1.0), flickerPeriod_(0s),
> + maxShutter_(0s), fixedShutter_(0s), fixedAnalogueGain_(0.0)
> {
> memset(&awb_, 0, sizeof(awb_));
> - // Setting status_.total_exposure_value_ to zero initially tells us
> + // Setting status_.totalExposureValue_ to zero initially tells us
> // it's not been calculated yet (i.e. Process hasn't yet run).
> memset(&status_, 0, sizeof(status_));
> status_.ev = ev_;
> }
>
> -char const *Agc::Name() const
> +char const *Agc::name() const
> {
> return NAME;
> }
>
> -void Agc::Read(boost::property_tree::ptree const ¶ms)
> +void Agc::read(boost::property_tree::ptree const ¶ms)
> {
> LOG(RPiAgc, Debug) << "Agc";
> - config_.Read(params);
> + config_.read(params);
> // Set the config's defaults (which are the first ones it read) as our
> // current modes, until someone changes them. (they're all known to
> // exist at this point)
> - metering_mode_name_ = config_.default_metering_mode;
> - metering_mode_ = &config_.metering_modes[metering_mode_name_];
> - exposure_mode_name_ = config_.default_exposure_mode;
> - exposure_mode_ = &config_.exposure_modes[exposure_mode_name_];
> - constraint_mode_name_ = config_.default_constraint_mode;
> - constraint_mode_ = &config_.constraint_modes[constraint_mode_name_];
> + meteringModeName_ = config_.defaultMeteringMode;
> + meteringMode_ = &config_.meteringModes[meteringModeName_];
> + exposureModeName_ = config_.defaultExposureMode;
> + exposureMode_ = &config_.exposureModes[exposureModeName_];
> + constraintModeName_ = config_.defaultConstraintMode;
> + constraintMode_ = &config_.constraintModes[constraintModeName_];
> // Set up the "last shutter/gain" values, in case AGC starts "disabled".
> - status_.shutter_time = config_.default_exposure_time;
> - status_.analogue_gain = config_.default_analogue_gain;
> + status_.shutterTime = config_.defaultExposureTime;
> + status_.analogueGain = config_.defaultAnalogueGain;
> }
>
> -bool Agc::IsPaused() const
> +bool Agc::isPaused() const
> {
> return false;
> }
>
> -void Agc::Pause()
> +void Agc::pause()
> {
> - fixed_shutter_ = status_.shutter_time;
> - fixed_analogue_gain_ = status_.analogue_gain;
> + fixedShutter_ = status_.shutterTime;
> + fixedAnalogueGain_ = status_.analogueGain;
> }
>
> -void Agc::Resume()
> +void Agc::resume()
> {
> - fixed_shutter_ = 0s;
> - fixed_analogue_gain_ = 0;
> + fixedShutter_ = 0s;
> + fixedAnalogueGain_ = 0;
> }
>
> -unsigned int Agc::GetConvergenceFrames() const
> +unsigned int Agc::getConvergenceFrames() const
> {
> // If shutter and gain have been explicitly set, there is no
> // convergence to happen, so no need to drop any frames - return zero.
> - if (fixed_shutter_ && fixed_analogue_gain_)
> + if (fixedShutter_ && fixedAnalogueGain_)
> return 0;
> else
> - return config_.convergence_frames;
> + return config_.convergenceFrames;
> }
>
> -void Agc::SetEv(double ev)
> +void Agc::setEv(double ev)
> {
> ev_ = ev;
> }
>
> -void Agc::SetFlickerPeriod(Duration flicker_period)
> +void Agc::setFlickerPeriod(Duration flickerPeriod)
> {
> - flicker_period_ = flicker_period;
> + flickerPeriod_ = flickerPeriod;
> }
>
> -void Agc::SetMaxShutter(Duration max_shutter)
> +void Agc::setMaxShutter(Duration maxShutter)
> {
> - max_shutter_ = max_shutter;
> + maxShutter_ = maxShutter;
> }
>
> -void Agc::SetFixedShutter(Duration fixed_shutter)
> +void Agc::setFixedShutter(Duration fixedShutter)
> {
> - fixed_shutter_ = fixed_shutter;
> + fixedShutter_ = fixedShutter;
> // Set this in case someone calls Pause() straight after.
> - status_.shutter_time = clipShutter(fixed_shutter_);
> + status_.shutterTime = clipShutter(fixedShutter_);
> }
>
> -void Agc::SetFixedAnalogueGain(double fixed_analogue_gain)
> +void Agc::setFixedAnalogueGain(double fixedAnalogueGain)
> {
> - fixed_analogue_gain_ = fixed_analogue_gain;
> + fixedAnalogueGain_ = fixedAnalogueGain_;
> // Set this in case someone calls Pause() straight after.
> - status_.analogue_gain = fixed_analogue_gain;
> + status_.analogueGain = fixedAnalogueGain;
> }
>
> -void Agc::SetMeteringMode(std::string const &metering_mode_name)
> +void Agc::setMeteringMode(std::string const &meteringModeName)
> {
> - metering_mode_name_ = metering_mode_name;
> + meteringModeName_ = meteringModeName;
> }
>
> -void Agc::SetExposureMode(std::string const &exposure_mode_name)
> +void Agc::setExposureMode(std::string const &exposureModeName)
> {
> - exposure_mode_name_ = exposure_mode_name;
> + exposureModeName_ = exposureModeName;
> }
>
> -void Agc::SetConstraintMode(std::string const &constraint_mode_name)
> +void Agc::setConstraintMode(std::string const &constraintModeName)
> {
> - constraint_mode_name_ = constraint_mode_name;
> + constraintModeName_ = constraintModeName;
> }
>
> -void Agc::SwitchMode(CameraMode const &camera_mode,
> +void Agc::switchMode(CameraMode const &cameraMode,
> Metadata *metadata)
> {
> /* AGC expects the mode sensitivity always to be non-zero. */
> - ASSERT(camera_mode.sensitivity);
> + ASSERT(cameraMode.sensitivity);
>
> housekeepConfig();
>
> - Duration fixed_shutter = clipShutter(fixed_shutter_);
> - if (fixed_shutter && fixed_analogue_gain_) {
> + Duration fixedShutter = clipShutter(fixedShutter_);
> + if (fixedShutter && fixedAnalogueGain_) {
> // We're going to reset the algorithm here with these fixed values.
>
> fetchAwbStatus(metadata);
> - double min_colour_gain = std::min({ awb_.gain_r, awb_.gain_g, awb_.gain_b, 1.0 });
> - ASSERT(min_colour_gain != 0.0);
> + double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 });
> + ASSERT(minColourGain != 0.0);
>
> // This is the equivalent of computeTargetExposure and applyDigitalGain.
> - target_.total_exposure_no_dg = fixed_shutter * fixed_analogue_gain_;
> - target_.total_exposure = target_.total_exposure_no_dg / min_colour_gain;
> + target_.totalExposureNoDG = fixedShutter_ * fixedAnalogueGain_;
> + target_.totalExposure = target_.totalExposureNoDG / minColourGain;
>
> // Equivalent of filterExposure. This resets any "history".
> filtered_ = target_;
>
> // Equivalent of divideUpExposure.
> - filtered_.shutter = fixed_shutter;
> - filtered_.analogue_gain = fixed_analogue_gain_;
> - } else if (status_.total_exposure_value) {
> + filtered_.shutter = fixedShutter;
> + filtered_.analogueGain = fixedAnalogueGain_;
> + } else if (status_.totalExposureValue) {
> // On a mode switch, various things could happen:
> // - the exposure profile might change
> // - a fixed exposure or gain might be set
> @@ -310,11 +305,11 @@ void Agc::SwitchMode(CameraMode const &camera_mode,
> // that we just need to re-divide the exposure/gain according to the
> // current exposure profile, which takes care of everything else.
>
> - double ratio = last_sensitivity_ / camera_mode.sensitivity;
> - target_.total_exposure_no_dg *= ratio;
> - target_.total_exposure *= ratio;
> - filtered_.total_exposure_no_dg *= ratio;
> - filtered_.total_exposure *= ratio;
> + double ratio = lastSensitivity_ / cameraMode.sensitivity;
> + target_.totalExposureNoDG *= ratio;
> + target_.totalExposure *= ratio;
> + filtered_.totalExposureNoDG *= ratio;
> + filtered_.totalExposure *= ratio;
>
> divideUpExposure();
> } else {
> @@ -324,114 +319,110 @@ void Agc::SwitchMode(CameraMode const &camera_mode,
> // for any that weren't set.
>
> // Equivalent of divideUpExposure.
> - filtered_.shutter = fixed_shutter ? fixed_shutter : config_.default_exposure_time;
> - filtered_.analogue_gain = fixed_analogue_gain_ ? fixed_analogue_gain_ : config_.default_analogue_gain;
> + filtered_.shutter = fixedShutter ? fixedShutter : config_.defaultExposureTime;
> + filtered_.analogueGain = fixedAnalogueGain_ ? fixedAnalogueGain_ : config_.defaultAnalogueGain;
> }
>
> writeAndFinish(metadata, false);
>
> // We must remember the sensitivity of this mode for the next SwitchMode.
> - last_sensitivity_ = camera_mode.sensitivity;
> + lastSensitivity_ = cameraMode.sensitivity;
> }
>
> -void Agc::Prepare(Metadata *image_metadata)
> +void Agc::prepare(Metadata *imageMetadata)
> {
> - status_.digital_gain = 1.0;
> - fetchAwbStatus(image_metadata); // always fetch it so that Process knows it's been done
> + status_.digitalGain = 1.0;
> + fetchAwbStatus(imageMetadata); // always fetch it so that Process knows it's been done
>
> - if (status_.total_exposure_value) {
> + if (status_.totalExposureValue) {
> // Process has run, so we have meaningful values.
> - DeviceStatus device_status;
> - if (image_metadata->Get("device.status", device_status) == 0) {
> - Duration actual_exposure = device_status.shutter_speed *
> - device_status.analogue_gain;
> - if (actual_exposure) {
> - status_.digital_gain =
> - status_.total_exposure_value /
> - actual_exposure;
> - LOG(RPiAgc, Debug) << "Want total exposure " << status_.total_exposure_value;
> + DeviceStatus deviceStatus;
> + if (imageMetadata->get("device.status", deviceStatus) == 0) {
> + Duration actualExposure = deviceStatus.shutterSpeed *
> + deviceStatus.analogueGain;
> + if (actualExposure) {
> + status_.digitalGain = status_.totalExposureValue / actualExposure;
> + LOG(RPiAgc, Debug) << "Want total exposure " << status_.totalExposureValue;
> // Never ask for a gain < 1.0, and also impose
> // some upper limit. Make it customisable?
> - status_.digital_gain = std::max(
> - 1.0,
> - std::min(status_.digital_gain, 4.0));
> - LOG(RPiAgc, Debug) << "Actual exposure " << actual_exposure;
> - LOG(RPiAgc, Debug) << "Use digital_gain " << status_.digital_gain;
> + status_.digitalGain = std::max(1.0, std::min(status_.digitalGain, 4.0));
> + LOG(RPiAgc, Debug) << "Actual exposure " << actualExposure;
> + LOG(RPiAgc, Debug) << "Use digital_gain " << status_.digitalGain;
s/digital_gain/digitalGain/
> LOG(RPiAgc, Debug) << "Effective exposure "
> - << actual_exposure * status_.digital_gain;
> + << actualExposure * status_.digitalGain;
> // Decide whether AEC/AGC has converged.
> - updateLockStatus(device_status);
> + updateLockStatus(deviceStatus);
> }
> } else
> - LOG(RPiAgc, Warning) << Name() << ": no device metadata";
> - image_metadata->Set("agc.status", status_);
> + LOG(RPiAgc, Warning) << name() << ": no device metadata";
> + imageMetadata->set("agc.status", status_);
> }
> }
>
> -void Agc::Process(StatisticsPtr &stats, Metadata *image_metadata)
> +void Agc::process(StatisticsPtr &stats, Metadata *imageMetadata)
> {
> - frame_count_++;
> + frameCount_++;
> // First a little bit of housekeeping, fetching up-to-date settings and
> // configuration, that kind of thing.
> housekeepConfig();
> // Get the current exposure values for the frame that's just arrived.
> - fetchCurrentExposure(image_metadata);
> + fetchCurrentExposure(imageMetadata);
> // Compute the total gain we require relative to the current exposure.
> - double gain, target_Y;
> - computeGain(stats.get(), image_metadata, gain, target_Y);
> + double gain, targetY;
> + computeGain(stats.get(), imageMetadata, gain, targetY);
> // Now compute the target (final) exposure which we think we want.
> computeTargetExposure(gain);
> // Some of the exposure has to be applied as digital gain, so work out
> // what that is. This function also tells us whether it's decided to
> // "desaturate" the image more quickly.
> - bool desaturate = applyDigitalGain(gain, target_Y);
> + bool desaturate = applyDigitalGain(gain, targetY);
> // The results have to be filtered so as not to change too rapidly.
> filterExposure(desaturate);
> // The last thing is to divide up the exposure value into a shutter time
> - // and analogue_gain, according to the current exposure mode.
> + // and analogue gain, according to the current exposure mode.
> divideUpExposure();
> // Finally advertise what we've done.
> - writeAndFinish(image_metadata, desaturate);
> + writeAndFinish(imageMetadata, desaturate);
> }
>
> -void Agc::updateLockStatus(DeviceStatus const &device_status)
> +void Agc::updateLockStatus(DeviceStatus const &deviceStatus)
> {
> - const double ERROR_FACTOR = 0.10; // make these customisable?
> - const int MAX_LOCK_COUNT = 5;
> - // Reset "lock count" when we exceed this multiple of ERROR_FACTOR
> - const double RESET_MARGIN = 1.5;
> + const double errorFactor = 0.10; // make these customisable?
> + const int maxLockCount = 5;
> + // Reset "lock count" when we exceed this multiple of errorFactor
> + const double resetMargin = 1.5;
>
> // Add 200us to the exposure time error to allow for line quantisation.
> - Duration exposure_error = last_device_status_.shutter_speed * ERROR_FACTOR + 200us;
> - double gain_error = last_device_status_.analogue_gain * ERROR_FACTOR;
> - Duration target_error = last_target_exposure_ * ERROR_FACTOR;
> + Duration exposureError = lastDeviceStatus_.shutterSpeed * errorFactor + 200us;
> + double gainError = lastDeviceStatus_.analogueGain * errorFactor;
> + Duration targetError = lastTargetExposure_ * errorFactor;
>
> // Note that we don't know the exposure/gain limits of the sensor, so
> // the values we keep requesting may be unachievable. For this reason
> // we only insist that we're close to values in the past few frames.
> - if (device_status.shutter_speed > last_device_status_.shutter_speed - exposure_error &&
> - device_status.shutter_speed < last_device_status_.shutter_speed + exposure_error &&
> - device_status.analogue_gain > last_device_status_.analogue_gain - gain_error &&
> - device_status.analogue_gain < last_device_status_.analogue_gain + gain_error &&
> - status_.target_exposure_value > last_target_exposure_ - target_error &&
> - status_.target_exposure_value < last_target_exposure_ + target_error)
> - lock_count_ = std::min(lock_count_ + 1, MAX_LOCK_COUNT);
> - else if (device_status.shutter_speed < last_device_status_.shutter_speed - RESET_MARGIN * exposure_error ||
> - device_status.shutter_speed > last_device_status_.shutter_speed + RESET_MARGIN * exposure_error ||
> - device_status.analogue_gain < last_device_status_.analogue_gain - RESET_MARGIN * gain_error ||
> - device_status.analogue_gain > last_device_status_.analogue_gain + RESET_MARGIN * gain_error ||
> - status_.target_exposure_value < last_target_exposure_ - RESET_MARGIN * target_error ||
> - status_.target_exposure_value > last_target_exposure_ + RESET_MARGIN * target_error)
> - lock_count_ = 0;
> -
> - last_device_status_ = device_status;
> - last_target_exposure_ = status_.target_exposure_value;
> -
> - LOG(RPiAgc, Debug) << "Lock count updated to " << lock_count_;
> - status_.locked = lock_count_ == MAX_LOCK_COUNT;
> -}
> -
> -static void copy_string(std::string const &s, char *d, size_t size)
> + if (deviceStatus.shutterSpeed > lastDeviceStatus_.shutterSpeed - exposureError &&
> + deviceStatus.shutterSpeed < lastDeviceStatus_.shutterSpeed + exposureError &&
> + deviceStatus.analogueGain > lastDeviceStatus_.analogueGain - gainError &&
> + deviceStatus.analogueGain < lastDeviceStatus_.analogueGain + gainError &&
> + status_.targetExposureValue > lastTargetExposure_ - targetError &&
> + status_.targetExposureValue < lastTargetExposure_ + targetError)
> + lockCount_ = std::min(lockCount_ + 1, maxLockCount);
> + else if (deviceStatus.shutterSpeed < lastDeviceStatus_.shutterSpeed - resetMargin * exposureError ||
> + deviceStatus.shutterSpeed > lastDeviceStatus_.shutterSpeed + resetMargin * exposureError ||
> + deviceStatus.analogueGain < lastDeviceStatus_.analogueGain - resetMargin * gainError ||
> + deviceStatus.analogueGain > lastDeviceStatus_.analogueGain + resetMargin * gainError ||
> + status_.targetExposureValue < lastTargetExposure_ - resetMargin * targetError ||
> + status_.targetExposureValue > lastTargetExposure_ + resetMargin * targetError)
> + lockCount_ = 0;
> +
> + lastDeviceStatus_ = deviceStatus;
> + lastTargetExposure_ = status_.targetExposureValue;
> +
> + LOG(RPiAgc, Debug) << "Lock count updated to " << lockCount_;
> + status_.locked = lockCount_ == maxLockCount;
> +}
> +
> +static void copyString(std::string const &s, char *d, size_t size)
> {
> size_t length = s.copy(d, size - 1);
> d[length] = '\0';
> @@ -441,97 +432,97 @@ void Agc::housekeepConfig()
> {
> // First fetch all the up-to-date settings, so no one else has to do it.
> status_.ev = ev_;
> - status_.fixed_shutter = clipShutter(fixed_shutter_);
> - status_.fixed_analogue_gain = fixed_analogue_gain_;
> - status_.flicker_period = flicker_period_;
> - LOG(RPiAgc, Debug) << "ev " << status_.ev << " fixed_shutter "
> - << status_.fixed_shutter << " fixed_analogue_gain "
> - << status_.fixed_analogue_gain;
> + status_.fixedShutter = clipShutter(fixedShutter_);
> + status_.fixedAnalogueGain = fixedAnalogueGain_;
> + status_.flickerPeriod = flickerPeriod_;
> + LOG(RPiAgc, Debug) << "ev " << status_.ev << " fixedShutter "
> + << status_.fixedShutter << " fixedAnalogueGain "
> + << status_.fixedAnalogueGain;
> // Make sure the "mode" pointers point to the up-to-date things, if
> // they've changed.
> - if (strcmp(metering_mode_name_.c_str(), status_.metering_mode)) {
> - auto it = config_.metering_modes.find(metering_mode_name_);
> - if (it == config_.metering_modes.end())
> + if (strcmp(meteringModeName_.c_str(), status_.meteringMode)) {
> + auto it = config_.meteringModes.find(meteringModeName_);
> + if (it == config_.meteringModes.end())
> throw std::runtime_error("Agc: no metering mode " +
> - metering_mode_name_);
> - metering_mode_ = &it->second;
> - copy_string(metering_mode_name_, status_.metering_mode,
> - sizeof(status_.metering_mode));
> + meteringModeName_);
> + meteringMode_ = &it->second;
> + copyString(meteringModeName_, status_.meteringMode,
> + sizeof(status_.meteringMode));
> }
> - if (strcmp(exposure_mode_name_.c_str(), status_.exposure_mode)) {
> - auto it = config_.exposure_modes.find(exposure_mode_name_);
> - if (it == config_.exposure_modes.end())
> + if (strcmp(exposureModeName_.c_str(), status_.exposureMode)) {
> + auto it = config_.exposureModes.find(exposureModeName_);
> + if (it == config_.exposureModes.end())
> throw std::runtime_error("Agc: no exposure profile " +
> - exposure_mode_name_);
> - exposure_mode_ = &it->second;
> - copy_string(exposure_mode_name_, status_.exposure_mode,
> - sizeof(status_.exposure_mode));
> + exposureModeName_);
> + exposureMode_ = &it->second;
> + copyString(exposureModeName_, status_.exposureMode,
> + sizeof(status_.exposureMode));
> }
> - if (strcmp(constraint_mode_name_.c_str(), status_.constraint_mode)) {
> + if (strcmp(constraintModeName_.c_str(), status_.constraint_mode)) {
AgcStatus::constraint_mode should also be renamed to constraintMode.
> auto it =
> - config_.constraint_modes.find(constraint_mode_name_);
> - if (it == config_.constraint_modes.end())
> + config_.constraintModes.find(constraintModeName_);
> + if (it == config_.constraintModes.end())
> throw std::runtime_error("Agc: no constraint list " +
> - constraint_mode_name_);
> - constraint_mode_ = &it->second;
> - copy_string(constraint_mode_name_, status_.constraint_mode,
> - sizeof(status_.constraint_mode));
> + constraintModeName_);
> + constraintMode_ = &it->second;
> + copyString(constraintModeName_, status_.constraint_mode,
> + sizeof(status_.constraint_mode));
> }
> - LOG(RPiAgc, Debug) << "exposure_mode "
> - << exposure_mode_name_ << " constraint_mode "
> - << constraint_mode_name_ << " metering_mode "
> - << metering_mode_name_;
> + LOG(RPiAgc, Debug) << "exposureMode "
> + << exposureModeName_ << " constraint_mode "
> + << constraintModeName_ << " meteringMode "
> + << meteringModeName_;
> }
>
> -void Agc::fetchCurrentExposure(Metadata *image_metadata)
> +void Agc::fetchCurrentExposure(Metadata *imageMetadata)
> {
> - std::unique_lock<Metadata> lock(*image_metadata);
> - DeviceStatus *device_status =
> - image_metadata->GetLocked<DeviceStatus>("device.status");
> - if (!device_status)
> + std::unique_lock<Metadata> lock(*imageMetadata);
> + DeviceStatus *deviceStatus =
> + imageMetadata->getLocked<DeviceStatus>("device.status");
> + if (!deviceStatus)
> throw std::runtime_error("Agc: no device metadata");
> - current_.shutter = device_status->shutter_speed;
> - current_.analogue_gain = device_status->analogue_gain;
> - AgcStatus *agc_status =
> - image_metadata->GetLocked<AgcStatus>("agc.status");
> - current_.total_exposure = agc_status ? agc_status->total_exposure_value : 0s;
> - current_.total_exposure_no_dg = current_.shutter * current_.analogue_gain;
> + current_.shutter = deviceStatus->shutterSpeed;
> + current_.analogueGain = deviceStatus->analogueGain;
> + AgcStatus *agcStatus =
> + imageMetadata->getLocked<AgcStatus>("agc.status");
> + current_.totalExposure = agcStatus ? agcStatus->totalExposureValue : 0s;
> + current_.totalExposureNoDG = current_.shutter * current_.analogueGain;
> }
>
> -void Agc::fetchAwbStatus(Metadata *image_metadata)
> +void Agc::fetchAwbStatus(Metadata *imageMetadata)
> {
> - awb_.gain_r = 1.0; // in case not found in metadata
> - awb_.gain_g = 1.0;
> - awb_.gain_b = 1.0;
> - if (image_metadata->Get("awb.status", awb_) != 0)
> + awb_.gainR = 1.0; // in case not found in metadata
> + awb_.gainG = 1.0;
> + awb_.gainB = 1.0;
> + if (imageMetadata->get("awb.status", awb_) != 0)
> LOG(RPiAgc, Debug) << "Agc: no AWB status found";
> }
>
> -static double compute_initial_Y(bcm2835_isp_stats *stats, AwbStatus const &awb,
> - double weights[], double gain)
> +static double computeInitialY(bcm2835_isp_stats *stats, AwbStatus const &awb,
> + double weights[], double gain)
> {
> bcm2835_isp_stats_region *regions = stats->agc_stats;
> // Note how the calculation below means that equal weights give you
> // "average" metering (i.e. all pixels equally important).
> - double R_sum = 0, G_sum = 0, B_sum = 0, pixel_sum = 0;
> + double rSum = 0, gSum = 0, bSum = 0, pixelSum = 0;
> for (int i = 0; i < AGC_STATS_SIZE; i++) {
> double counted = regions[i].counted;
> - double r_sum = std::min(regions[i].r_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);
> - double g_sum = std::min(regions[i].g_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);
> - double b_sum = std::min(regions[i].b_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);
> - R_sum += r_sum * weights[i];
> - G_sum += g_sum * weights[i];
> - B_sum += b_sum * weights[i];
> - pixel_sum += counted * weights[i];
> + double rAcc = std::min(regions[i].r_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);
> + double gAcc = std::min(regions[i].g_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);
> + double bAcc = std::min(regions[i].b_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);
> + rSum += rAcc * weights[i];
> + gSum += gAcc * weights[i];
> + bSum += bAcc * weights[i];
> + pixelSum += counted * weights[i];
> }
> - if (pixel_sum == 0.0) {
> + if (pixelSum == 0.0) {
> LOG(RPiAgc, Warning) << "compute_initial_Y: pixel_sum is zero";
This comment needs updating.
> return 0;
> }
> - double Y_sum = R_sum * awb.gain_r * .299 +
> - G_sum * awb.gain_g * .587 +
> - B_sum * awb.gain_b * .114;
> - return Y_sum / pixel_sum / (1 << PIPELINE_BITS);
> + double ySum = rSum * awb.gainR * .299 +
> + gSum * awb.gainG * .587 +
> + bSum * awb.gainB * .114;
> + return ySum / pixelSum / (1 << PIPELINE_BITS);
> }
>
> // We handle extra gain through EV by adjusting our Y targets. However, you
> @@ -542,108 +533,102 @@ static double compute_initial_Y(bcm2835_isp_stats *stats, AwbStatus const &awb,
>
> #define EV_GAIN_Y_TARGET_LIMIT 0.9
>
> -static double constraint_compute_gain(AgcConstraint &c, Histogram &h,
> - double lux, double ev_gain,
> - double &target_Y)
> +static double constraintComputeGain(AgcConstraint &c, Histogram &h, double lux,
> + double evGain, double &targetY)
> {
> - target_Y = c.Y_target.Eval(c.Y_target.Domain().Clip(lux));
> - target_Y = std::min(EV_GAIN_Y_TARGET_LIMIT, target_Y * ev_gain);
> - double iqm = h.InterQuantileMean(c.q_lo, c.q_hi);
> - return (target_Y * NUM_HISTOGRAM_BINS) / iqm;
> + targetY = c.yTarget.eval(c.yTarget.domain().clip(lux));
> + targetY = std::min(EV_GAIN_Y_TARGET_LIMIT, targetY * evGain);
> + double iqm = h.interQuantileMean(c.qLo, c.qHi);
> + return (targetY * NUM_HISTOGRAM_BINS) / iqm;
> }
>
> -void Agc::computeGain(bcm2835_isp_stats *statistics, Metadata *image_metadata,
> - double &gain, double &target_Y)
> +void Agc::computeGain(bcm2835_isp_stats *statistics, Metadata *imageMetadata,
> + double &gain, double &targetY)
> {
> struct LuxStatus lux = {};
> lux.lux = 400; // default lux level to 400 in case no metadata found
> - if (image_metadata->Get("lux.status", lux) != 0)
> + if (imageMetadata->get("lux.status", lux) != 0)
> LOG(RPiAgc, Warning) << "Agc: no lux level found";
> Histogram h(statistics->hist[0].g_hist, NUM_HISTOGRAM_BINS);
> - double ev_gain = status_.ev * config_.base_ev;
> + double evGain = status_.ev * config_.baseEv;
> // The initial gain and target_Y come from some of the regions. After
> // that we consider the histogram constraints.
> - target_Y =
> - config_.Y_target.Eval(config_.Y_target.Domain().Clip(lux.lux));
> - target_Y = std::min(EV_GAIN_Y_TARGET_LIMIT, target_Y * ev_gain);
> + targetY = config_.yTarget.eval(config_.yTarget.domain().clip(lux.lux));
> + targetY = std::min(EV_GAIN_Y_TARGET_LIMIT, targetY * evGain);
>
> // Do this calculation a few times as brightness increase can be
> // non-linear when there are saturated regions.
> gain = 1.0;
> for (int i = 0; i < 8; i++) {
> - double initial_Y = compute_initial_Y(statistics, awb_,
> - metering_mode_->weights, gain);
> - double extra_gain = std::min(10.0, target_Y / (initial_Y + .001));
> - gain *= extra_gain;
> - LOG(RPiAgc, Debug) << "Initial Y " << initial_Y << " target " << target_Y
> + double initialY = computeInitialY(statistics, awb_, meteringMode_->weights, gain);
> + double extraGain = std::min(10.0, targetY / (initialY + .001));
> + gain *= extraGain;
> + LOG(RPiAgc, Debug) << "Initial Y " << initialY << " target " << targetY
> << " gives gain " << gain;
> - if (extra_gain < 1.01) // close enough
> + if (extraGain < 1.01) // close enough
> break;
> }
>
> - for (auto &c : *constraint_mode_) {
> - double new_target_Y;
> - double new_gain =
> - constraint_compute_gain(c, h, lux.lux, ev_gain,
> - new_target_Y);
> + for (auto &c : *constraintMode_) {
> + double newTargetY;
> + double newGain = constraintComputeGain(c, h, lux.lux, evGain, newTargetY);
> LOG(RPiAgc, Debug) << "Constraint has target_Y "
> - << new_target_Y << " giving gain " << new_gain;
> - if (c.bound == AgcConstraint::Bound::LOWER &&
> - new_gain > gain) {
> + << newTargetY << " giving gain " << newGain;
> + if (c.bound == AgcConstraint::Bound::LOWER && newGain > gain) {
> LOG(RPiAgc, Debug) << "Lower bound constraint adopted";
> - gain = new_gain, target_Y = new_target_Y;
> - } else if (c.bound == AgcConstraint::Bound::UPPER &&
> - new_gain < gain) {
> + gain = newGain;
> + targetY = newTargetY;
> + } else if (c.bound == AgcConstraint::Bound::UPPER && newGain < gain) {
> LOG(RPiAgc, Debug) << "Upper bound constraint adopted";
> - gain = new_gain, target_Y = new_target_Y;
> + gain = newGain;
> + targetY = newTargetY;
> }
> }
> - LOG(RPiAgc, Debug) << "Final gain " << gain << " (target_Y " << target_Y << " ev "
> - << status_.ev << " base_ev " << config_.base_ev
> + LOG(RPiAgc, Debug) << "Final gain " << gain << " (target_Y " << targetY << " ev "
> + << status_.ev << " base_ev " << config_.baseEv
> << ")";
> }
>
> void Agc::computeTargetExposure(double gain)
> {
> - if (status_.fixed_shutter && status_.fixed_analogue_gain) {
> + if (status_.fixedShutter && status_.fixedAnalogueGain) {
> // When ag and shutter are both fixed, we need to drive the
> // total exposure so that we end up with a digital gain of at least
> // 1/min_colour_gain. Otherwise we'd desaturate channels causing
s/min_colour_gain/minColourGain/
> // white to go cyan or magenta.
> - double min_colour_gain = std::min({ awb_.gain_r, awb_.gain_g, awb_.gain_b, 1.0 });
> - ASSERT(min_colour_gain != 0.0);
> - target_.total_exposure =
> - status_.fixed_shutter * status_.fixed_analogue_gain / min_colour_gain;
> + double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 });
> + ASSERT(minColourGain != 0.0);
> + target_.totalExposure =
> + status_.fixedShutter * status_.fixedAnalogueGain / minColourGain;
> } else {
> // The statistics reflect the image without digital gain, so the final
> // total exposure we're aiming for is:
> - target_.total_exposure = current_.total_exposure_no_dg * gain;
> + target_.totalExposure = current_.totalExposureNoDG * gain;
> // The final target exposure is also limited to what the exposure
> // mode allows.
> - Duration max_shutter = status_.fixed_shutter
> - ? status_.fixed_shutter
> - : exposure_mode_->shutter.back();
> - max_shutter = clipShutter(max_shutter);
> - Duration max_total_exposure =
> - max_shutter *
> - (status_.fixed_analogue_gain != 0.0
> - ? status_.fixed_analogue_gain
> - : exposure_mode_->gain.back());
> - target_.total_exposure = std::min(target_.total_exposure,
> - max_total_exposure);
> + Duration maxShutter = status_.fixedShutter
> + ? status_.fixedShutter
> + : exposureMode_->shutter.back();
> + maxShutter = clipShutter(maxShutter);
> + Duration maxTotalExposure =
> + maxShutter *
> + (status_.fixedAnalogueGain != 0.0
> + ? status_.fixedAnalogueGain
> + : exposureMode_->gain.back());
> + target_.totalExposure = std::min(target_.totalExposure, maxTotalExposure);
> }
> - LOG(RPiAgc, Debug) << "Target total_exposure " << target_.total_exposure;
> + LOG(RPiAgc, Debug) << "Target totalExposure " << target_.totalExposure;
> }
>
> -bool Agc::applyDigitalGain(double gain, double target_Y)
> +bool Agc::applyDigitalGain(double gain, double targetY)
> {
> - double min_colour_gain = std::min({ awb_.gain_r, awb_.gain_g, awb_.gain_b, 1.0 });
> - ASSERT(min_colour_gain != 0.0);
> - double dg = 1.0 / min_colour_gain;
> + double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 });
> + ASSERT(minColourGain != 0.0);
> + double dg = 1.0 / minColourGain;
> // I think this pipeline subtracts black level and rescales before we
> // get the stats, so no need to worry about it.
> LOG(RPiAgc, Debug) << "after AWB, target dg " << dg << " gain " << gain
> - << " target_Y " << target_Y;
> + << " target_Y " << targetY;
> // Finally, if we're trying to reduce exposure but the target_Y is
> // "close" to 1.0, then the gain computed for that constraint will be
> // only slightly less than one, because the measured Y can never be
> @@ -651,13 +636,13 @@ bool Agc::applyDigitalGain(double gain, double target_Y)
> // that the exposure can be reduced, de-saturating the image much more
> // quickly (and we then approach the correct value more quickly from
> // below).
> - bool desaturate = target_Y > config_.fast_reduce_threshold &&
> - gain < sqrt(target_Y);
> + bool desaturate = targetY > config_.fastReduceThreshold &&
> + gain < sqrt(targetY);
> if (desaturate)
> - dg /= config_.fast_reduce_threshold;
> + dg /= config_.fastReduceThreshold;
> LOG(RPiAgc, Debug) << "Digital gain " << dg << " desaturate? " << desaturate;
> - target_.total_exposure_no_dg = target_.total_exposure / dg;
> - LOG(RPiAgc, Debug) << "Target total_exposure_no_dg " << target_.total_exposure_no_dg;
> + target_.totalExposureNoDG = target_.totalExposure / dg;
> + LOG(RPiAgc, Debug) << "Target totalExposureNoDG " << target_.totalExposureNoDG;
> return desaturate;
> }
>
> @@ -666,39 +651,38 @@ void Agc::filterExposure(bool desaturate)
> double speed = config_.speed;
> // AGC adapts instantly if both shutter and gain are directly specified
> // or we're in the startup phase.
> - if ((status_.fixed_shutter && status_.fixed_analogue_gain) ||
> - frame_count_ <= config_.startup_frames)
> + if ((status_.fixedShutter && status_.fixedAnalogueGain) ||
> + frameCount_ <= config_.startupFrames)
> speed = 1.0;
> - if (!filtered_.total_exposure) {
> - filtered_.total_exposure = target_.total_exposure;
> - filtered_.total_exposure_no_dg = target_.total_exposure_no_dg;
> + if (!filtered_.totalExposure) {
> + filtered_.totalExposure = target_.totalExposure;
> + filtered_.totalExposureNoDG = target_.totalExposureNoDG;
> } else {
> // If close to the result go faster, to save making so many
> // micro-adjustments on the way. (Make this customisable?)
> - if (filtered_.total_exposure < 1.2 * target_.total_exposure &&
> - filtered_.total_exposure > 0.8 * target_.total_exposure)
> + if (filtered_.totalExposure < 1.2 * target_.totalExposure &&
> + filtered_.totalExposure > 0.8 * target_.totalExposure)
> speed = sqrt(speed);
> - filtered_.total_exposure = speed * target_.total_exposure +
> - filtered_.total_exposure * (1.0 - speed);
> + filtered_.totalExposure = speed * target_.totalExposure +
> + filtered_.totalExposure * (1.0 - speed);
> // When desaturing, take a big jump down in exposure_no_dg,
s/exposure_no_dg/totalExposureNoDG/
> // which we'll hide with digital gain.
> if (desaturate)
> - filtered_.total_exposure_no_dg =
> - target_.total_exposure_no_dg;
> + filtered_.totalExposureNoDG =
> + target_.totalExposureNoDG;
> else
> - filtered_.total_exposure_no_dg =
> - speed * target_.total_exposure_no_dg +
> - filtered_.total_exposure_no_dg * (1.0 - speed);
> + filtered_.totalExposureNoDG =
> + speed * target_.totalExposureNoDG +
> + filtered_.totalExposureNoDG * (1.0 - speed);
> }
> // We can't let the no_dg exposure deviate too far below the
Maybe an update here too.
> // total exposure, as there might not be enough digital gain available
> // in the ISP to hide it (which will cause nasty oscillation).
> - if (filtered_.total_exposure_no_dg <
> - filtered_.total_exposure * config_.fast_reduce_threshold)
> - filtered_.total_exposure_no_dg = filtered_.total_exposure *
> - config_.fast_reduce_threshold;
> - LOG(RPiAgc, Debug) << "After filtering, total_exposure " << filtered_.total_exposure
> - << " no dg " << filtered_.total_exposure_no_dg;
> + if (filtered_.totalExposureNoDG <
> + filtered_.totalExposure * config_.fastReduceThreshold)
> + filtered_.totalExposureNoDG = filtered_.totalExposure * config_.fastReduceThreshold;
> + LOG(RPiAgc, Debug) << "After filtering, totalExposure " << filtered_.totalExposure
> + << " no dg " << filtered_.totalExposureNoDG;
> }
>
> void Agc::divideUpExposure()
> @@ -706,92 +690,84 @@ void Agc::divideUpExposure()
> // Sending the fixed shutter/gain cases through the same code may seem
> // unnecessary, but it will make more sense when extend this to cover
> // variable aperture.
> - Duration exposure_value = filtered_.total_exposure_no_dg;
> - Duration shutter_time;
> - double analogue_gain;
> - shutter_time = status_.fixed_shutter
> - ? status_.fixed_shutter
> - : exposure_mode_->shutter[0];
> - shutter_time = clipShutter(shutter_time);
> - analogue_gain = status_.fixed_analogue_gain != 0.0
> - ? status_.fixed_analogue_gain
> - : exposure_mode_->gain[0];
> - if (shutter_time * analogue_gain < exposure_value) {
> + Duration exposureValue = filtered_.totalExposureNoDG;
> + Duration shutterTime;
> + double analogueGain;
> + shutterTime = status_.fixedShutter ? status_.fixedShutter
> + : exposureMode_->shutter[0];
> + shutterTime = clipShutter(shutterTime);
> + analogueGain = status_.fixedAnalogueGain != 0.0 ? status_.fixedAnalogueGain
> + : exposureMode_->gain[0];
> + if (shutterTime * analogueGain < exposureValue) {
> for (unsigned int stage = 1;
> - stage < exposure_mode_->gain.size(); stage++) {
> - if (!status_.fixed_shutter) {
> + stage < exposureMode_->gain.size(); stage++) {
> + if (!status_.fixedShutter) {
> Duration stage_shutter =
This variable also needs to be renamed.
> - clipShutter(exposure_mode_->shutter[stage]);
> - if (stage_shutter * analogue_gain >=
> - exposure_value) {
> - shutter_time =
> - exposure_value / analogue_gain;
> + clipShutter(exposureMode_->shutter[stage]);
> + if (stage_shutter * analogueGain >= exposureValue) {
> + shutterTime = exposureValue / analogueGain;
> break;
> }
> - shutter_time = stage_shutter;
> + shutterTime = stage_shutter;
> }
> - if (status_.fixed_analogue_gain == 0.0) {
> - if (exposure_mode_->gain[stage] *
> - shutter_time >=
> - exposure_value) {
> - analogue_gain =
> - exposure_value / shutter_time;
> + if (status_.fixedAnalogueGain == 0.0) {
> + if (exposureMode_->gain[stage] * shutterTime >= exposureValue) {
> + analogueGain = exposureValue / shutterTime;
> break;
> }
> - analogue_gain = exposure_mode_->gain[stage];
> + analogueGain = exposureMode_->gain[stage];
> }
> }
> }
> - LOG(RPiAgc, Debug) << "Divided up shutter and gain are " << shutter_time << " and "
> - << analogue_gain;
> + LOG(RPiAgc, Debug) << "Divided up shutter and gain are " << shutterTime << " and "
> + << analogueGain;
> // Finally adjust shutter time for flicker avoidance (require both
> // shutter and gain not to be fixed).
> - if (!status_.fixed_shutter && !status_.fixed_analogue_gain &&
> - status_.flicker_period) {
> - int flicker_periods = shutter_time / status_.flicker_period;
> - if (flicker_periods) {
> - Duration new_shutter_time = flicker_periods * status_.flicker_period;
> - analogue_gain *= shutter_time / new_shutter_time;
> + if (!status_.fixedShutter && !status_.fixedAnalogueGain &&
> + status_.flickerPeriod) {
> + int flickerPeriods = shutterTime / status_.flickerPeriod;
> + if (flickerPeriods) {
> + Duration newShutterTime = flickerPeriods * status_.flickerPeriod;
> + analogueGain *= shutterTime / newShutterTime;
> // We should still not allow the ag to go over the
> // largest value in the exposure mode. Note that this
> // may force more of the total exposure into the digital
> // gain as a side-effect.
> - analogue_gain = std::min(analogue_gain,
> - exposure_mode_->gain.back());
> - shutter_time = new_shutter_time;
> + analogueGain = std::min(analogueGain, exposureMode_->gain.back());
> + shutterTime = newShutterTime;
> }
> LOG(RPiAgc, Debug) << "After flicker avoidance, shutter "
> - << shutter_time << " gain " << analogue_gain;
> + << shutterTime << " gain " << analogueGain;
> }
> - filtered_.shutter = shutter_time;
> - filtered_.analogue_gain = analogue_gain;
> + filtered_.shutter = shutterTime;
> + filtered_.analogueGain = analogueGain;
> }
>
> -void Agc::writeAndFinish(Metadata *image_metadata, bool desaturate)
> +void Agc::writeAndFinish(Metadata *imageMetadata, bool desaturate)
> {
> - status_.total_exposure_value = filtered_.total_exposure;
> - status_.target_exposure_value = desaturate ? 0s : target_.total_exposure_no_dg;
> - status_.shutter_time = filtered_.shutter;
> - status_.analogue_gain = filtered_.analogue_gain;
> + status_.totalExposureValue = filtered_.totalExposure;
> + status_.targetExposureValue = desaturate ? 0s : target_.totalExposureNoDG;
> + status_.shutterTime = filtered_.shutter;
> + status_.analogueGain = filtered_.analogueGain;
> // Write to metadata as well, in case anyone wants to update the camera
> // immediately.
> - image_metadata->Set("agc.status", status_);
> + imageMetadata->set("agc.status", status_);
> LOG(RPiAgc, Debug) << "Output written, total exposure requested is "
> - << filtered_.total_exposure;
> + << filtered_.totalExposure;
> LOG(RPiAgc, Debug) << "Camera exposure update: shutter time " << filtered_.shutter
> - << " analogue gain " << filtered_.analogue_gain;
> + << " analogue gain " << filtered_.analogueGain;
> }
>
> Duration Agc::clipShutter(Duration shutter)
> {
> - if (max_shutter_)
> - shutter = std::min(shutter, max_shutter_);
> + if (maxShutter_)
> + shutter = std::min(shutter, maxShutter_);
> return shutter;
> }
>
> // Register algorithm with the system.
> -static Algorithm *Create(Controller *controller)
> +static Algorithm *create(Controller *controller)
> {
> return (Algorithm *)new Agc(controller);
> }
> -static RegisterAlgorithm reg(NAME, &Create);
> +static RegisterAlgorithm reg(NAME, &create);
> diff --git a/src/ipa/raspberrypi/controller/rpi/agc.hpp b/src/ipa/raspberrypi/controller/rpi/agc.hpp
> index c100d3128c90..4ed7293bce97 100644
> --- a/src/ipa/raspberrypi/controller/rpi/agc.hpp
> +++ b/src/ipa/raspberrypi/controller/rpi/agc.hpp
> @@ -26,114 +26,114 @@ namespace RPiController {
>
> struct AgcMeteringMode {
> double weights[AGC_STATS_SIZE];
> - void Read(boost::property_tree::ptree const ¶ms);
> + void read(boost::property_tree::ptree const ¶ms);
> };
>
> struct AgcExposureMode {
> std::vector<libcamera::utils::Duration> shutter;
> std::vector<double> gain;
> - void Read(boost::property_tree::ptree const ¶ms);
> + void read(boost::property_tree::ptree const ¶ms);
> };
>
> struct AgcConstraint {
> enum class Bound { LOWER = 0, UPPER = 1 };
> Bound bound;
> - double q_lo;
> - double q_hi;
> - Pwl Y_target;
> - void Read(boost::property_tree::ptree const ¶ms);
> + double qLo;
> + double qHi;
> + Pwl yTarget;
> + void read(boost::property_tree::ptree const ¶ms);
> };
>
> typedef std::vector<AgcConstraint> AgcConstraintMode;
>
> struct AgcConfig {
> - void Read(boost::property_tree::ptree const ¶ms);
> - std::map<std::string, AgcMeteringMode> metering_modes;
> - std::map<std::string, AgcExposureMode> exposure_modes;
> - std::map<std::string, AgcConstraintMode> constraint_modes;
> - Pwl Y_target;
> + void read(boost::property_tree::ptree const ¶ms);
> + std::map<std::string, AgcMeteringMode> meteringModes;
> + std::map<std::string, AgcExposureMode> exposureModes;
> + std::map<std::string, AgcConstraintMode> constraintModes;
> + Pwl yTarget;
> double speed;
> - uint16_t startup_frames;
> - unsigned int convergence_frames;
> - double max_change;
> - double min_change;
> - double fast_reduce_threshold;
> - double speed_up_threshold;
> - std::string default_metering_mode;
> - std::string default_exposure_mode;
> - std::string default_constraint_mode;
> - double base_ev;
> - libcamera::utils::Duration default_exposure_time;
> - double default_analogue_gain;
> + uint16_t startupFrames;
> + unsigned int convergenceFrames;
> + double maxChange;
> + double minChange;
> + double fastReduceThreshold;
> + double speedUpThreshold;
> + std::string defaultMeteringMode;
> + std::string defaultExposureMode;
> + std::string defaultConstraintMode;
> + double baseEv;
> + libcamera::utils::Duration defaultExposureTime;
> + double defaultAnalogueGain;
> };
>
> class Agc : public AgcAlgorithm
> {
> public:
> Agc(Controller *controller);
> - char const *Name() const override;
> - void Read(boost::property_tree::ptree const ¶ms) override;
> + char const *name() const override;
> + void read(boost::property_tree::ptree const ¶ms) override;
> // AGC handles "pausing" for itself.
> - bool IsPaused() const override;
> - void Pause() override;
> - void Resume() override;
> - unsigned int GetConvergenceFrames() const override;
> - void SetEv(double ev) override;
> - void SetFlickerPeriod(libcamera::utils::Duration flicker_period) override;
> - void SetMaxShutter(libcamera::utils::Duration max_shutter) override;
> - void SetFixedShutter(libcamera::utils::Duration fixed_shutter) override;
> - void SetFixedAnalogueGain(double fixed_analogue_gain) override;
> - void SetMeteringMode(std::string const &metering_mode_name) override;
> - void SetExposureMode(std::string const &exposure_mode_name) override;
> - void SetConstraintMode(std::string const &contraint_mode_name) override;
> - void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override;
> - void Prepare(Metadata *image_metadata) override;
> - void Process(StatisticsPtr &stats, Metadata *image_metadata) override;
> + bool isPaused() const override;
> + void pause() override;
> + void resume() override;
> + unsigned int getConvergenceFrames() const override;
> + void setEv(double ev) override;
> + void setFlickerPeriod(libcamera::utils::Duration flickerPeriod) override;
> + void setMaxShutter(libcamera::utils::Duration maxShutter) override;
> + void setFixedShutter(libcamera::utils::Duration fixedShutter) override;
> + void setFixedAnalogueGain(double fixedAnalogueGain) override;
> + void setMeteringMode(std::string const &meteringModeName) override;
> + void setExposureMode(std::string const &exposureModeName) override;
> + void setConstraintMode(std::string const &contraintModeName) override;
> + void switchMode(CameraMode const &cameraMode, Metadata *metadata) override;
> + void prepare(Metadata *imageMetadata) override;
> + void process(StatisticsPtr &stats, Metadata *imageMetadata) override;
>
> private:
> - void updateLockStatus(DeviceStatus const &device_status);
> + void updateLockStatus(DeviceStatus const &deviceStatus);
> AgcConfig config_;
> void housekeepConfig();
> - void fetchCurrentExposure(Metadata *image_metadata);
> - void fetchAwbStatus(Metadata *image_metadata);
> - void computeGain(bcm2835_isp_stats *statistics, Metadata *image_metadata,
> - double &gain, double &target_Y);
> + void fetchCurrentExposure(Metadata *imageMetadata);
> + void fetchAwbStatus(Metadata *imageMetadata);
> + void computeGain(bcm2835_isp_stats *statistics, Metadata *imageMetadata,
> + double &gain, double &targetY);
> void computeTargetExposure(double gain);
> - bool applyDigitalGain(double gain, double target_Y);
> + bool applyDigitalGain(double gain, double targetY);
> void filterExposure(bool desaturate);
> void divideUpExposure();
> - void writeAndFinish(Metadata *image_metadata, bool desaturate);
> + void writeAndFinish(Metadata *imageMetadata, bool desaturate);
> libcamera::utils::Duration clipShutter(libcamera::utils::Duration shutter);
> - AgcMeteringMode *metering_mode_;
> - AgcExposureMode *exposure_mode_;
> - AgcConstraintMode *constraint_mode_;
> - uint64_t frame_count_;
> + AgcMeteringMode *meteringMode_;
> + AgcExposureMode *exposureMode_;
> + AgcConstraintMode *constraintMode_;
> + uint64_t frameCount_;
> AwbStatus awb_;
> struct ExposureValues {
> ExposureValues();
>
> libcamera::utils::Duration shutter;
> - double analogue_gain;
> - libcamera::utils::Duration total_exposure;
> - libcamera::utils::Duration total_exposure_no_dg; // without digital gain
> + double analogueGain;
> + libcamera::utils::Duration totalExposure;
> + libcamera::utils::Duration totalExposureNoDG; // without digital gain
> };
> ExposureValues current_; // values for the current frame
> ExposureValues target_; // calculate the values we want here
> ExposureValues filtered_; // these values are filtered towards target
> AgcStatus status_;
> - int lock_count_;
> - DeviceStatus last_device_status_;
> - libcamera::utils::Duration last_target_exposure_;
> - double last_sensitivity_; // sensitivity of the previous camera mode
> + int lockCount_;
> + DeviceStatus lastDeviceStatus_;
> + libcamera::utils::Duration lastTargetExposure_;
> + double lastSensitivity_; // sensitivity of the previous camera mode
> // Below here the "settings" that applications can change.
> - std::string metering_mode_name_;
> - std::string exposure_mode_name_;
> - std::string constraint_mode_name_;
> + std::string meteringModeName_;
> + std::string exposureModeName_;
> + std::string constraintModeName_;
> double ev_;
> - libcamera::utils::Duration flicker_period_;
> - libcamera::utils::Duration max_shutter_;
> - libcamera::utils::Duration fixed_shutter_;
> - double fixed_analogue_gain_;
> + libcamera::utils::Duration flickerPeriod_;
> + libcamera::utils::Duration maxShutter_;
> + libcamera::utils::Duration fixedShutter_;
> + double fixedAnalogueGain_;
> };
>
> } // namespace RPiController
> diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.cpp b/src/ipa/raspberrypi/controller/rpi/alsc.cpp
> index e575c14a92db..4929abc5b360 100644
> --- a/src/ipa/raspberrypi/controller/rpi/alsc.cpp
> +++ b/src/ipa/raspberrypi/controller/rpi/alsc.cpp
> @@ -26,31 +26,31 @@ LOG_DEFINE_CATEGORY(RPiAlsc)
> static const int X = ALSC_CELLS_X;
> static const int Y = ALSC_CELLS_Y;
> static const int XY = X * Y;
> -static const double INSUFFICIENT_DATA = -1.0;
> +static const double InsufficientData = -1.0;
>
> Alsc::Alsc(Controller *controller)
> : Algorithm(controller)
> {
> - async_abort_ = async_start_ = async_started_ = async_finished_ = false;
> - async_thread_ = std::thread(std::bind(&Alsc::asyncFunc, this));
> + asyncAbort_ = asyncStart_ = asyncStarted_ = asyncFinished_ = false;
> + asyncThread_ = std::thread(std::bind(&Alsc::asyncFunc, this));
> }
>
> Alsc::~Alsc()
> {
> {
> std::lock_guard<std::mutex> lock(mutex_);
> - async_abort_ = true;
> + asyncAbort_ = true;
> }
> - async_signal_.notify_one();
> - async_thread_.join();
> + asyncSignal_.notify_one();
> + asyncThread_.join();
> }
>
> -char const *Alsc::Name() const
> +char const *Alsc::name() const
> {
> return NAME;
> }
>
> -static void generate_lut(double *lut, boost::property_tree::ptree const ¶ms)
> +static void generateLut(double *lut, boost::property_tree::ptree const ¶ms)
> {
> double cstrength = params.get<double>("corner_strength", 2.0);
> if (cstrength <= 1.0)
> @@ -73,34 +73,34 @@ static void generate_lut(double *lut, boost::property_tree::ptree const ¶ms)
> }
> }
>
> -static void read_lut(double *lut, boost::property_tree::ptree const ¶ms)
> +static void readLut(double *lut, boost::property_tree::ptree const ¶ms)
> {
> int num = 0;
> - const int max_num = XY;
> + const int maxNum = XY;
> for (auto &p : params) {
> - if (num == max_num)
> + if (num == maxNum)
> throw std::runtime_error(
> "Alsc: too many entries in LSC table");
> lut[num++] = p.second.get_value<double>();
> }
> - if (num < max_num)
> + if (num < maxNum)
> throw std::runtime_error("Alsc: too few entries in LSC table");
> }
>
> -static void read_calibrations(std::vector<AlscCalibration> &calibrations,
> - boost::property_tree::ptree const ¶ms,
> - std::string const &name)
> +static void readCalibrations(std::vector<AlscCalibration> &calibrations,
> + boost::property_tree::ptree const ¶ms,
> + std::string const &name)
> {
> if (params.get_child_optional(name)) {
> - double last_ct = 0;
> + double lastCt = 0;
> for (auto &p : params.get_child(name)) {
> double ct = p.second.get<double>("ct");
> - if (ct <= last_ct)
> + if (ct <= lastCt)
> throw std::runtime_error(
> "Alsc: entries in " + name +
> " must be in increasing ct order");
> AlscCalibration calibration;
> - calibration.ct = last_ct = ct;
> + calibration.ct = lastCt = ct;
> boost::property_tree::ptree const &table =
> p.second.get_child("table");
> int num = 0;
> @@ -124,249 +124,239 @@ static void read_calibrations(std::vector<AlscCalibration> &calibrations,
> }
> }
>
> -void Alsc::Read(boost::property_tree::ptree const ¶ms)
> +void Alsc::read(boost::property_tree::ptree const ¶ms)
> {
> - config_.frame_period = params.get<uint16_t>("frame_period", 12);
> - config_.startup_frames = params.get<uint16_t>("startup_frames", 10);
> + config_.framePeriod = params.get<uint16_t>("frame_period", 12);
> + config_.startupFrames = params.get<uint16_t>("startup_frames", 10);
> config_.speed = params.get<double>("speed", 0.05);
> double sigma = params.get<double>("sigma", 0.01);
> - config_.sigma_Cr = params.get<double>("sigma_Cr", sigma);
> - config_.sigma_Cb = params.get<double>("sigma_Cb", sigma);
> - config_.min_count = params.get<double>("min_count", 10.0);
> - config_.min_G = params.get<uint16_t>("min_G", 50);
> + config_.sigmaCr = params.get<double>("sigma_Cr", sigma);
> + config_.sigmaCb = params.get<double>("sigma_Cb", sigma);
> + config_.minCount = params.get<double>("min_count", 10.0);
> + config_.minG = params.get<uint16_t>("min_G", 50);
> config_.omega = params.get<double>("omega", 1.3);
> - config_.n_iter = params.get<uint32_t>("n_iter", X + Y);
> - config_.luminance_strength =
> + config_.nIter = params.get<uint32_t>("n_iter", X + Y);
> + config_.luminanceStrength =
> params.get<double>("luminance_strength", 1.0);
> for (int i = 0; i < XY; i++)
> - config_.luminance_lut[i] = 1.0;
> + config_.luminanceLut[i] = 1.0;
> if (params.get_child_optional("corner_strength"))
> - generate_lut(config_.luminance_lut, params);
> + generateLut(config_.luminanceLut, params);
> else if (params.get_child_optional("luminance_lut"))
> - read_lut(config_.luminance_lut,
> - params.get_child("luminance_lut"));
> + readLut(config_.luminanceLut,
> + params.get_child("luminance_lut"));
> else
> LOG(RPiAlsc, Warning)
> << "no luminance table - assume unity everywhere";
> - read_calibrations(config_.calibrations_Cr, params, "calibrations_Cr");
> - read_calibrations(config_.calibrations_Cb, params, "calibrations_Cb");
> - config_.default_ct = params.get<double>("default_ct", 4500.0);
> + readCalibrations(config_.calibrationsCr, params, "calibrations_Cr");
> + readCalibrations(config_.calibrationsCb, params, "calibrations_Cb");
> + config_.defaultCt = params.get<double>("default_ct", 4500.0);
> config_.threshold = params.get<double>("threshold", 1e-3);
> - config_.lambda_bound = params.get<double>("lambda_bound", 0.05);
> -}
> -
> -static double get_ct(Metadata *metadata, double default_ct);
> -static void get_cal_table(double ct,
> - std::vector<AlscCalibration> const &calibrations,
> - double cal_table[XY]);
> -static void resample_cal_table(double const cal_table_in[XY],
> - CameraMode const &camera_mode,
> - double cal_table_out[XY]);
> -static void compensate_lambdas_for_cal(double const cal_table[XY],
> - double const old_lambdas[XY],
> - double new_lambdas[XY]);
> -static void add_luminance_to_tables(double results[3][Y][X],
> - double const lambda_r[XY], double lambda_g,
> - double const lambda_b[XY],
> - double const luminance_lut[XY],
> - double luminance_strength);
> -
> -void Alsc::Initialise()
> -{
> - frame_count2_ = frame_count_ = frame_phase_ = 0;
> - first_time_ = true;
> - ct_ = config_.default_ct;
> + config_.lambdaBound = params.get<double>("lambda_bound", 0.05);
> +}
> +
> +static double getCt(Metadata *metadata, double defaultCt);
> +static void getCalTable(double ct, std::vector<AlscCalibration> const &calibrations,
> + double calTable[XY]);
> +static void resampleCalTable(double const calTableIn[XY], CameraMode const &cameraMode,
> + double calTableOut[XY]);
> +static void compensateLambdasForCal(double const calTable[XY], double const oldLambdas[XY],
> + double newLambdas[XY]);
> +static void addLuminanceToTables(double results[3][Y][X], double const lambdaR[XY], double lambdaG,
> + double const lambdaB[XY], double const luminanceLut[XY],
> + double luminanceStrength);
> +
> +void Alsc::initialise()
> +{
> + frameCount2_ = frameCount_ = framePhase_ = 0;
> + firstTime_ = true;
> + ct_ = config_.defaultCt;
> // The lambdas are initialised in the SwitchMode.
> }
>
> void Alsc::waitForAysncThread()
> {
> - if (async_started_) {
> - async_started_ = false;
> + if (asyncStarted_) {
> + asyncStarted_ = false;
> std::unique_lock<std::mutex> lock(mutex_);
> - sync_signal_.wait(lock, [&] {
> - return async_finished_;
> + syncSignal_.wait(lock, [&] {
> + return asyncFinished_;
> });
> - async_finished_ = false;
> + asyncFinished_ = false;
> }
> }
>
> -static bool compare_modes(CameraMode const &cm0, CameraMode const &cm1)
> +static bool compareModes(CameraMode const &cm0, CameraMode const &cm1)
> {
> // Return true if the modes crop from the sensor significantly differently,
> // or if the user transform has changed.
> if (cm0.transform != cm1.transform)
> return true;
> - int left_diff = abs(cm0.crop_x - cm1.crop_x);
> - int top_diff = abs(cm0.crop_y - cm1.crop_y);
> - int right_diff = fabs(cm0.crop_x + cm0.scale_x * cm0.width -
> - cm1.crop_x - cm1.scale_x * cm1.width);
> - int bottom_diff = fabs(cm0.crop_y + cm0.scale_y * cm0.height -
> - cm1.crop_y - cm1.scale_y * cm1.height);
> + int leftDiff = abs(cm0.cropX - cm1.cropX);
> + int topDiff = abs(cm0.cropY - cm1.cropY);
> + int rightDiff = fabs(cm0.cropX + cm0.scaleX * cm0.width -
> + cm1.cropX - cm1.scaleX * cm1.width);
> + int bottomDiff = fabs(cm0.cropY + cm0.scaleY * cm0.height -
> + cm1.cropY - cm1.scaleY * cm1.height);
> // These thresholds are a rather arbitrary amount chosen to trigger
> // when carrying on with the previously calculated tables might be
> // worse than regenerating them (but without the adaptive algorithm).
> - int threshold_x = cm0.sensor_width >> 4;
> - int threshold_y = cm0.sensor_height >> 4;
> - return left_diff > threshold_x || right_diff > threshold_x ||
> - top_diff > threshold_y || bottom_diff > threshold_y;
> + int thresholdX = cm0.sensorWidth >> 4;
> + int thresholdY = cm0.sensorHeight >> 4;
> + return leftDiff > thresholdX || rightDiff > thresholdX ||
> + topDiff > thresholdY || bottomDiff > thresholdY;
> }
>
> -void Alsc::SwitchMode(CameraMode const &camera_mode,
> +void Alsc::switchMode(CameraMode const &cameraMode,
> [[maybe_unused]] Metadata *metadata)
> {
> // We're going to start over with the tables if there's any "significant"
> // change.
> - bool reset_tables = first_time_ || compare_modes(camera_mode_, camera_mode);
> + bool resetTables = firstTime_ || compareModes(cameraMode_, cameraMode);
>
> // Believe the colour temperature from the AWB, if there is one.
> - ct_ = get_ct(metadata, ct_);
> + ct_ = getCt(metadata, ct_);
>
> // Ensure the other thread isn't running while we do this.
> waitForAysncThread();
>
> - camera_mode_ = camera_mode;
> + cameraMode_ = cameraMode;
>
> // We must resample the luminance table like we do the others, but it's
> // fixed so we can simply do it up front here.
> - resample_cal_table(config_.luminance_lut, camera_mode_, luminance_table_);
> + resampleCalTable(config_.luminanceLut, cameraMode_, luminanceTable_);
>
> - if (reset_tables) {
> + if (resetTables) {
> // Upon every "table reset", arrange for something sensible to be
> // generated. Construct the tables for the previous recorded colour
> // temperature. In order to start over from scratch we initialise
> // the lambdas, but the rest of this code then echoes the code in
> // doAlsc, without the adaptive algorithm.
> for (int i = 0; i < XY; i++)
> - lambda_r_[i] = lambda_b_[i] = 1.0;
> - double cal_table_r[XY], cal_table_b[XY], cal_table_tmp[XY];
> - get_cal_table(ct_, config_.calibrations_Cr, cal_table_tmp);
> - resample_cal_table(cal_table_tmp, camera_mode_, cal_table_r);
> - get_cal_table(ct_, config_.calibrations_Cb, cal_table_tmp);
> - resample_cal_table(cal_table_tmp, camera_mode_, cal_table_b);
> - compensate_lambdas_for_cal(cal_table_r, lambda_r_,
> - async_lambda_r_);
> - compensate_lambdas_for_cal(cal_table_b, lambda_b_,
> - async_lambda_b_);
> - add_luminance_to_tables(sync_results_, async_lambda_r_, 1.0,
> - async_lambda_b_, luminance_table_,
> - config_.luminance_strength);
> - memcpy(prev_sync_results_, sync_results_,
> - sizeof(prev_sync_results_));
> - frame_phase_ = config_.frame_period; // run the algo again asap
> - first_time_ = false;
> + lambdaR_[i] = lambdaB_[i] = 1.0;
> + double calTableR[XY], calTableB[XY], calTableTmp[XY];
> + getCalTable(ct_, config_.calibrationsCr, calTableTmp);
> + resampleCalTable(calTableTmp, cameraMode_, calTableR);
> + getCalTable(ct_, config_.calibrationsCb, calTableTmp);
> + resampleCalTable(calTableTmp, cameraMode_, calTableB);
> + compensateLambdasForCal(calTableR, lambdaR_, asyncLambdaR_);
> + compensateLambdasForCal(calTableB, lambdaB_, asyncLambdaB_);
> + addLuminanceToTables(syncResults_, asyncLambdaR_, 1.0, asyncLambdaB_,
> + luminanceTable_, config_.luminanceStrength);
> + memcpy(prevSyncResults_, syncResults_, sizeof(prevSyncResults_));
> + framePhase_ = config_.framePeriod; // run the algo again asap
> + firstTime_ = false;
> }
> }
>
> void Alsc::fetchAsyncResults()
> {
> LOG(RPiAlsc, Debug) << "Fetch ALSC results";
> - async_finished_ = false;
> - async_started_ = false;
> - memcpy(sync_results_, async_results_, sizeof(sync_results_));
> + asyncFinished_ = false;
> + asyncStarted_ = false;
> + memcpy(syncResults_, asyncResults_, sizeof(syncResults_));
> }
>
> -double get_ct(Metadata *metadata, double default_ct)
> +double getCt(Metadata *metadata, double defaultCt)
> {
> - AwbStatus awb_status;
> - awb_status.temperature_K = default_ct; // in case nothing found
> - if (metadata->Get("awb.status", awb_status) != 0)
> + AwbStatus awbStatus;
> + awbStatus.temperatureK = defaultCt; // in case nothing found
> + if (metadata->get("awb.status", awbStatus) != 0)
> LOG(RPiAlsc, Debug) << "no AWB results found, using "
> - << awb_status.temperature_K;
> + << awbStatus.temperatureK;
> else
> LOG(RPiAlsc, Debug) << "AWB results found, using "
> - << awb_status.temperature_K;
> - return awb_status.temperature_K;
> + << awbStatus.temperatureK;
> + return awbStatus.temperatureK;
> }
>
> -static void copy_stats(bcm2835_isp_stats_region regions[XY], StatisticsPtr &stats,
> - AlscStatus const &status)
> +static void copyStats(bcm2835_isp_stats_region regions[XY], StatisticsPtr &stats,
> + AlscStatus const &status)
> {
> - bcm2835_isp_stats_region *input_regions = stats->awb_stats;
> - double *r_table = (double *)status.r;
> - double *g_table = (double *)status.g;
> - double *b_table = (double *)status.b;
> + bcm2835_isp_stats_region *inputRegions = stats->awb_stats;
> + double *rTable = (double *)status.r;
> + double *gTable = (double *)status.g;
> + double *bTable = (double *)status.b;
> for (int i = 0; i < XY; i++) {
> - regions[i].r_sum = input_regions[i].r_sum / r_table[i];
> - regions[i].g_sum = input_regions[i].g_sum / g_table[i];
> - regions[i].b_sum = input_regions[i].b_sum / b_table[i];
> - regions[i].counted = input_regions[i].counted;
> + regions[i].r_sum = inputRegions[i].r_sum / rTable[i];
> + regions[i].g_sum = inputRegions[i].g_sum / gTable[i];
> + regions[i].b_sum = inputRegions[i].b_sum / bTable[i];
> + regions[i].counted = inputRegions[i].counted;
> // (don't care about the uncounted value)
> }
> }
>
> -void Alsc::restartAsync(StatisticsPtr &stats, Metadata *image_metadata)
> +void Alsc::restartAsync(StatisticsPtr &stats, Metadata *imageMetadata)
> {
> LOG(RPiAlsc, Debug) << "Starting ALSC calculation";
> // Get the current colour temperature. It's all we need from the
> // metadata. Default to the last CT value (which could be the default).
> - ct_ = get_ct(image_metadata, ct_);
> + ct_ = getCt(imageMetadata, ct_);
> // We have to copy the statistics here, dividing out our best guess of
> // the LSC table that the pipeline applied to them.
> - AlscStatus alsc_status;
> - if (image_metadata->Get("alsc.status", alsc_status) != 0) {
> + AlscStatus alscStatus;
> + if (imageMetadata->get("alsc.status", alscStatus) != 0) {
> LOG(RPiAlsc, Warning)
> << "No ALSC status found for applied gains!";
> for (int y = 0; y < Y; y++)
> for (int x = 0; x < X; x++) {
> - alsc_status.r[y][x] = 1.0;
> - alsc_status.g[y][x] = 1.0;
> - alsc_status.b[y][x] = 1.0;
> + alscStatus.r[y][x] = 1.0;
> + alscStatus.g[y][x] = 1.0;
> + alscStatus.b[y][x] = 1.0;
> }
> }
> - copy_stats(statistics_, stats, alsc_status);
> - frame_phase_ = 0;
> - async_started_ = true;
> + copyStats(statistics_, stats, alscStatus);
> + framePhase_ = 0;
> + asyncStarted_ = true;
> {
> std::lock_guard<std::mutex> lock(mutex_);
> - async_start_ = true;
> + asyncStart_ = true;
> }
> - async_signal_.notify_one();
> + asyncSignal_.notify_one();
> }
>
> -void Alsc::Prepare(Metadata *image_metadata)
> +void Alsc::prepare(Metadata *imageMetadata)
> {
> // Count frames since we started, and since we last poked the async
> // thread.
> - if (frame_count_ < (int)config_.startup_frames)
> - frame_count_++;
> - double speed = frame_count_ < (int)config_.startup_frames
> + if (frameCount_ < (int)config_.startupFrames)
> + frameCount_++;
> + double speed = frameCount_ < (int)config_.startupFrames
> ? 1.0
> : config_.speed;
> LOG(RPiAlsc, Debug)
> - << "frame_count " << frame_count_ << " speed " << speed;
> + << "frame count " << frameCount_ << " speed " << speed;
> {
> std::unique_lock<std::mutex> lock(mutex_);
> - if (async_started_ && async_finished_)
> + if (asyncStarted_ && asyncFinished_)
> fetchAsyncResults();
> }
> // Apply IIR filter to results and program into the pipeline.
> - double *ptr = (double *)sync_results_,
> - *pptr = (double *)prev_sync_results_;
> - for (unsigned int i = 0;
> - i < sizeof(sync_results_) / sizeof(double); i++)
> + double *ptr = (double *)syncResults_,
> + *pptr = (double *)prevSyncResults_;
> + for (unsigned int i = 0; i < sizeof(syncResults_) / sizeof(double); i++)
> pptr[i] = speed * ptr[i] + (1.0 - speed) * pptr[i];
> // Put output values into status metadata.
> AlscStatus status;
> - memcpy(status.r, prev_sync_results_[0], sizeof(status.r));
> - memcpy(status.g, prev_sync_results_[1], sizeof(status.g));
> - memcpy(status.b, prev_sync_results_[2], sizeof(status.b));
> - image_metadata->Set("alsc.status", status);
> + memcpy(status.r, prevSyncResults_[0], sizeof(status.r));
> + memcpy(status.g, prevSyncResults_[1], sizeof(status.g));
> + memcpy(status.b, prevSyncResults_[2], sizeof(status.b));
> + imageMetadata->set("alsc.status", status);
> }
>
> -void Alsc::Process(StatisticsPtr &stats, Metadata *image_metadata)
> +void Alsc::process(StatisticsPtr &stats, Metadata *imageMetadata)
> {
> // Count frames since we started, and since we last poked the async
> // thread.
> - if (frame_phase_ < (int)config_.frame_period)
> - frame_phase_++;
> - if (frame_count2_ < (int)config_.startup_frames)
> - frame_count2_++;
> - LOG(RPiAlsc, Debug) << "frame_phase " << frame_phase_;
> - if (frame_phase_ >= (int)config_.frame_period ||
> - frame_count2_ < (int)config_.startup_frames) {
> - if (async_started_ == false)
> - restartAsync(stats, image_metadata);
> + if (framePhase_ < (int)config_.framePeriod)
> + framePhase_++;
> + if (frameCount2_ < (int)config_.startupFrames)
> + frameCount2_++;
> + LOG(RPiAlsc, Debug) << "frame_phase " << framePhase_;
> + if (framePhase_ >= (int)config_.framePeriod ||
> + frameCount2_ < (int)config_.startupFrames) {
> + if (asyncStarted_ == false)
> + restartAsync(stats, imageMetadata);
> }
> }
>
> @@ -375,143 +365,140 @@ void Alsc::asyncFunc()
> while (true) {
> {
> std::unique_lock<std::mutex> lock(mutex_);
> - async_signal_.wait(lock, [&] {
> - return async_start_ || async_abort_;
> + asyncSignal_.wait(lock, [&] {
> + return asyncStart_ || asyncAbort_;
> });
> - async_start_ = false;
> - if (async_abort_)
> + asyncStart_ = false;
> + if (asyncAbort_)
> break;
> }
> doAlsc();
> {
> std::lock_guard<std::mutex> lock(mutex_);
> - async_finished_ = true;
> + asyncFinished_ = true;
> }
> - sync_signal_.notify_one();
> + syncSignal_.notify_one();
> }
> }
>
> -void get_cal_table(double ct, std::vector<AlscCalibration> const &calibrations,
> - double cal_table[XY])
> +void getCalTable(double ct, std::vector<AlscCalibration> const &calibrations,
> + double calTable[XY])
> {
> if (calibrations.empty()) {
> for (int i = 0; i < XY; i++)
> - cal_table[i] = 1.0;
> + calTable[i] = 1.0;
> LOG(RPiAlsc, Debug) << "no calibrations found";
> } else if (ct <= calibrations.front().ct) {
> - memcpy(cal_table, calibrations.front().table,
> - XY * sizeof(double));
> + memcpy(calTable, calibrations.front().table, XY * sizeof(double));
> LOG(RPiAlsc, Debug) << "using calibration for "
> << calibrations.front().ct;
> } else if (ct >= calibrations.back().ct) {
> - memcpy(cal_table, calibrations.back().table,
> - XY * sizeof(double));
> + memcpy(calTable, calibrations.back().table, XY * sizeof(double));
> LOG(RPiAlsc, Debug) << "using calibration for "
> << calibrations.back().ct;
> } else {
> int idx = 0;
> while (ct > calibrations[idx + 1].ct)
> idx++;
> - double ct0 = calibrations[idx].ct,
> - ct1 = calibrations[idx + 1].ct;
> + double ct0 = calibrations[idx].ct, ct1 = calibrations[idx + 1].ct;
> LOG(RPiAlsc, Debug)
> << "ct is " << ct << ", interpolating between "
> << ct0 << " and " << ct1;
> for (int i = 0; i < XY; i++)
> - cal_table[i] =
> + calTable[i] =
> (calibrations[idx].table[i] * (ct1 - ct) +
> calibrations[idx + 1].table[i] * (ct - ct0)) /
> (ct1 - ct0);
> }
> }
>
> -void resample_cal_table(double const cal_table_in[XY],
> - CameraMode const &camera_mode, double cal_table_out[XY])
> +void resampleCalTable(double const calTableIn[XY],
> + CameraMode const &cameraMode, double calTableOut[XY])
> {
> // Precalculate and cache the x sampling locations and phases to save
> // recomputing them on every row.
> - int x_lo[X], x_hi[X];
> + int xLo[X], xHi[X];
> double xf[X];
> - double scale_x = camera_mode.sensor_width /
> - (camera_mode.width * camera_mode.scale_x);
> - double x_off = camera_mode.crop_x / (double)camera_mode.sensor_width;
> - double x = .5 / scale_x + x_off * X - .5;
> - double x_inc = 1 / scale_x;
> - for (int i = 0; i < X; i++, x += x_inc) {
> - x_lo[i] = floor(x);
> - xf[i] = x - x_lo[i];
> - x_hi[i] = std::min(x_lo[i] + 1, X - 1);
> - x_lo[i] = std::max(x_lo[i], 0);
> - if (!!(camera_mode.transform & libcamera::Transform::HFlip)) {
> - x_lo[i] = X - 1 - x_lo[i];
> - x_hi[i] = X - 1 - x_hi[i];
> + double scaleX = cameraMode.sensorWidth /
> + (cameraMode.width * cameraMode.scaleX);
> + double xOff = cameraMode.cropX / (double)cameraMode.sensorWidth;
> + double x = .5 / scaleX + xOff * X - .5;
> + double xInc = 1 / scaleX;
> + for (int i = 0; i < X; i++, x += xInc) {
> + xLo[i] = floor(x);
> + xf[i] = x - xLo[i];
> + xHi[i] = std::min(xLo[i] + 1, X - 1);
> + xLo[i] = std::max(xLo[i], 0);
> + if (!!(cameraMode.transform & libcamera::Transform::HFlip)) {
> + xLo[i] = X - 1 - xLo[i];
> + xHi[i] = X - 1 - xHi[i];
> }
> }
> // Now march over the output table generating the new values.
> - double scale_y = camera_mode.sensor_height /
> - (camera_mode.height * camera_mode.scale_y);
> - double y_off = camera_mode.crop_y / (double)camera_mode.sensor_height;
> - double y = .5 / scale_y + y_off * Y - .5;
> - double y_inc = 1 / scale_y;
> - for (int j = 0; j < Y; j++, y += y_inc) {
> - int y_lo = floor(y);
> - double yf = y - y_lo;
> - int y_hi = std::min(y_lo + 1, Y - 1);
> - y_lo = std::max(y_lo, 0);
> - if (!!(camera_mode.transform & libcamera::Transform::VFlip)) {
> - y_lo = Y - 1 - y_lo;
> - y_hi = Y - 1 - y_hi;
> + double scaleY = cameraMode.sensorHeight /
> + (cameraMode.height * cameraMode.scaleY);
> + double yOff = cameraMode.cropY / (double)cameraMode.sensorHeight;
> + double y = .5 / scaleY + yOff * Y - .5;
> + double yInc = 1 / scaleY;
> + for (int j = 0; j < Y; j++, y += yInc) {
> + int yLo = floor(y);
> + double yf = y - yLo;
> + int yHi = std::min(yLo + 1, Y - 1);
> + yLo = std::max(yLo, 0);
> + if (!!(cameraMode.transform & libcamera::Transform::VFlip)) {
> + yLo = Y - 1 - yLo;
> + yHi = Y - 1 - yHi;
> }
> - double const *row_above = cal_table_in + X * y_lo;
> - double const *row_below = cal_table_in + X * y_hi;
> + double const *rowAbove = calTableIn + X * yLo;
> + double const *rowBelow = calTableIn + X * yHi;
> for (int i = 0; i < X; i++) {
> - double above = row_above[x_lo[i]] * (1 - xf[i]) +
> - row_above[x_hi[i]] * xf[i];
> - double below = row_below[x_lo[i]] * (1 - xf[i]) +
> - row_below[x_hi[i]] * xf[i];
> - *(cal_table_out++) = above * (1 - yf) + below * yf;
> + double above = rowAbove[xLo[i]] * (1 - xf[i]) +
> + rowAbove[xHi[i]] * xf[i];
> + double below = rowBelow[xLo[i]] * (1 - xf[i]) +
> + rowBelow[xHi[i]] * xf[i];
> + *(calTableOut++) = above * (1 - yf) + below * yf;
> }
> }
> }
>
> // Calculate chrominance statistics (R/G and B/G) for each region.
> static_assert(XY == AWB_REGIONS, "ALSC/AWB statistics region mismatch");
> -static void calculate_Cr_Cb(bcm2835_isp_stats_region *awb_region, double Cr[XY],
> - double Cb[XY], uint32_t min_count, uint16_t min_G)
> +static void calculateCrCb(bcm2835_isp_stats_region *awbRegion, double cr[XY],
> + double cb[XY], uint32_t minCount, uint16_t minG)
> {
> for (int i = 0; i < XY; i++) {
> - bcm2835_isp_stats_region &zone = awb_region[i];
> - if (zone.counted <= min_count ||
> - zone.g_sum / zone.counted <= min_G) {
> - Cr[i] = Cb[i] = INSUFFICIENT_DATA;
> + bcm2835_isp_stats_region &zone = awbRegion[i];
> + if (zone.counted <= minCount ||
> + zone.g_sum / zone.counted <= minG) {
> + cr[i] = cb[i] = InsufficientData;
> continue;
> }
> - Cr[i] = zone.r_sum / (double)zone.g_sum;
> - Cb[i] = zone.b_sum / (double)zone.g_sum;
> + cr[i] = zone.r_sum / (double)zone.g_sum;
> + cb[i] = zone.b_sum / (double)zone.g_sum;
> }
> }
>
> -static void apply_cal_table(double const cal_table[XY], double C[XY])
> +static void applyCalTable(double const calTable[XY], double C[XY])
> {
> for (int i = 0; i < XY; i++)
> - if (C[i] != INSUFFICIENT_DATA)
> - C[i] *= cal_table[i];
> + if (C[i] != InsufficientData)
> + C[i] *= calTable[i];
> }
>
> -void compensate_lambdas_for_cal(double const cal_table[XY],
> - double const old_lambdas[XY],
> - double new_lambdas[XY])
> +void compensateLambdasForCal(double const calTable[XY],
> + double const oldLambdas[XY],
> + double newLambdas[XY])
> {
> - double min_new_lambda = std::numeric_limits<double>::max();
> + double minNewLambda = std::numeric_limits<double>::max();
> for (int i = 0; i < XY; i++) {
> - new_lambdas[i] = old_lambdas[i] * cal_table[i];
> - min_new_lambda = std::min(min_new_lambda, new_lambdas[i]);
> + newLambdas[i] = oldLambdas[i] * calTable[i];
> + minNewLambda = std::min(minNewLambda, newLambdas[i]);
> }
> for (int i = 0; i < XY; i++)
> - new_lambdas[i] /= min_new_lambda;
> + newLambdas[i] /= minNewLambda;
> }
>
> -[[maybe_unused]] static void print_cal_table(double const C[XY])
> +[[maybe_unused]] static void printCalTable(double const C[XY])
> {
> printf("table: [\n");
> for (int j = 0; j < Y; j++) {
> @@ -527,31 +514,29 @@ void compensate_lambdas_for_cal(double const cal_table[XY],
>
> // Compute weight out of 1.0 which reflects how similar we wish to make the
> // colours of these two regions.
> -static double compute_weight(double C_i, double C_j, double sigma)
> +static double computeWeight(double Ci, double Cj, double sigma)
> {
> - if (C_i == INSUFFICIENT_DATA || C_j == INSUFFICIENT_DATA)
> + if (Ci == InsufficientData || Cj == InsufficientData)
> return 0;
> - double diff = (C_i - C_j) / sigma;
> + double diff = (Ci - Cj) / sigma;
> return exp(-diff * diff / 2);
> }
>
> // Compute all weights.
> -static void compute_W(double const C[XY], double sigma, double W[XY][4])
> +static void computeW(double const C[XY], double sigma, double W[XY][4])
> {
> for (int i = 0; i < XY; i++) {
> // Start with neighbour above and go clockwise.
> - W[i][0] = i >= X ? compute_weight(C[i], C[i - X], sigma) : 0;
> - W[i][1] = i % X < X - 1 ? compute_weight(C[i], C[i + 1], sigma)
> - : 0;
> - W[i][2] =
> - i < XY - X ? compute_weight(C[i], C[i + X], sigma) : 0;
> - W[i][3] = i % X ? compute_weight(C[i], C[i - 1], sigma) : 0;
> + W[i][0] = i >= X ? computeWeight(C[i], C[i - X], sigma) : 0;
> + W[i][1] = i % X < X - 1 ? computeWeight(C[i], C[i + 1], sigma) : 0;
> + W[i][2] = i < XY - X ? computeWeight(C[i], C[i + X], sigma) : 0;
> + W[i][3] = i % X ? computeWeight(C[i], C[i - 1], sigma) : 0;
> }
> }
>
> // Compute M, the large but sparse matrix such that M * lambdas = 0.
> -static void construct_M(double const C[XY], double const W[XY][4],
> - double M[XY][4])
> +static void constructM(double const C[XY], double const W[XY][4],
> + double M[XY][4])
> {
> double epsilon = 0.001;
> for (int i = 0; i < XY; i++) {
> @@ -560,108 +545,96 @@ static void construct_M(double const C[XY], double const W[XY][4],
> int m = !!(i >= X) + !!(i % X < X - 1) + !!(i < XY - X) +
> !!(i % X); // total number of neighbours
> // we'll divide the diagonal out straight away
> - double diagonal =
> - (epsilon + W[i][0] + W[i][1] + W[i][2] + W[i][3]) *
> - C[i];
> - M[i][0] = i >= X ? (W[i][0] * C[i - X] + epsilon / m * C[i]) /
> - diagonal
> - : 0;
> - M[i][1] = i % X < X - 1
> - ? (W[i][1] * C[i + 1] + epsilon / m * C[i]) /
> - diagonal
> - : 0;
> - M[i][2] = i < XY - X
> - ? (W[i][2] * C[i + X] + epsilon / m * C[i]) /
> - diagonal
> - : 0;
> - M[i][3] = i % X ? (W[i][3] * C[i - 1] + epsilon / m * C[i]) /
> - diagonal
> - : 0;
> + double diagonal = (epsilon + W[i][0] + W[i][1] + W[i][2] + W[i][3]) * C[i];
> + M[i][0] = i >= X ? (W[i][0] * C[i - X] + epsilon / m * C[i]) / diagonal : 0;
> + M[i][1] = i % X < X - 1 ? (W[i][1] * C[i + 1] + epsilon / m * C[i]) / diagonal : 0;
> + M[i][2] = i < XY - X ? (W[i][2] * C[i + X] + epsilon / m * C[i]) / diagonal : 0;
> + M[i][3] = i % X ? (W[i][3] * C[i - 1] + epsilon / m * C[i]) / diagonal : 0;
> }
> }
>
> // In the compute_lambda_ functions, note that the matrix coefficients for the
> // left/right neighbours are zero down the left/right edges, so we don't need
> // need to test the i value to exclude them.
> -static double compute_lambda_bottom(int i, double const M[XY][4],
> - double lambda[XY])
> +static double computeLambdaBottom(int i, double const M[XY][4],
> + double lambda[XY])
> {
> return M[i][1] * lambda[i + 1] + M[i][2] * lambda[i + X] +
> M[i][3] * lambda[i - 1];
> }
> -static double compute_lambda_bottom_start(int i, double const M[XY][4],
> - double lambda[XY])
> +static double computeLambdaBottomStart(int i, double const M[XY][4],
> + double lambda[XY])
> {
> return M[i][1] * lambda[i + 1] + M[i][2] * lambda[i + X];
> }
> -static double compute_lambda_interior(int i, double const M[XY][4],
> - double lambda[XY])
> +static double computeLambdaInterior(int i, double const M[XY][4],
> + double lambda[XY])
> {
> return M[i][0] * lambda[i - X] + M[i][1] * lambda[i + 1] +
> M[i][2] * lambda[i + X] + M[i][3] * lambda[i - 1];
> }
> -static double compute_lambda_top(int i, double const M[XY][4],
> - double lambda[XY])
> +static double computeLambdaTop(int i, double const M[XY][4],
> + double lambda[XY])
> {
> return M[i][0] * lambda[i - X] + M[i][1] * lambda[i + 1] +
> M[i][3] * lambda[i - 1];
> }
> -static double compute_lambda_top_end(int i, double const M[XY][4],
> - double lambda[XY])
> +static double computeLambdaTopEnd(int i, double const M[XY][4],
> + double lambda[XY])
> {
> return M[i][0] * lambda[i - X] + M[i][3] * lambda[i - 1];
> }
>
> // Gauss-Seidel iteration with over-relaxation.
> -static double gauss_seidel2_SOR(double const M[XY][4], double omega,
> - double lambda[XY], double lambda_bound)
> +static double gaussSeidel2Sor(double const M[XY][4], double omega,
> + double lambda[XY], double lambdaBound)
> {
> - const double min = 1 - lambda_bound, max = 1 + lambda_bound;
> - double old_lambda[XY];
> + const double min = 1 - lambdaBound, max = 1 + lambdaBound;
> + double oldLambda[XY];
> int i;
> for (i = 0; i < XY; i++)
> - old_lambda[i] = lambda[i];
> - lambda[0] = compute_lambda_bottom_start(0, M, lambda);
> + oldLambda[i] = lambda[i];
> + lambda[0] = computeLambdaBottomStart(0, M, lambda);
> lambda[0] = std::clamp(lambda[0], min, max);
> for (i = 1; i < X; i++) {
> - lambda[i] = compute_lambda_bottom(i, M, lambda);
> + lambda[i] = computeLambdaBottom(i, M, lambda);
> lambda[i] = std::clamp(lambda[i], min, max);
> }
> for (; i < XY - X; i++) {
> - lambda[i] = compute_lambda_interior(i, M, lambda);
> + lambda[i] = computeLambdaInterior(i, M, lambda);
> lambda[i] = std::clamp(lambda[i], min, max);
> }
> for (; i < XY - 1; i++) {
> - lambda[i] = compute_lambda_top(i, M, lambda);
> + lambda[i] = computeLambdaTop(i, M, lambda);
> lambda[i] = std::clamp(lambda[i], min, max);
> }
> - lambda[i] = compute_lambda_top_end(i, M, lambda);
> + lambda[i] = computeLambdaTopEnd(i, M, lambda);
> lambda[i] = std::clamp(lambda[i], min, max);
> // Also solve the system from bottom to top, to help spread the updates
> // better.
> - lambda[i] = compute_lambda_top_end(i, M, lambda);
> + lambda[i] = computeLambdaTopEnd(i, M, lambda);
> lambda[i] = std::clamp(lambda[i], min, max);
> for (i = XY - 2; i >= XY - X; i--) {
> - lambda[i] = compute_lambda_top(i, M, lambda);
> + lambda[i] = computeLambdaTop(i, M, lambda);
> lambda[i] = std::clamp(lambda[i], min, max);
> }
> for (; i >= X; i--) {
> - lambda[i] = compute_lambda_interior(i, M, lambda);
> + lambda[i] = computeLambdaInterior(i, M, lambda);
> lambda[i] = std::clamp(lambda[i], min, max);
> }
> for (; i >= 1; i--) {
> - lambda[i] = compute_lambda_bottom(i, M, lambda);
> + lambda[i] = computeLambdaBottom(i, M, lambda);
> lambda[i] = std::clamp(lambda[i], min, max);
> }
> - lambda[0] = compute_lambda_bottom_start(0, M, lambda);
> + lambda[0] = computeLambdaBottomStart(0, M, lambda);
> lambda[0] = std::clamp(lambda[0], min, max);
> - double max_diff = 0;
> + double maxDiff = 0;
> for (i = 0; i < XY; i++) {
> - lambda[i] = old_lambda[i] + (lambda[i] - old_lambda[i]) * omega;
> - if (fabs(lambda[i] - old_lambda[i]) > fabs(max_diff))
> - max_diff = lambda[i] - old_lambda[i];
> + lambda[i] = oldLambda[i] + (lambda[i] - oldLambda[i]) * omega;
> + if (fabs(lambda[i] - oldLambda[i]) > fabs(maxDiff))
> + maxDiff = lambda[i] - oldLambda[i];
> }
> - return max_diff;
> + return maxDiff;
> }
>
> // Normalise the values so that the smallest value is 1.
> @@ -683,105 +656,99 @@ static void reaverage(Span<double> data)
> d *= ratio;
> }
>
> -static void run_matrix_iterations(double const C[XY], double lambda[XY],
> - double const W[XY][4], double omega,
> - int n_iter, double threshold, double lambda_bound)
> +static void runMatrixIterations(double const C[XY], double lambda[XY],
> + double const W[XY][4], double omega,
> + int nIter, double threshold, double lambdaBound)
> {
> double M[XY][4];
> - construct_M(C, W, M);
> - double last_max_diff = std::numeric_limits<double>::max();
> - for (int i = 0; i < n_iter; i++) {
> - double max_diff = fabs(gauss_seidel2_SOR(M, omega, lambda, lambda_bound));
> - if (max_diff < threshold) {
> + constructM(C, W, M);
> + double lastMaxDiff = std::numeric_limits<double>::max();
> + for (int i = 0; i < nIter; i++) {
> + double maxDiff = fabs(gaussSeidel2Sor(M, omega, lambda, lambdaBound));
> + if (maxDiff < threshold) {
> LOG(RPiAlsc, Debug)
> << "Stop after " << i + 1 << " iterations";
> break;
> }
> // this happens very occasionally (so make a note), though
> // doesn't seem to matter
> - if (max_diff > last_max_diff)
> + if (maxDiff > lastMaxDiff)
> LOG(RPiAlsc, Debug)
> << "Iteration " << i << ": max_diff gone up "
s/max_diff/maxDiff/
> - << last_max_diff << " to " << max_diff;
> - last_max_diff = max_diff;
> + << lastMaxDiff << " to " << maxDiff;
> + lastMaxDiff = maxDiff;
> }
> // We're going to normalise the lambdas so the total average is 1.
> reaverage({ lambda, XY });
> }
>
> -static void add_luminance_rb(double result[XY], double const lambda[XY],
> - double const luminance_lut[XY],
> - double luminance_strength)
> +static void addLuminanceRb(double result[XY], double const lambda[XY],
> + double const luminanceLut[XY],
> + double luminanceStrength)
> {
> for (int i = 0; i < XY; i++)
> - result[i] = lambda[i] *
> - ((luminance_lut[i] - 1) * luminance_strength + 1);
> + result[i] = lambda[i] * ((luminanceLut[i] - 1) * luminanceStrength + 1);
> }
>
> -static void add_luminance_g(double result[XY], double lambda,
> - double const luminance_lut[XY],
> - double luminance_strength)
> +static void addLuminanceG(double result[XY], double lambda,
> + double const luminanceLut[XY],
> + double luminanceStrength)
> {
> for (int i = 0; i < XY; i++)
> - result[i] = lambda *
> - ((luminance_lut[i] - 1) * luminance_strength + 1);
> + result[i] = lambda * ((luminanceLut[i] - 1) * luminanceStrength + 1);
> }
>
> -void add_luminance_to_tables(double results[3][Y][X], double const lambda_r[XY],
> - double lambda_g, double const lambda_b[XY],
> - double const luminance_lut[XY],
> - double luminance_strength)
> +void addLuminanceToTables(double results[3][Y][X], double const lambdaR[XY],
> + double lambdaG, double const lambdaB[XY],
> + double const luminanceLut[XY],
> + double luminanceStrength)
> {
> - add_luminance_rb((double *)results[0], lambda_r, luminance_lut,
> - luminance_strength);
> - add_luminance_g((double *)results[1], lambda_g, luminance_lut,
> - luminance_strength);
> - add_luminance_rb((double *)results[2], lambda_b, luminance_lut,
> - luminance_strength);
> + addLuminanceRb((double *)results[0], lambdaR, luminanceLut, luminanceStrength);
> + addLuminanceG((double *)results[1], lambdaG, luminanceLut, luminanceStrength);
> + addLuminanceRb((double *)results[2], lambdaB, luminanceLut, luminanceStrength);
> normalise((double *)results, 3 * XY);
> }
>
> void Alsc::doAlsc()
> {
> - double Cr[XY], Cb[XY], Wr[XY][4], Wb[XY][4], cal_table_r[XY],
> - cal_table_b[XY], cal_table_tmp[XY];
> + double cr[XY], cb[XY], wr[XY][4], wb[XY][4], calTableR[XY], calTableB[XY], calTableTmp[XY];
> // Calculate our R/B ("Cr"/"Cb") colour statistics, and assess which are
> // usable.
> - calculate_Cr_Cb(statistics_, Cr, Cb, config_.min_count, config_.min_G);
> + calculateCrCb(statistics_, cr, cb, config_.minCount, config_.minG);
> // Fetch the new calibrations (if any) for this CT. Resample them in
> // case the camera mode is not full-frame.
> - get_cal_table(ct_, config_.calibrations_Cr, cal_table_tmp);
> - resample_cal_table(cal_table_tmp, camera_mode_, cal_table_r);
> - get_cal_table(ct_, config_.calibrations_Cb, cal_table_tmp);
> - resample_cal_table(cal_table_tmp, camera_mode_, cal_table_b);
> + getCalTable(ct_, config_.calibrationsCr, calTableTmp);
> + resampleCalTable(calTableTmp, cameraMode_, calTableR);
> + getCalTable(ct_, config_.calibrationsCb, calTableTmp);
> + resampleCalTable(calTableTmp, cameraMode_, calTableB);
> // You could print out the cal tables for this image here, if you're
> // tuning the algorithm...
> // Apply any calibration to the statistics, so the adaptive algorithm
> // makes only the extra adjustments.
> - apply_cal_table(cal_table_r, Cr);
> - apply_cal_table(cal_table_b, Cb);
> + applyCalTable(calTableR, cr);
> + applyCalTable(calTableB, cb);
> // Compute weights between zones.
> - compute_W(Cr, config_.sigma_Cr, Wr);
> - compute_W(Cb, config_.sigma_Cb, Wb);
> + computeW(cr, config_.sigmaCr, wr);
> + computeW(cb, config_.sigmaCb, wb);
> // Run Gauss-Seidel iterations over the resulting matrix, for R and B.
> - run_matrix_iterations(Cr, lambda_r_, Wr, config_.omega, config_.n_iter,
> - config_.threshold, config_.lambda_bound);
> - run_matrix_iterations(Cb, lambda_b_, Wb, config_.omega, config_.n_iter,
> - config_.threshold, config_.lambda_bound);
> + runMatrixIterations(cr, lambdaR_, wr, config_.omega, config_.nIter,
> + config_.threshold, config_.lambdaBound);
> + runMatrixIterations(cb, lambdaB_, wb, config_.omega, config_.nIter,
> + config_.threshold, config_.lambdaBound);
> // Fold the calibrated gains into our final lambda values. (Note that on
> // the next run, we re-start with the lambda values that don't have the
> // calibration gains included.)
> - compensate_lambdas_for_cal(cal_table_r, lambda_r_, async_lambda_r_);
> - compensate_lambdas_for_cal(cal_table_b, lambda_b_, async_lambda_b_);
> + compensateLambdasForCal(calTableR, lambdaR_, asyncLambdaR_);
> + compensateLambdasForCal(calTableB, lambdaB_, asyncLambdaB_);
> // Fold in the luminance table at the appropriate strength.
> - add_luminance_to_tables(async_results_, async_lambda_r_, 1.0,
> - async_lambda_b_, luminance_table_,
> - config_.luminance_strength);
> + addLuminanceToTables(asyncResults_, asyncLambdaR_, 1.0,
> + asyncLambdaB_, luminanceTable_,
> + config_.luminanceStrength);
> }
>
> // Register algorithm with the system.
> -static Algorithm *Create(Controller *controller)
> +static Algorithm *create(Controller *controller)
> {
> return (Algorithm *)new Alsc(controller);
> }
> -static RegisterAlgorithm reg(NAME, &Create);
> +static RegisterAlgorithm reg(NAME, &create);
> diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.hpp b/src/ipa/raspberrypi/controller/rpi/alsc.hpp
> index d1dbe0d1d22d..7a0949d1ccc5 100644
> --- a/src/ipa/raspberrypi/controller/rpi/alsc.hpp
> +++ b/src/ipa/raspberrypi/controller/rpi/alsc.hpp
> @@ -24,24 +24,24 @@ struct AlscCalibration {
>
> struct AlscConfig {
> // Only repeat the ALSC calculation every "this many" frames
> - uint16_t frame_period;
> + uint16_t framePeriod;
> // number of initial frames for which speed taken as 1.0 (maximum)
> - uint16_t startup_frames;
> + uint16_t startupFrames;
> // IIR filter speed applied to algorithm results
> double speed;
> - double sigma_Cr;
> - double sigma_Cb;
> - double min_count;
> - uint16_t min_G;
> + double sigmaCr;
> + double sigmaCb;
> + double minCount;
> + uint16_t minG;
> double omega;
> - uint32_t n_iter;
> - double luminance_lut[ALSC_CELLS_X * ALSC_CELLS_Y];
> - double luminance_strength;
> - std::vector<AlscCalibration> calibrations_Cr;
> - std::vector<AlscCalibration> calibrations_Cb;
> - double default_ct; // colour temperature if no metadata found
> + uint32_t nIter;
> + double luminanceLut[ALSC_CELLS_X * ALSC_CELLS_Y];
> + double luminanceStrength;
> + std::vector<AlscCalibration> calibrationsCr;
> + std::vector<AlscCalibration> calibrationsCb;
> + double defaultCt; // colour temperature if no metadata found
> double threshold; // iteration termination threshold
> - double lambda_bound; // upper/lower bound for lambda from a value of 1
> + double lambdaBound; // upper/lower bound for lambda from a value of 1
> };
>
> class Alsc : public Algorithm
> @@ -49,58 +49,58 @@ class Alsc : public Algorithm
> public:
> Alsc(Controller *controller = NULL);
> ~Alsc();
> - char const *Name() const override;
> - void Initialise() override;
> - void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override;
> - void Read(boost::property_tree::ptree const ¶ms) override;
> - void Prepare(Metadata *image_metadata) override;
> - void Process(StatisticsPtr &stats, Metadata *image_metadata) override;
> + char const *name() const override;
> + void initialise() override;
> + void switchMode(CameraMode const &cameraMode, Metadata *metadata) override;
> + void read(boost::property_tree::ptree const ¶ms) override;
> + void prepare(Metadata *imageMetadata) override;
> + void process(StatisticsPtr &stats, Metadata *imageMetadata) override;
>
> private:
> // configuration is read-only, and available to both threads
> AlscConfig config_;
> - bool first_time_;
> - CameraMode camera_mode_;
> - double luminance_table_[ALSC_CELLS_X * ALSC_CELLS_Y];
> - std::thread async_thread_;
> + bool firstTime_;
> + CameraMode cameraMode_;
> + double luminanceTable_[ALSC_CELLS_X * ALSC_CELLS_Y];
> + std::thread asyncThread_;
> void asyncFunc(); // asynchronous thread function
> std::mutex mutex_;
> // condvar for async thread to wait on
> - std::condition_variable async_signal_;
> + std::condition_variable asyncSignal_;
> // condvar for synchronous thread to wait on
> - std::condition_variable sync_signal_;
> + std::condition_variable syncSignal_;
> // for sync thread to check if async thread finished (requires mutex)
> - bool async_finished_;
> + bool asyncFinished_;
> // for async thread to check if it's been told to run (requires mutex)
> - bool async_start_;
> + bool asyncStart_;
> // for async thread to check if it's been told to quit (requires mutex)
> - bool async_abort_;
> + bool asyncAbort_;
>
> // 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_;
> - // counts up to startup_frames
> - int frame_count_;
> - // counts up to startup_frames for Process function
> - int frame_count2_;
> - double sync_results_[3][ALSC_CELLS_Y][ALSC_CELLS_X];
> - double prev_sync_results_[3][ALSC_CELLS_Y][ALSC_CELLS_X];
> + bool asyncStarted_;
> + // counts up to framePeriod before restarting the async thread
> + int framePhase_;
> + // counts up to startupFrames
> + int frameCount_;
> + // counts up to startupFrames for Process function
> + int frameCount2_;
> + double syncResults_[3][ALSC_CELLS_Y][ALSC_CELLS_X];
> + double prevSyncResults_[3][ALSC_CELLS_Y][ALSC_CELLS_X];
> void waitForAysncThread();
> // 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, Metadata *image_metadata);
> + void restartAsync(StatisticsPtr &stats, Metadata *imageMetadata);
> // copy out the results from the async thread so that it can be restarted
> void fetchAsyncResults();
> double ct_;
> bcm2835_isp_stats_region statistics_[ALSC_CELLS_Y * ALSC_CELLS_X];
> - double async_results_[3][ALSC_CELLS_Y][ALSC_CELLS_X];
> - double async_lambda_r_[ALSC_CELLS_X * ALSC_CELLS_Y];
> - double async_lambda_b_[ALSC_CELLS_X * ALSC_CELLS_Y];
> + double asyncResults_[3][ALSC_CELLS_Y][ALSC_CELLS_X];
> + double asyncLambdaR_[ALSC_CELLS_X * ALSC_CELLS_Y];
> + double asyncLambdaB_[ALSC_CELLS_X * ALSC_CELLS_Y];
> void doAlsc();
> - double lambda_r_[ALSC_CELLS_X * ALSC_CELLS_Y];
> - double lambda_b_[ALSC_CELLS_X * ALSC_CELLS_Y];
> + double lambdaR_[ALSC_CELLS_X * ALSC_CELLS_Y];
> + double lambdaB_[ALSC_CELLS_X * ALSC_CELLS_Y];
> };
>
> } // namespace RPiController
> diff --git a/src/ipa/raspberrypi/controller/rpi/awb.cpp b/src/ipa/raspberrypi/controller/rpi/awb.cpp
> index d4c934473832..74449c8c7591 100644
> --- a/src/ipa/raspberrypi/controller/rpi/awb.cpp
> +++ b/src/ipa/raspberrypi/controller/rpi/awb.cpp
> @@ -24,33 +24,33 @@ LOG_DEFINE_CATEGORY(RPiAwb)
> // todo - the locking in this algorithm needs some tidying up as has been done
> // elsewhere (ALSC and AGC).
>
> -void AwbMode::Read(boost::property_tree::ptree const ¶ms)
> +void AwbMode::read(boost::property_tree::ptree const ¶ms)
> {
> - ct_lo = params.get<double>("lo");
> - ct_hi = params.get<double>("hi");
> + ctLo = params.get<double>("lo");
> + ctHi = params.get<double>("hi");
> }
>
> -void AwbPrior::Read(boost::property_tree::ptree const ¶ms)
> +void AwbPrior::read(boost::property_tree::ptree const ¶ms)
> {
> lux = params.get<double>("lux");
> - prior.Read(params.get_child("prior"));
> + prior.read(params.get_child("prior"));
> }
>
> -static void read_ct_curve(Pwl &ct_r, Pwl &ct_b,
> - boost::property_tree::ptree const ¶ms)
> +static void readCtCurve(Pwl &ctR, Pwl &ctB,
> + boost::property_tree::ptree const ¶ms)
> {
> int num = 0;
> for (auto it = params.begin(); it != params.end(); it++) {
> double ct = it->second.get_value<double>();
> - assert(it == params.begin() || ct != ct_r.Domain().end);
> + assert(it == params.begin() || ct != ctR.domain().end);
> if (++it == params.end())
> throw std::runtime_error(
> "AwbConfig: incomplete CT curve entry");
> - ct_r.Append(ct, it->second.get_value<double>());
> + ctR.append(ct, it->second.get_value<double>());
> if (++it == params.end())
> throw std::runtime_error(
> "AwbConfig: incomplete CT curve entry");
> - ct_b.Append(ct, it->second.get_value<double>());
> + ctB.append(ct, it->second.get_value<double>());
> num++;
> }
> if (num < 2)
> @@ -58,22 +58,21 @@ static void read_ct_curve(Pwl &ct_r, Pwl &ct_b,
> "AwbConfig: insufficient points in CT curve");
> }
>
> -void AwbConfig::Read(boost::property_tree::ptree const ¶ms)
> +void AwbConfig::read(boost::property_tree::ptree const ¶ms)
> {
> bayes = params.get<int>("bayes", 1);
> - frame_period = params.get<uint16_t>("frame_period", 10);
> - startup_frames = params.get<uint16_t>("startup_frames", 10);
> - convergence_frames = params.get<unsigned int>("convergence_frames", 3);
> + framePeriod = params.get<uint16_t>("framePeriod", 10);
> + startupFrames = params.get<uint16_t>("startupFrames", 10);
> + convergenceFrames = params.get<unsigned int>("convergence_frames", 3);
> speed = params.get<double>("speed", 0.05);
> if (params.get_child_optional("ct_curve"))
> - read_ct_curve(ct_r, ct_b, params.get_child("ct_curve"));
> + readCtCurve(ctR, ctB, params.get_child("ct_curve"));
> if (params.get_child_optional("priors")) {
> for (auto &p : params.get_child("priors")) {
> AwbPrior prior;
> - prior.Read(p.second);
> + prior.read(p.second);
> if (!priors.empty() && prior.lux <= priors.back().lux)
> - throw std::runtime_error(
> - "AwbConfig: Prior must be ordered in increasing lux value");
> + throw std::runtime_error("AwbConfig: Prior must be ordered in increasing lux value");
> priors.push_back(prior);
> }
> if (priors.empty())
> @@ -82,177 +81,170 @@ void AwbConfig::Read(boost::property_tree::ptree const ¶ms)
> }
> if (params.get_child_optional("modes")) {
> for (auto &p : params.get_child("modes")) {
> - modes[p.first].Read(p.second);
> - if (default_mode == nullptr)
> - default_mode = &modes[p.first];
> + modes[p.first].read(p.second);
> + if (defaultMode == nullptr)
> + defaultMode = &modes[p.first];
> }
> - if (default_mode == nullptr)
> - throw std::runtime_error(
> - "AwbConfig: no AWB modes configured");
> + if (defaultMode == nullptr)
> + throw std::runtime_error("AwbConfig: no AWB modes configured");
> }
> - min_pixels = params.get<double>("min_pixels", 16.0);
> - min_G = params.get<uint16_t>("min_G", 32);
> - min_regions = params.get<uint32_t>("min_regions", 10);
> - delta_limit = params.get<double>("delta_limit", 0.2);
> - coarse_step = params.get<double>("coarse_step", 0.2);
> - transverse_pos = params.get<double>("transverse_pos", 0.01);
> - transverse_neg = params.get<double>("transverse_neg", 0.01);
> - if (transverse_pos <= 0 || transverse_neg <= 0)
> - throw std::runtime_error(
> - "AwbConfig: transverse_pos/neg must be > 0");
> - sensitivity_r = params.get<double>("sensitivity_r", 1.0);
> - sensitivity_b = params.get<double>("sensitivity_b", 1.0);
> + minPixels = params.get<double>("min_pixels", 16.0);
> + minG = params.get<uint16_t>("min_G", 32);
> + minRegions = params.get<uint32_t>("min_regions", 10);
> + deltaLimit = params.get<double>("delta_limit", 0.2);
> + coarseStep = params.get<double>("coarse_step", 0.2);
> + transversePos = params.get<double>("transverse_pos", 0.01);
> + transverseNeg = params.get<double>("transverse_neg", 0.01);
> + if (transversePos <= 0 || transverseNeg <= 0)
> + throw std::runtime_error("AwbConfig: transverse_pos/neg must be > 0");
> + sensitivityR = params.get<double>("sensitivity_r", 1.0);
> + sensitivityB = params.get<double>("sensitivity_b", 1.0);
> if (bayes) {
> - if (ct_r.Empty() || ct_b.Empty() || priors.empty() ||
> - default_mode == nullptr) {
> + if (ctR.empty() || ctB.empty() || priors.empty() ||
> + defaultMode == nullptr) {
> LOG(RPiAwb, Warning)
> << "Bayesian AWB mis-configured - switch to Grey method";
> bayes = false;
> }
> }
> - fast = params.get<int>(
> - "fast", bayes); // default to fast for Bayesian, otherwise slow
> - whitepoint_r = params.get<double>("whitepoint_r", 0.0);
> - whitepoint_b = params.get<double>("whitepoint_b", 0.0);
> + fast = params.get<int>("fast", bayes); // default to fast for Bayesian, otherwise slow
> + whitepointR = params.get<double>("whitepoint_r", 0.0);
> + whitepointB = params.get<double>("whitepoint_b", 0.0);
> if (bayes == false)
> - sensitivity_r = sensitivity_b =
> - 1.0; // nor do sensitivities make any sense
> + sensitivityR = sensitivityB = 1.0; // nor do sensitivities make any sense
> }
>
> Awb::Awb(Controller *controller)
> : AwbAlgorithm(controller)
> {
> - async_abort_ = async_start_ = async_started_ = async_finished_ = false;
> + asyncAbort_ = asyncStart_ = asyncStarted_ = asyncFinished_ = false;
> mode_ = nullptr;
> - manual_r_ = manual_b_ = 0.0;
> - first_switch_mode_ = true;
> - async_thread_ = std::thread(std::bind(&Awb::asyncFunc, this));
> + manualR_ = manualB_ = 0.0;
> + firstSwitchMode_ = true;
> + asyncThread_ = std::thread(std::bind(&Awb::asyncFunc, this));
> }
>
> Awb::~Awb()
> {
> {
> std::lock_guard<std::mutex> lock(mutex_);
> - async_abort_ = true;
> + asyncAbort_ = true;
> }
> - async_signal_.notify_one();
> - async_thread_.join();
> + asyncSignal_.notify_one();
> + asyncThread_.join();
> }
>
> -char const *Awb::Name() const
> +char const *Awb::name() const
> {
> return NAME;
> }
>
> -void Awb::Read(boost::property_tree::ptree const ¶ms)
> +void Awb::read(boost::property_tree::ptree const ¶ms)
> {
> - config_.Read(params);
> + config_.read(params);
> }
>
> -void Awb::Initialise()
> +void Awb::initialise()
> {
> - frame_count_ = frame_phase_ = 0;
> + frameCount_ = framePhase_ = 0;
> // Put something sane into the status that we are filtering towards,
> // just in case the first few frames don't have anything meaningful in
> // them.
> - if (!config_.ct_r.Empty() && !config_.ct_b.Empty()) {
> - sync_results_.temperature_K = config_.ct_r.Domain().Clip(4000);
> - sync_results_.gain_r =
> - 1.0 / config_.ct_r.Eval(sync_results_.temperature_K);
> - sync_results_.gain_g = 1.0;
> - sync_results_.gain_b =
> - 1.0 / config_.ct_b.Eval(sync_results_.temperature_K);
> + if (!config_.ctR.empty() && !config_.ctB.empty()) {
> + syncResults_.temperatureK = config_.ctR.domain().clip(4000);
> + syncResults_.gainR = 1.0 / config_.ctR.eval(syncResults_.temperatureK);
> + syncResults_.gainG = 1.0;
> + syncResults_.gainB = 1.0 / config_.ctB.eval(syncResults_.temperatureK);
> } else {
> // random values just to stop the world blowing up
> - sync_results_.temperature_K = 4500;
> - sync_results_.gain_r = sync_results_.gain_g =
> - sync_results_.gain_b = 1.0;
> + syncResults_.temperatureK = 4500;
> + syncResults_.gainR = syncResults_.gainG = syncResults_.gainB = 1.0;
> }
> - prev_sync_results_ = sync_results_;
> - async_results_ = sync_results_;
> + prevSyncResults_ = syncResults_;
> + asyncResults_ = syncResults_;
> }
>
> -bool Awb::IsPaused() const
> +bool Awb::isPaused() const
> {
> return false;
> }
>
> -void Awb::Pause()
> +void Awb::pause()
> {
> // "Pause" by fixing everything to the most recent values.
> - manual_r_ = sync_results_.gain_r = prev_sync_results_.gain_r;
> - manual_b_ = sync_results_.gain_b = prev_sync_results_.gain_b;
> - sync_results_.gain_g = prev_sync_results_.gain_g;
> - sync_results_.temperature_K = prev_sync_results_.temperature_K;
> + manualR_ = syncResults_.gainR = prevSyncResults_.gainR;
> + manualB_ = syncResults_.gainB = prevSyncResults_.gainB;
> + syncResults_.gainG = prevSyncResults_.gainG;
> + syncResults_.temperatureK = prevSyncResults_.temperatureK;
> }
>
> -void Awb::Resume()
> +void Awb::resume()
> {
> - manual_r_ = 0.0;
> - manual_b_ = 0.0;
> + manualR_ = 0.0;
> + manualB_ = 0.0;
> }
>
> -unsigned int Awb::GetConvergenceFrames() const
> +unsigned int Awb::getConvergenceFrames() const
> {
> // If not in auto mode, there is no convergence
> // to happen, so no need to drop any frames - return zero.
> if (!isAutoEnabled())
> return 0;
> else
> - return config_.convergence_frames;
> + return config_.convergenceFrames;
> }
>
> -void Awb::SetMode(std::string const &mode_name)
> +void Awb::setMode(std::string const &modeName)
> {
> - mode_name_ = mode_name;
> + modeName_ = modeName;
> }
>
> -void Awb::SetManualGains(double manual_r, double manual_b)
> +void Awb::setManualGains(double manualR, double manualB)
> {
> // If any of these are 0.0, we swich back to auto.
> - manual_r_ = manual_r;
> - manual_b_ = manual_b;
> + manualR_ = manualR;
> + manualB_ = manualB;
> // If not in auto mode, set these values into the sync_results which
s/sync_results/syncResults/
> // means that Prepare() will adopt them immediately.
> if (!isAutoEnabled()) {
> - sync_results_.gain_r = prev_sync_results_.gain_r = manual_r_;
> - sync_results_.gain_g = prev_sync_results_.gain_g = 1.0;
> - sync_results_.gain_b = prev_sync_results_.gain_b = manual_b_;
> + syncResults_.gainR = prevSyncResults_.gainR = manualR_;
> + syncResults_.gainG = prevSyncResults_.gainG = 1.0;
> + syncResults_.gainB = prevSyncResults_.gainB = manualB_;
> }
> }
>
> -void Awb::SwitchMode([[maybe_unused]] CameraMode const &camera_mode,
> +void Awb::switchMode([[maybe_unused]] CameraMode const &cameraMode,
> Metadata *metadata)
> {
> // On the first mode switch we'll have no meaningful colour
> // temperature, so try to dead reckon one if in manual mode.
> - if (!isAutoEnabled() && first_switch_mode_ && config_.bayes) {
> - Pwl ct_r_inverse = config_.ct_r.Inverse();
> - Pwl ct_b_inverse = config_.ct_b.Inverse();
> - double ct_r = ct_r_inverse.Eval(ct_r_inverse.Domain().Clip(1 / manual_r_));
> - double ct_b = ct_b_inverse.Eval(ct_b_inverse.Domain().Clip(1 / manual_b_));
> - prev_sync_results_.temperature_K = (ct_r + ct_b) / 2;
> - sync_results_.temperature_K = prev_sync_results_.temperature_K;
> + if (!isAutoEnabled() && firstSwitchMode_ && config_.bayes) {
> + Pwl ctRInverse = config_.ctR.inverse();
> + Pwl ctBInverse = config_.ctB.inverse();
> + double ctR = ctRInverse.eval(ctRInverse.domain().clip(1 / manualR_));
> + double ctB = ctBInverse.eval(ctBInverse.domain().clip(1 / manualB_));
> + prevSyncResults_.temperatureK = (ctR + ctB) / 2;
> + syncResults_.temperatureK = prevSyncResults_.temperatureK;
> }
> // Let other algorithms know the current white balance values.
> - metadata->Set("awb.status", prev_sync_results_);
> - first_switch_mode_ = false;
> + metadata->set("awb.status", prevSyncResults_);
> + firstSwitchMode_ = false;
> }
>
> bool Awb::isAutoEnabled() const
> {
> - return manual_r_ == 0.0 || manual_b_ == 0.0;
> + return manualR_ == 0.0 || manualB_ == 0.0;
> }
>
> void Awb::fetchAsyncResults()
> {
> LOG(RPiAwb, Debug) << "Fetch AWB results";
> - async_finished_ = false;
> - async_started_ = false;
> + asyncFinished_ = false;
> + asyncStarted_ = false;
> // It's possible manual gains could be set even while the async
> // thread was running, so only copy the results if still in auto mode.
> if (isAutoEnabled())
> - sync_results_ = async_results_;
> + syncResults_ = asyncResults_;
> }
>
> void Awb::restartAsync(StatisticsPtr &stats, double lux)
> @@ -261,75 +253,74 @@ void Awb::restartAsync(StatisticsPtr &stats, double lux)
> // this makes a new reference which belongs to the asynchronous thread
> statistics_ = stats;
> // store the mode as it could technically change
> - auto m = config_.modes.find(mode_name_);
> + auto m = config_.modes.find(modeName_);
> mode_ = m != config_.modes.end()
> ? &m->second
> - : (mode_ == nullptr ? config_.default_mode : mode_);
> + : (mode_ == nullptr ? config_.defaultMode : mode_);
> lux_ = lux;
> - frame_phase_ = 0;
> - async_started_ = true;
> - size_t len = mode_name_.copy(async_results_.mode,
> - sizeof(async_results_.mode) - 1);
> - async_results_.mode[len] = '\0';
> + framePhase_ = 0;
> + asyncStarted_ = true;
> + size_t len = modeName_.copy(asyncResults_.mode,
> + sizeof(asyncResults_.mode) - 1);
> + asyncResults_.mode[len] = '\0';
> {
> std::lock_guard<std::mutex> lock(mutex_);
> - async_start_ = true;
> + asyncStart_ = true;
> }
> - async_signal_.notify_one();
> + asyncSignal_.notify_one();
> }
>
> -void Awb::Prepare(Metadata *image_metadata)
> +void Awb::prepare(Metadata *imageMetadata)
> {
> - if (frame_count_ < (int)config_.startup_frames)
> - frame_count_++;
> - double speed = frame_count_ < (int)config_.startup_frames
> + if (frameCount_ < (int)config_.startupFrames)
> + frameCount_++;
> + double speed = frameCount_ < (int)config_.startupFrames
> ? 1.0
> : config_.speed;
> LOG(RPiAwb, Debug)
> - << "frame_count " << frame_count_ << " speed " << speed;
> + << "frame_count " << frameCount_ << " speed " << speed;
> {
> std::unique_lock<std::mutex> lock(mutex_);
> - if (async_started_ && async_finished_)
> + if (asyncStarted_ && asyncFinished_)
> fetchAsyncResults();
> }
> // Finally apply IIR filter to results and put into metadata.
> - memcpy(prev_sync_results_.mode, sync_results_.mode,
> - sizeof(prev_sync_results_.mode));
> - prev_sync_results_.temperature_K =
> - speed * sync_results_.temperature_K +
> - (1.0 - speed) * prev_sync_results_.temperature_K;
> - prev_sync_results_.gain_r = speed * sync_results_.gain_r +
> - (1.0 - speed) * prev_sync_results_.gain_r;
> - prev_sync_results_.gain_g = speed * sync_results_.gain_g +
> - (1.0 - speed) * prev_sync_results_.gain_g;
> - prev_sync_results_.gain_b = speed * sync_results_.gain_b +
> - (1.0 - speed) * prev_sync_results_.gain_b;
> - image_metadata->Set("awb.status", prev_sync_results_);
> + memcpy(prevSyncResults_.mode, syncResults_.mode,
> + sizeof(prevSyncResults_.mode));
> + prevSyncResults_.temperatureK = speed * syncResults_.temperatureK +
> + (1.0 - speed) * prevSyncResults_.temperatureK;
> + prevSyncResults_.gainR = speed * syncResults_.gainR +
> + (1.0 - speed) * prevSyncResults_.gainR;
> + prevSyncResults_.gainG = speed * syncResults_.gainG +
> + (1.0 - speed) * prevSyncResults_.gainG;
> + prevSyncResults_.gainB = speed * syncResults_.gainB +
> + (1.0 - speed) * prevSyncResults_.gainB;
> + imageMetadata->set("awb.status", prevSyncResults_);
> LOG(RPiAwb, Debug)
> - << "Using AWB gains r " << prev_sync_results_.gain_r << " g "
> - << prev_sync_results_.gain_g << " b "
> - << prev_sync_results_.gain_b;
> + << "Using AWB gains r " << prevSyncResults_.gainR << " g "
> + << prevSyncResults_.gainG << " b "
> + << prevSyncResults_.gainB;
> }
>
> -void Awb::Process(StatisticsPtr &stats, Metadata *image_metadata)
> +void Awb::process(StatisticsPtr &stats, Metadata *imageMetadata)
> {
> // Count frames since we last poked the async thread.
> - if (frame_phase_ < (int)config_.frame_period)
> - frame_phase_++;
> - LOG(RPiAwb, Debug) << "frame_phase " << frame_phase_;
> + if (framePhase_ < (int)config_.framePeriod)
> + framePhase_++;
> + LOG(RPiAwb, Debug) << "frame_phase " << framePhase_;
> // We do not restart the async thread if we're not in auto mode.
> if (isAutoEnabled() &&
> - (frame_phase_ >= (int)config_.frame_period ||
> - frame_count_ < (int)config_.startup_frames)) {
> + (framePhase_ >= (int)config_.framePeriod ||
> + frameCount_ < (int)config_.startupFrames)) {
> // Update any settings and any image metadata that we need.
> - struct LuxStatus lux_status = {};
> - lux_status.lux = 400; // in case no metadata
> - if (image_metadata->Get("lux.status", lux_status) != 0)
> + struct LuxStatus luxStatus = {};
> + luxStatus.lux = 400; // in case no metadata
> + if (imageMetadata->get("lux.status", luxStatus) != 0)
> LOG(RPiAwb, Debug) << "No lux metadata found";
> - LOG(RPiAwb, Debug) << "Awb lux value is " << lux_status.lux;
> + LOG(RPiAwb, Debug) << "Awb lux value is " << luxStatus.lux;
>
> - if (async_started_ == false)
> - restartAsync(stats, lux_status.lux);
> + if (asyncStarted_ == false)
> + restartAsync(stats, luxStatus.lux);
> }
> }
>
> @@ -338,32 +329,32 @@ void Awb::asyncFunc()
> while (true) {
> {
> std::unique_lock<std::mutex> lock(mutex_);
> - async_signal_.wait(lock, [&] {
> - return async_start_ || async_abort_;
> + asyncSignal_.wait(lock, [&] {
> + return asyncStart_ || asyncAbort_;
> });
> - async_start_ = false;
> - if (async_abort_)
> + asyncStart_ = false;
> + if (asyncAbort_)
> break;
> }
> doAwb();
> {
> std::lock_guard<std::mutex> lock(mutex_);
> - async_finished_ = true;
> + asyncFinished_ = true;
> }
> - sync_signal_.notify_one();
> + syncSignal_.notify_one();
> }
> }
>
> -static void generate_stats(std::vector<Awb::RGB> &zones,
> - bcm2835_isp_stats_region *stats, double min_pixels,
> - double min_G)
> +static void generateStats(std::vector<Awb::RGB> &zones,
> + bcm2835_isp_stats_region *stats, double minPixels,
> + double minG)
> {
> for (int i = 0; i < AWB_STATS_SIZE_X * AWB_STATS_SIZE_Y; i++) {
> Awb::RGB zone;
> double counted = stats[i].counted;
> - if (counted >= min_pixels) {
> + if (counted >= minPixels) {
> zone.G = stats[i].g_sum / counted;
> - if (zone.G >= min_G) {
> + if (zone.G >= minG) {
> zone.R = stats[i].r_sum / counted;
> zone.B = stats[i].b_sum / counted;
> zones.push_back(zone);
> @@ -377,32 +368,33 @@ void Awb::prepareStats()
> zones_.clear();
> // LSC has already been applied to the stats in this pipeline, so stop
> // any LSC compensation. We also ignore config_.fast in this version.
> - generate_stats(zones_, statistics_->awb_stats, config_.min_pixels,
> - config_.min_G);
> + generateStats(zones_, statistics_->awb_stats, config_.minPixels,
> + config_.minG);
> // we're done with these; we may as well relinquish our hold on the
> // pointer.
> statistics_.reset();
> // apply sensitivities, so values appear to come from our "canonical"
> // sensor.
> - for (auto &zone : zones_)
> - zone.R *= config_.sensitivity_r,
> - zone.B *= config_.sensitivity_b;
> + for (auto &zone : zones_) {
> + zone.R *= config_.sensitivityR;
> + zone.B *= config_.sensitivityB;
> + }
> }
>
> -double Awb::computeDelta2Sum(double gain_r, double gain_b)
> +double Awb::computeDelta2Sum(double gainR, double gainB)
> {
> // Compute the sum of the squared colour error (non-greyness) as it
> // appears in the log likelihood equation.
> - double delta2_sum = 0;
> + double delta2Sum = 0;
> for (auto &z : zones_) {
> - double delta_r = gain_r * z.R - 1 - config_.whitepoint_r;
> - double delta_b = gain_b * z.B - 1 - config_.whitepoint_b;
> - double delta2 = delta_r * delta_r + delta_b * delta_b;
> + double deltaR = gainR * z.R - 1 - config_.whitepointR;
> + double deltaB = gainB * z.B - 1 - config_.whitepointB;
> + double delta2 = deltaR * deltaR + deltaB * deltaB;
> //LOG(RPiAwb, Debug) << "delta_r " << delta_r << " delta_b " << delta_b << " delta2 " << delta2;
> - delta2 = std::min(delta2, config_.delta_limit);
> - delta2_sum += delta2;
> + delta2 = std::min(delta2, config_.deltaLimit);
> + delta2Sum += delta2;
> }
> - return delta2_sum;
> + return delta2Sum;
> }
>
> Pwl Awb::interpolatePrior()
> @@ -420,7 +412,7 @@ Pwl Awb::interpolatePrior()
> idx++;
> double lux0 = config_.priors[idx].lux,
> lux1 = config_.priors[idx + 1].lux;
> - return Pwl::Combine(config_.priors[idx].prior,
> + return Pwl::combine(config_.priors[idx].prior,
> config_.priors[idx + 1].prior,
> [&](double /*x*/, double y0, double y1) {
> return y0 + (y1 - y0) *
> @@ -429,62 +421,60 @@ Pwl Awb::interpolatePrior()
> }
> }
>
> -static double interpolate_quadatric(Pwl::Point const &A, Pwl::Point const &B,
> - Pwl::Point const &C)
> +static double interpolateQuadatric(Pwl::Point const &a, Pwl::Point const &b,
> + Pwl::Point const &c)
> {
> // Given 3 points on a curve, find the extremum of the function in that
> // interval by fitting a quadratic.
> const double eps = 1e-3;
> - Pwl::Point CA = C - A, BA = B - A;
> - double denominator = 2 * (BA.y * CA.x - CA.y * BA.x);
> + Pwl::Point ca = c - a, ba = b - a;
> + double denominator = 2 * (ba.y * ca.x - ca.y * ba.x);
> if (abs(denominator) > eps) {
> - double numerator = BA.y * CA.x * CA.x - CA.y * BA.x * BA.x;
> - double result = numerator / denominator + A.x;
> - return std::max(A.x, std::min(C.x, result));
> + double numerator = ba.y * ca.x * ca.x - ca.y * ba.x * ba.x;
> + double result = numerator / denominator + a.x;
> + return std::max(a.x, std::min(c.x, result));
> }
> // has degenerated to straight line segment
> - return A.y < C.y - eps ? A.x : (C.y < A.y - eps ? C.x : B.x);
> + return a.y < c.y - eps ? a.x : (c.y < a.y - eps ? c.x : b.x);
> }
>
> double Awb::coarseSearch(Pwl const &prior)
> {
> points_.clear(); // assume doesn't deallocate memory
> - size_t best_point = 0;
> - double t = mode_->ct_lo;
> - int span_r = 0, span_b = 0;
> + size_t bestPoint = 0;
> + double t = mode_->ctLo;
> + int spanR = 0, spanB = 0;
> // Step down the CT curve evaluating log likelihood.
> while (true) {
> - double r = config_.ct_r.Eval(t, &span_r);
> - double b = config_.ct_b.Eval(t, &span_b);
> - double gain_r = 1 / r, gain_b = 1 / b;
> - double delta2_sum = computeDelta2Sum(gain_r, gain_b);
> - double prior_log_likelihood =
> - prior.Eval(prior.Domain().Clip(t));
> - double final_log_likelihood = delta2_sum - prior_log_likelihood;
> + double r = config_.ctR.eval(t, &spanR);
> + double b = config_.ctB.eval(t, &spanB);
> + double gainR = 1 / r, gainB = 1 / b;
> + double delta2Sum = computeDelta2Sum(gainR, gainB);
> + double priorLogLikelihood = prior.eval(prior.domain().clip(t));
> + double finalLogLikelihood = delta2Sum - priorLogLikelihood;
> LOG(RPiAwb, Debug)
> - << "t: " << t << " gain_r " << gain_r << " gain_b "
> - << gain_b << " delta2_sum " << delta2_sum
> - << " prior " << prior_log_likelihood << " final "
> - << final_log_likelihood;
> - points_.push_back(Pwl::Point(t, final_log_likelihood));
> - if (points_.back().y < points_[best_point].y)
> - best_point = points_.size() - 1;
> - if (t == mode_->ct_hi)
> + << "t: " << t << " gain R " << gainR << " gain B "
> + << gainB << " delta2_sum " << delta2Sum
> + << " prior " << priorLogLikelihood << " final "
> + << finalLogLikelihood;
> + points_.push_back(Pwl::Point(t, finalLogLikelihood));
> + if (points_.back().y < points_[bestPoint].y)
> + bestPoint = points_.size() - 1;
> + if (t == mode_->ctHi)
> break;
> // for even steps along the r/b curve scale them by the current t
> - t = std::min(t + t / 10 * config_.coarse_step,
> - mode_->ct_hi);
> + t = std::min(t + t / 10 * config_.coarseStep, mode_->ctHi);
> }
> - t = points_[best_point].x;
> + t = points_[bestPoint].x;
> LOG(RPiAwb, Debug) << "Coarse search found CT " << t;
> // We have the best point of the search, but refine it with a quadratic
> // interpolation around its neighbours.
> if (points_.size() > 2) {
> - unsigned long bp = std::min(best_point, points_.size() - 2);
> - best_point = std::max(1UL, bp);
> - t = interpolate_quadatric(points_[best_point - 1],
> - points_[best_point],
> - points_[best_point + 1]);
> + unsigned long bp = std::min(bestPoint, points_.size() - 2);
> + bestPoint = std::max(1UL, bp);
> + t = interpolateQuadatric(points_[bestPoint - 1],
> + points_[bestPoint],
> + points_[bestPoint + 1]);
> LOG(RPiAwb, Debug)
> << "After quadratic refinement, coarse search has CT "
> << t;
> @@ -494,80 +484,76 @@ double Awb::coarseSearch(Pwl const &prior)
>
> void Awb::fineSearch(double &t, double &r, double &b, Pwl const &prior)
> {
> - int span_r = -1, span_b = -1;
> - config_.ct_r.Eval(t, &span_r);
> - config_.ct_b.Eval(t, &span_b);
> - double step = t / 10 * config_.coarse_step * 0.1;
> + int spanR = -1, spanB = -1;
> + config_.ctR.eval(t, &spanR);
> + config_.ctB.eval(t, &spanB);
> + double step = t / 10 * config_.coarseStep * 0.1;
> int nsteps = 5;
> - double r_diff = config_.ct_r.Eval(t + nsteps * step, &span_r) -
> - config_.ct_r.Eval(t - nsteps * step, &span_r);
> - double b_diff = config_.ct_b.Eval(t + nsteps * step, &span_b) -
> - config_.ct_b.Eval(t - nsteps * step, &span_b);
> - Pwl::Point transverse(b_diff, -r_diff);
> - if (transverse.Len2() < 1e-6)
> + double rDiff = config_.ctR.eval(t + nsteps * step, &spanR) -
> + config_.ctR.eval(t - nsteps * step, &spanR);
> + double bDiff = config_.ctB.eval(t + nsteps * step, &spanB) -
> + config_.ctB.eval(t - nsteps * step, &spanB);
> + Pwl::Point transverse(bDiff, -rDiff);
> + if (transverse.len2() < 1e-6)
> return;
> // unit vector orthogonal to the b vs. r function (pointing outwards
> // with r and b increasing)
> - transverse = transverse / transverse.Len();
> - double best_log_likelihood = 0, best_t = 0, best_r = 0, best_b = 0;
> - double transverse_range =
> - config_.transverse_neg + config_.transverse_pos;
> - const int MAX_NUM_DELTAS = 12;
> + transverse = transverse / transverse.len();
> + double bestLogLikelihood = 0, bestT = 0, bestR = 0, bestB = 0;
> + double transverseRange = config_.transverseNeg + config_.transversePos;
> + const int maxNumDeltas = 12;
> // a transverse step approximately every 0.01 r/b units
> - int num_deltas = floor(transverse_range * 100 + 0.5) + 1;
> - num_deltas = num_deltas < 3 ? 3 :
> - (num_deltas > MAX_NUM_DELTAS ? MAX_NUM_DELTAS : num_deltas);
> + int numDeltas = floor(transverseRange * 100 + 0.5) + 1;
> + numDeltas = numDeltas < 3 ? 3 : (numDeltas > maxNumDeltas ? maxNumDeltas : numDeltas);
> // Step down CT curve. March a bit further if the transverse range is
> // large.
> - nsteps += num_deltas;
> + nsteps += numDeltas;
> for (int i = -nsteps; i <= nsteps; i++) {
> - double t_test = t + i * step;
> - double prior_log_likelihood =
> - prior.Eval(prior.Domain().Clip(t_test));
> - double r_curve = config_.ct_r.Eval(t_test, &span_r);
> - double b_curve = config_.ct_b.Eval(t_test, &span_b);
> + double tTest = t + i * step;
> + double priorLogLikelihood =
> + prior.eval(prior.domain().clip(tTest));
> + double rCurve = config_.ctR.eval(tTest, &spanR);
> + double bCurve = config_.ctB.eval(tTest, &spanB);
> // x will be distance off the curve, y the log likelihood there
> - Pwl::Point points[MAX_NUM_DELTAS];
> - int best_point = 0;
> + Pwl::Point points[maxNumDeltas];
> + int bestPoint = 0;
> // Take some measurements transversely *off* the CT curve.
> - for (int j = 0; j < num_deltas; j++) {
> - points[j].x = -config_.transverse_neg +
> - (transverse_range * j) / (num_deltas - 1);
> - Pwl::Point rb_test = Pwl::Point(r_curve, b_curve) +
> - transverse * points[j].x;
> - double r_test = rb_test.x, b_test = rb_test.y;
> - double gain_r = 1 / r_test, gain_b = 1 / b_test;
> - double delta2_sum = computeDelta2Sum(gain_r, gain_b);
> - points[j].y = delta2_sum - prior_log_likelihood;
> + for (int j = 0; j < numDeltas; j++) {
> + points[j].x = -config_.transverseNeg +
> + (transverseRange * j) / (numDeltas - 1);
> + Pwl::Point rbTest = Pwl::Point(rCurve, bCurve) +
> + transverse * points[j].x;
> + double rTest = rbTest.x, bTest = rbTest.y;
> + double gainR = 1 / rTest, gainB = 1 / bTest;
> + double delta2Sum = computeDelta2Sum(gainR, gainB);
> + points[j].y = delta2Sum - priorLogLikelihood;
> LOG(RPiAwb, Debug)
> - << "At t " << t_test << " r " << r_test << " b "
> - << b_test << ": " << points[j].y;
> - if (points[j].y < points[best_point].y)
> - best_point = j;
> + << "At t " << tTest << " r " << rTest << " b "
> + << bTest << ": " << points[j].y;
> + if (points[j].y < points[bestPoint].y)
> + bestPoint = j;
> }
> // We have NUM_DELTAS points transversely across the CT curve,
> // now let's do a quadratic interpolation for the best result.
> - best_point = std::max(1, std::min(best_point, num_deltas - 2));
> - Pwl::Point rb_test =
> - Pwl::Point(r_curve, b_curve) +
> - transverse *
> - interpolate_quadatric(points[best_point - 1],
> - points[best_point],
> - points[best_point + 1]);
> - double r_test = rb_test.x, b_test = rb_test.y;
> - double gain_r = 1 / r_test, gain_b = 1 / b_test;
> - double delta2_sum = computeDelta2Sum(gain_r, gain_b);
> - double final_log_likelihood = delta2_sum - prior_log_likelihood;
> + bestPoint = std::max(1, std::min(bestPoint, numDeltas - 2));
> + Pwl::Point rbTest = Pwl::Point(rCurve, bCurve) +
> + transverse * interpolateQuadatric(points[bestPoint - 1],
> + points[bestPoint],
> + points[bestPoint + 1]);
> + double rTest = rbTest.x, bTest = rbTest.y;
> + double gainR = 1 / rTest, gainB = 1 / bTest;
> + double delta2Sum = computeDelta2Sum(gainR, gainB);
> + double finalLogLikelihood = delta2Sum - priorLogLikelihood;
> LOG(RPiAwb, Debug)
> << "Finally "
> - << t_test << " r " << r_test << " b " << b_test << ": "
> - << final_log_likelihood
> - << (final_log_likelihood < best_log_likelihood ? " BEST" : "");
> - if (best_t == 0 || final_log_likelihood < best_log_likelihood)
> - best_log_likelihood = final_log_likelihood,
> - best_t = t_test, best_r = r_test, best_b = b_test;
> + << tTest << " r " << rTest << " b " << bTest << ": "
> + << finalLogLikelihood
> + << (finalLogLikelihood < bestLogLikelihood ? " BEST" : "");
> + if (bestT == 0 || finalLogLikelihood < bestLogLikelihood)
> + bestLogLikelihood = finalLogLikelihood,
> + bestT = tTest, bestR = rTest, bestB = bTest;
> }
> - t = best_t, r = best_r, b = best_b;
> + t = bestT, r = bestR, b = bestB;
> LOG(RPiAwb, Debug)
> << "Fine search found t " << t << " r " << r << " b " << b;
> }
> @@ -582,12 +568,12 @@ void Awb::awbBayes()
> // valid... not entirely sure about this.
> Pwl prior = interpolatePrior();
> prior *= zones_.size() / (double)(AWB_STATS_SIZE_X * AWB_STATS_SIZE_Y);
> - prior.Map([](double x, double y) {
> + prior.map([](double x, double y) {
> LOG(RPiAwb, Debug) << "(" << x << "," << y << ")";
> });
> double t = coarseSearch(prior);
> - double r = config_.ct_r.Eval(t);
> - double b = config_.ct_b.Eval(t);
> + double r = config_.ctR.eval(t);
> + double b = config_.ctB.eval(t);
> LOG(RPiAwb, Debug)
> << "After coarse search: r " << r << " b " << b << " (gains r "
> << 1 / r << " b " << 1 / b << ")";
> @@ -604,10 +590,10 @@ void Awb::awbBayes()
> // Write results out for the main thread to pick up. Remember to adjust
> // the gains from the ones that the "canonical sensor" would require to
> // the ones needed by *this* sensor.
> - async_results_.temperature_K = t;
> - async_results_.gain_r = 1.0 / r * config_.sensitivity_r;
> - async_results_.gain_g = 1.0;
> - async_results_.gain_b = 1.0 / b * config_.sensitivity_b;
> + asyncResults_.temperatureK = t;
> + asyncResults_.gainR = 1.0 / r * config_.sensitivityR;
> + asyncResults_.gainG = 1.0;
> + asyncResults_.gainB = 1.0 / b * config_.sensitivityB;
> }
>
> void Awb::awbGrey()
> @@ -617,51 +603,51 @@ void Awb::awbGrey()
> // that we can sort them to exclude the extreme gains. We could
> // consider some variations, such as normalising all the zones first, or
> // doing an L2 average etc.
> - std::vector<RGB> &derivs_R(zones_);
> - std::vector<RGB> derivs_B(derivs_R);
> - std::sort(derivs_R.begin(), derivs_R.end(),
> + std::vector<RGB> &derivsR(zones_);
> + std::vector<RGB> derivsB(derivsR);
> + std::sort(derivsR.begin(), derivsR.end(),
> [](RGB const &a, RGB const &b) {
> return a.G * b.R < b.G * a.R;
> });
> - std::sort(derivs_B.begin(), derivs_B.end(),
> + std::sort(derivsB.begin(), derivsB.end(),
> [](RGB const &a, RGB const &b) {
> return a.G * b.B < b.G * a.B;
> });
> // Average the middle half of the values.
> - int discard = derivs_R.size() / 4;
> - RGB sum_R(0, 0, 0), sum_B(0, 0, 0);
> - for (auto ri = derivs_R.begin() + discard,
> - bi = derivs_B.begin() + discard;
> - ri != derivs_R.end() - discard; ri++, bi++)
> - sum_R += *ri, sum_B += *bi;
> - double gain_r = sum_R.G / (sum_R.R + 1),
> - gain_b = sum_B.G / (sum_B.B + 1);
> - async_results_.temperature_K = 4500; // don't know what it is
> - async_results_.gain_r = gain_r;
> - async_results_.gain_g = 1.0;
> - async_results_.gain_b = gain_b;
> + int discard = derivsR.size() / 4;
> + RGB sumR(0, 0, 0), sumB(0, 0, 0);
> + for (auto ri = derivsR.begin() + discard,
> + bi = derivsB.begin() + discard;
> + ri != derivsR.end() - discard; ri++, bi++)
> + sumR += *ri, sumB += *bi;
> + double gainR = sumR.G / (sumR.R + 1),
> + gainB = sumB.G / (sumB.B + 1);
> + asyncResults_.temperatureK = 4500; // don't know what it is
> + asyncResults_.gainR = gainR;
> + asyncResults_.gainG = 1.0;
> + asyncResults_.gainB = gainB;
> }
>
> void Awb::doAwb()
> {
> prepareStats();
> LOG(RPiAwb, Debug) << "Valid zones: " << zones_.size();
> - if (zones_.size() > config_.min_regions) {
> + if (zones_.size() > config_.minRegions) {
> if (config_.bayes)
> awbBayes();
> else
> awbGrey();
> LOG(RPiAwb, Debug)
> << "CT found is "
> - << async_results_.temperature_K
> - << " with gains r " << async_results_.gain_r
> - << " and b " << async_results_.gain_b;
> + << asyncResults_.temperatureK
> + << " with gains r " << asyncResults_.gainR
> + << " and b " << asyncResults_.gainB;
> }
> }
>
> // Register algorithm with the system.
> -static Algorithm *Create(Controller *controller)
> +static Algorithm *create(Controller *controller)
> {
> return (Algorithm *)new Awb(controller);
> }
> -static RegisterAlgorithm reg(NAME, &Create);
> +static RegisterAlgorithm reg(NAME, &create);
> diff --git a/src/ipa/raspberrypi/controller/rpi/awb.hpp b/src/ipa/raspberrypi/controller/rpi/awb.hpp
> index ac3dca6f42fc..91251d6be2da 100644
> --- a/src/ipa/raspberrypi/controller/rpi/awb.hpp
> +++ b/src/ipa/raspberrypi/controller/rpi/awb.hpp
> @@ -19,59 +19,59 @@ namespace RPiController {
> // 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
> + void read(boost::property_tree::ptree const ¶ms);
> + double ctLo; // low CT value for search
> + double ctHi; // high CT value for search
> };
>
> struct AwbPrior {
> - void Read(boost::property_tree::ptree const ¶ms);
> + 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);
> + AwbConfig() : defaultMode(nullptr) {}
> + void read(boost::property_tree::ptree const ¶ms);
> // Only repeat the AWB calculation every "this many" frames
> - uint16_t frame_period;
> + uint16_t framePeriod;
> // number of initial frames for which speed taken as 1.0 (maximum)
> - uint16_t startup_frames;
> - unsigned int convergence_frames; // approx number of frames to converge
> + uint16_t startupFrames;
> + unsigned int convergenceFrames; // approx number of frames to converge
> 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)
> + Pwl ctR; // function maps CT to r (= R/G)
> + Pwl ctB; // 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
> + AwbMode *defaultMode; // mode used if no mode selected
> // minimum proportion of pixels counted within AWB region for it to be
> // "useful"
> - double min_pixels;
> + double minPixels;
> // minimum G value of those pixels, to be regarded a "useful"
> - uint16_t min_G;
> + uint16_t minG;
> // number of AWB regions that must be "useful" in order to do the AWB
> // calculation
> - uint32_t min_regions;
> + uint32_t minRegions;
> // clamp on colour error term (so as not to penalise non-grey excessively)
> - double delta_limit;
> + double deltaLimit;
> // step size control in coarse search
> - double coarse_step;
> + double coarseStep;
> // how far to wander off CT curve towards "more purple"
> - double transverse_pos;
> + double transversePos;
> // how far to wander off CT curve towards "more green"
> - double transverse_neg;
> + double transverseNeg;
> // red sensitivity ratio (set to canonical sensor's R/G divided by this
> // sensor's R/G)
> - double sensitivity_r;
> + double sensitivityR;
> // blue sensitivity ratio (set to canonical sensor's B/G divided by this
> // sensor's B/G)
> - double sensitivity_b;
> + double sensitivityB;
> // The whitepoint (which we normally "aim" for) can be moved.
> - double whitepoint_r;
> - double whitepoint_b;
> + double whitepointR;
> + double whitepointB;
> bool bayes; // use Bayesian algorithm
> };
>
> @@ -80,22 +80,22 @@ 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;
> + char const *name() const override;
> + void initialise() override;
> + void read(boost::property_tree::ptree const ¶ms) override;
> // AWB handles "pausing" for itself.
> - bool IsPaused() const override;
> - void Pause() override;
> - void Resume() override;
> - unsigned int GetConvergenceFrames() const override;
> - void SetMode(std::string const &name) override;
> - void SetManualGains(double manual_r, double manual_b) override;
> - void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override;
> - void Prepare(Metadata *image_metadata) override;
> - void Process(StatisticsPtr &stats, Metadata *image_metadata) override;
> + bool isPaused() const override;
> + void pause() override;
> + void resume() override;
> + unsigned int getConvergenceFrames() const override;
> + void setMode(std::string const &name) override;
> + void setManualGains(double manualR, double manualB) override;
> + void switchMode(CameraMode const &cameraMode, Metadata *metadata) override;
> + void prepare(Metadata *imageMetadata) override;
> + void process(StatisticsPtr &stats, Metadata *imageMetadata) override;
> struct RGB {
> - RGB(double _R = 0, double _G = 0, double _B = 0)
> - : R(_R), G(_G), B(_B)
> + RGB(double r = 0, double g = 0, double b = 0)
> + : R(r), G(g), B(b)
> {
> }
> double R, G, B;
> @@ -110,29 +110,29 @@ private:
> bool isAutoEnabled() const;
> // configuration is read-only, and available to both threads
> AwbConfig config_;
> - std::thread async_thread_;
> + std::thread asyncThread_;
> void asyncFunc(); // asynchronous thread function
> std::mutex mutex_;
> // condvar for async thread to wait on
> - std::condition_variable async_signal_;
> + std::condition_variable asyncSignal_;
> // condvar for synchronous thread to wait on
> - std::condition_variable sync_signal_;
> + std::condition_variable syncSignal_;
> // for sync thread to check if async thread finished (requires mutex)
> - bool async_finished_;
> + bool asyncFinished_;
> // for async thread to check if it's been told to run (requires mutex)
> - bool async_start_;
> + bool asyncStart_;
> // for async thread to check if it's been told to quit (requires mutex)
> - bool async_abort_;
> + bool asyncAbort_;
>
> // 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
> - AwbStatus sync_results_;
> - AwbStatus prev_sync_results_;
> - std::string mode_name_;
> + bool asyncStarted_;
> + // counts up to framePeriod before restarting the async thread
> + int framePhase_;
> + int frameCount_; // counts up to startup_frames
> + AwbStatus syncResults_;
> + AwbStatus prevSyncResults_;
> + std::string modeName_;
> // 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, double lux);
> @@ -141,22 +141,22 @@ private:
> StatisticsPtr statistics_;
> AwbMode *mode_;
> double lux_;
> - AwbStatus async_results_;
> + AwbStatus asyncResults_;
> void doAwb();
> void awbBayes();
> void awbGrey();
> void prepareStats();
> - double computeDelta2Sum(double gain_r, double gain_b);
> + double computeDelta2Sum(double gain_r, double gainB);
> 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_;
> + double manualR_;
> // manual b setting
> - double manual_b_;
> - bool first_switch_mode_; // is this the first call to SwitchMode?
> + double manualB_;
> + bool firstSwitchMode_; // is this the first call to SwitchMode?
> };
>
> static inline Awb::RGB operator+(Awb::RGB const &a, Awb::RGB const &b)
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list