libcamera/src/ipa/libipa/lux.cpp
Laurent Pinchart 3e753e2273 ipa: libipa: lux: Fix indentation
Indentation in a doxygen comment is wrong, fix it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
2025-01-24 22:07:17 +02:00

181 lines
4.4 KiB
C++

/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (C) 2019, Raspberry Pi Ltd
* Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>
*
* Helper class that implements lux estimation
*/
#include "lux.h"
#include <algorithm>
#include <chrono>
#include <libcamera/base/log.h>
#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<double>();
if (!value) {
LOG(Lux, Error) << "Missing tuning parameter: "
<< "'referenceExposureTime'";
return -EINVAL;
}
referenceExposureTime_ = *value * 1.0us;
value = tuningData["referenceAnalogueGain"].get<double>();
if (!value) {
LOG(Lux, Error) << "Missing tuning parameter: "
<< "'referenceAnalogueGain'";
return -EINVAL;
}
referenceAnalogueGain_ = *value;
value = tuningData["referenceDigitalGain"].get<double>();
if (!value) {
LOG(Lux, Error) << "Missing tuning parameter: "
<< "'referenceDigitalGain'";
return -EINVAL;
}
referenceDigitalGain_ = *value;
value = tuningData["referenceY"].get<double>();
if (!value) {
LOG(Lux, Error) << "Missing tuning parameter: "
<< "'referenceY'";
return -EINVAL;
}
referenceY_ = *value;
value = tuningData["referenceLux"].get<double>();
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 */