mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-13 07:19:45 +03:00
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>
181 lines
4.4 KiB
C++
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 */
|