/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2019, Raspberry Pi Ltd * Copyright (C) 2024, Paul Elder * * Helper class that implements lux estimation */ #include "lux.h" #include #include #include #include "libcamera/internal/yaml_parser.h" #include "histogram.h" /** * \file lux.h * \brief Helper class that implements lux estimation * * Estimating the lux level of an image is a common operation that can for * instance be used to adjust the target Y value in AGC or for Bayesian AWB * estimation. */ namespace libcamera { using namespace std::literals::chrono_literals; LOG_DEFINE_CATEGORY(Lux) namespace ipa { /** * \class Lux * \brief Class that implements lux estimation * * IPAs that wish to use lux estimation should create a Lux algorithm module * that lightly wraps this module by providing the platform-specific luminance * histogram. The Lux entry in the tuning file must then precede the algorithms * that depend on the estimated lux value. */ /** * \var Lux::binSize_ * \brief The maximum count of each bin */ /** * \var Lux::referenceExposureTime_ * \brief The exposure time of the reference image, in microseconds */ /** * \var Lux::referenceAnalogueGain_ * \brief The analogue gain of the reference image */ /** * \var Lux::referenceDigitalGain_ * \brief The analogue gain of the reference image */ /** * \var Lux::referenceY_ * \brief The measured luminance of the reference image, out of the bin size * * \sa binSize_ */ /** * \var Lux::referenceLux_ * \brief The estimated lux level of the reference image */ /** * \brief Construct the Lux helper module * \param[in] binSize The maximum count of each bin */ Lux::Lux(unsigned int binSize) : binSize_(binSize) { } /** * \brief Parse tuning data * \param[in] tuningData The YamlObject representing the tuning data * * This function parses yaml tuning data for the common Lux module. It requires * reference exposure time, analogue gain, digital gain, and lux values. * * \code{.unparsed} * algorithms: * - Lux: * referenceExposureTime: 10000 * referenceAnalogueGain: 4.0 * referenceDigitalGain: 1.0 * referenceY: 12000 * referenceLux: 1000 * \endcode * * \return 0 on success or a negative error code */ int Lux::parseTuningData(const YamlObject &tuningData) { auto value = tuningData["referenceExposureTime"].get(); if (!value) { LOG(Lux, Error) << "Missing tuning parameter: " << "'referenceExposureTime'"; return -EINVAL; } referenceExposureTime_ = *value * 1.0us; value = tuningData["referenceAnalogueGain"].get(); if (!value) { LOG(Lux, Error) << "Missing tuning parameter: " << "'referenceAnalogueGain'"; return -EINVAL; } referenceAnalogueGain_ = *value; value = tuningData["referenceDigitalGain"].get(); if (!value) { LOG(Lux, Error) << "Missing tuning parameter: " << "'referenceDigitalGain'"; return -EINVAL; } referenceDigitalGain_ = *value; value = tuningData["referenceY"].get(); if (!value) { LOG(Lux, Error) << "Missing tuning parameter: " << "'referenceY'"; return -EINVAL; } referenceY_ = *value; value = tuningData["referenceLux"].get(); if (!value) { LOG(Lux, Error) << "Missing tuning parameter: " << "'referenceLux'"; return -EINVAL; } referenceLux_ = *value; return 0; } /** * \brief Estimate lux given runtime values * \param[in] exposureTime Exposure time applied to the frame * \param[in] aGain Analogue gain applied to the frame * \param[in] dGain Digital gain applied to the frame * \param[in] yHist Histogram from the ISP statistics * * Estimate the lux given the exposure time, gain, and histogram. * * \return Estimated lux value */ double Lux::estimateLux(utils::Duration exposureTime, double aGain, double dGain, const Histogram &yHist) const { double currentY = yHist.interQuantileMean(0, 1); double exposureTimeRatio = referenceExposureTime_ / exposureTime; double aGainRatio = referenceAnalogueGain_ / aGain; double dGainRatio = referenceDigitalGain_ / dGain; double yRatio = currentY * (binSize_ / yHist.bins()) / referenceY_; double estimatedLux = exposureTimeRatio * aGainRatio * dGainRatio * yRatio * referenceLux_; LOG(Lux, Debug) << "Estimated lux " << estimatedLux; return estimatedLux; } } /* namespace ipa */ } /* namespace libcamera */