Message ID | 20250109115412.356768-6-stefan.klug@ideasonboard.com |
---|---|
State | New |
Headers | show |
Series |
|
Related | show |
On Thu, Jan 09, 2025 at 12:53:56PM +0100, Stefan Klug wrote: > Add the grey world algorithm that is currently used in rkisp1 to libipa. > No changes in functionality were made. > > Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com> > --- > src/ipa/libipa/awb_grey.cpp | 114 ++++++++++++++++++++++++++++++++++++ > src/ipa/libipa/awb_grey.h | 35 +++++++++++ > src/ipa/libipa/meson.build | 2 + > 3 files changed, 151 insertions(+) > create mode 100644 src/ipa/libipa/awb_grey.cpp > create mode 100644 src/ipa/libipa/awb_grey.h > > diff --git a/src/ipa/libipa/awb_grey.cpp b/src/ipa/libipa/awb_grey.cpp > new file mode 100644 > index 000000000000..192a7cf3834a > --- /dev/null > +++ b/src/ipa/libipa/awb_grey.cpp > @@ -0,0 +1,114 @@ > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > +/* > + * Copyright (C) 2024 Ideas on Board Oy > + * > + * Base class for bayesian AWB algorithm > + */ > + > +#include "awb_grey.h" > + > +#include <cmath> > + > +#include <libcamera/base/log.h> > +#include <libcamera/control_ids.h> > + > +#include "colours.h" > + > +using namespace libcamera::controls; > + > +/** > + * \file awb_grey.h > + * \brief Implementation of a grey world AWB algorithm > + */ > + > +namespace libcamera { > + > +LOG_DECLARE_CATEGORY(Awb) > +namespace ipa { > + > +/** > + * \class AwbGrey > + * \brief A Grey world auto white balance algorithm > + */ > + > +/** > + * \brief Initialize the algorithm with the given tuning data > + * \param[in] tuningData The tuning data for the algorithm > + * > + * Load the colour temperature curve from the tuning data. If there is no tuning > + * data available, continue with a warning. Manual colour temperature will not > + * work in that case. > + * > + * \return 0 on success, a negative error code otherwise > + */ > +int AwbGrey::init(const YamlObject &tuningData) > +{ > + Interpolator<Vector<double, 2>> gains; > + int ret = gains.readYaml(tuningData["colourGains"], "ct", "gains"); > + if (ret < 0) > + LOG(Awb, Warning) > + << "Failed to parse 'colourGains' " > + << "parameter from tuning file; " > + << "manual colour temperature will not work properly"; > + else > + colourGainCurve_ = gains; > + > + return 0; > +} > + > +/** > + * \brief Calculate awb data from the given statistics > + * \param[in] stats The statistics to use for the calculation > + * \param[in] lux The lux value of the scene > + * > + * Estimates the colour temperature based on the coulours::estimateCCT function. s/coulours/colors/ -- wait no -- s/coulours/colours/ > + * The gains are calculated purely based on the RGB means provided by the \a > + * stats. The colour temperature is not taken into account when calculating the > + * gains. > + * > + * The \a lux parameter is not used in this algorithm. > + * > + * \return The awb result > + */ > +AwbResult AwbGrey::calculateAwb(const AwbStats &stats, [[maybe_unused]] int lux) > +{ > + AwbResult result; > + auto means = stats.getRGBMeans(); > + result.colourTemperature = estimateCCT(means); > + > + /* > + * Estimate the red and blue gains to apply in a grey world. The green > + * gain is hardcoded to 1.0. Avoid divisions by zero by clamping the > + * divisor to a minimum value of 1.0. > + */ > + result.gains.r() = means.g() / std::max(means.r(), 1.0); > + result.gains.g() = 1.0; > + result.gains.b() = means.g() / std::max(means.b(), 1.0); > + return result; > +} > + > +/** > + * \brief Compute white balance gains from a colour temperature > + * \param[in] colourTemperature The colour temperature in Kelvin > + * > + * Compute the white balance gains from a \a colourTemperature. This function > + * does not take any statistics into account. It simply interpolates the colour > + * gains configured in the colour temperature curve. > + * > + * \return The colour gains if a colour temperature curve is available, > + * [1, 1, 1] otherwise. > + */ > +RGB<double> AwbGrey::gainsFromColourTemperature(double colourTemperature) > +{ > + if (!colourGainCurve_) { > + LOG(Awb, Error) << "No gains defined"; > + return RGB<double>({ 1.0, 1.0, 1.0 }); > + } > + > + auto gains = colourGainCurve_->getInterpolated(colourTemperature); > + return { { gains[0], 1.0, gains[0] } }; Should the second gains[0] be gains[1]...? Otherwise looks good to me. Paul > +} > + > +} /* namespace ipa */ > + > +} /* namespace libcamera */ > diff --git a/src/ipa/libipa/awb_grey.h b/src/ipa/libipa/awb_grey.h > new file mode 100644 > index 000000000000..6eda8e5498fb > --- /dev/null > +++ b/src/ipa/libipa/awb_grey.h > @@ -0,0 +1,35 @@ > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > +/* > + * Copyright (C) 2024 Ideas on Board Oy > + * > + * AWB grey world algorithm > + */ > + > +#pragma once > + > +#include "libcamera/internal/yaml_parser.h" > + > +#include "awb.h" > +#include "interpolator.h" > +#include "vector.h" > + > +namespace libcamera { > + > +namespace ipa { > + > +class AwbGrey : public AwbAlgorithm > +{ > +public: > + AwbGrey() = default; > + > + int init(const YamlObject &tuningData) override; > + AwbResult calculateAwb(const AwbStats &stats, int lux) override; > + RGB<double> gainsFromColourTemperature(double coulourTemperature) override; > + > +private: > + std::optional<Interpolator<Vector<double, 2>>> colourGainCurve_; > +}; > + > +} /* namespace ipa */ > + > +} /* namespace libcamera */ > diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build > index 03e879c5834f..c550a6eb45b6 100644 > --- a/src/ipa/libipa/meson.build > +++ b/src/ipa/libipa/meson.build > @@ -3,6 +3,7 @@ > libipa_headers = files([ > 'agc_mean_luminance.h', > 'algorithm.h', > + 'awb_grey.h', > 'awb.h', > 'camera_sensor_helper.h', > 'colours.h', > @@ -21,6 +22,7 @@ libipa_headers = files([ > libipa_sources = files([ > 'agc_mean_luminance.cpp', > 'algorithm.cpp', > + 'awb_grey.cpp', > 'awb.cpp', > 'camera_sensor_helper.cpp', > 'colours.cpp', > -- > 2.43.0 >
diff --git a/src/ipa/libipa/awb_grey.cpp b/src/ipa/libipa/awb_grey.cpp new file mode 100644 index 000000000000..192a7cf3834a --- /dev/null +++ b/src/ipa/libipa/awb_grey.cpp @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024 Ideas on Board Oy + * + * Base class for bayesian AWB algorithm + */ + +#include "awb_grey.h" + +#include <cmath> + +#include <libcamera/base/log.h> +#include <libcamera/control_ids.h> + +#include "colours.h" + +using namespace libcamera::controls; + +/** + * \file awb_grey.h + * \brief Implementation of a grey world AWB algorithm + */ + +namespace libcamera { + +LOG_DECLARE_CATEGORY(Awb) +namespace ipa { + +/** + * \class AwbGrey + * \brief A Grey world auto white balance algorithm + */ + +/** + * \brief Initialize the algorithm with the given tuning data + * \param[in] tuningData The tuning data for the algorithm + * + * Load the colour temperature curve from the tuning data. If there is no tuning + * data available, continue with a warning. Manual colour temperature will not + * work in that case. + * + * \return 0 on success, a negative error code otherwise + */ +int AwbGrey::init(const YamlObject &tuningData) +{ + Interpolator<Vector<double, 2>> gains; + int ret = gains.readYaml(tuningData["colourGains"], "ct", "gains"); + if (ret < 0) + LOG(Awb, Warning) + << "Failed to parse 'colourGains' " + << "parameter from tuning file; " + << "manual colour temperature will not work properly"; + else + colourGainCurve_ = gains; + + return 0; +} + +/** + * \brief Calculate awb data from the given statistics + * \param[in] stats The statistics to use for the calculation + * \param[in] lux The lux value of the scene + * + * Estimates the colour temperature based on the coulours::estimateCCT function. + * The gains are calculated purely based on the RGB means provided by the \a + * stats. The colour temperature is not taken into account when calculating the + * gains. + * + * The \a lux parameter is not used in this algorithm. + * + * \return The awb result + */ +AwbResult AwbGrey::calculateAwb(const AwbStats &stats, [[maybe_unused]] int lux) +{ + AwbResult result; + auto means = stats.getRGBMeans(); + result.colourTemperature = estimateCCT(means); + + /* + * Estimate the red and blue gains to apply in a grey world. The green + * gain is hardcoded to 1.0. Avoid divisions by zero by clamping the + * divisor to a minimum value of 1.0. + */ + result.gains.r() = means.g() / std::max(means.r(), 1.0); + result.gains.g() = 1.0; + result.gains.b() = means.g() / std::max(means.b(), 1.0); + return result; +} + +/** + * \brief Compute white balance gains from a colour temperature + * \param[in] colourTemperature The colour temperature in Kelvin + * + * Compute the white balance gains from a \a colourTemperature. This function + * does not take any statistics into account. It simply interpolates the colour + * gains configured in the colour temperature curve. + * + * \return The colour gains if a colour temperature curve is available, + * [1, 1, 1] otherwise. + */ +RGB<double> AwbGrey::gainsFromColourTemperature(double colourTemperature) +{ + if (!colourGainCurve_) { + LOG(Awb, Error) << "No gains defined"; + return RGB<double>({ 1.0, 1.0, 1.0 }); + } + + auto gains = colourGainCurve_->getInterpolated(colourTemperature); + return { { gains[0], 1.0, gains[0] } }; +} + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/src/ipa/libipa/awb_grey.h b/src/ipa/libipa/awb_grey.h new file mode 100644 index 000000000000..6eda8e5498fb --- /dev/null +++ b/src/ipa/libipa/awb_grey.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024 Ideas on Board Oy + * + * AWB grey world algorithm + */ + +#pragma once + +#include "libcamera/internal/yaml_parser.h" + +#include "awb.h" +#include "interpolator.h" +#include "vector.h" + +namespace libcamera { + +namespace ipa { + +class AwbGrey : public AwbAlgorithm +{ +public: + AwbGrey() = default; + + int init(const YamlObject &tuningData) override; + AwbResult calculateAwb(const AwbStats &stats, int lux) override; + RGB<double> gainsFromColourTemperature(double coulourTemperature) override; + +private: + std::optional<Interpolator<Vector<double, 2>>> colourGainCurve_; +}; + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build index 03e879c5834f..c550a6eb45b6 100644 --- a/src/ipa/libipa/meson.build +++ b/src/ipa/libipa/meson.build @@ -3,6 +3,7 @@ libipa_headers = files([ 'agc_mean_luminance.h', 'algorithm.h', + 'awb_grey.h', 'awb.h', 'camera_sensor_helper.h', 'colours.h', @@ -21,6 +22,7 @@ libipa_headers = files([ libipa_sources = files([ 'agc_mean_luminance.cpp', 'algorithm.cpp', + 'awb_grey.cpp', 'awb.cpp', 'camera_sensor_helper.cpp', 'colours.cpp',
Add the grey world algorithm that is currently used in rkisp1 to libipa. No changes in functionality were made. Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com> --- src/ipa/libipa/awb_grey.cpp | 114 ++++++++++++++++++++++++++++++++++++ src/ipa/libipa/awb_grey.h | 35 +++++++++++ src/ipa/libipa/meson.build | 2 + 3 files changed, 151 insertions(+) create mode 100644 src/ipa/libipa/awb_grey.cpp create mode 100644 src/ipa/libipa/awb_grey.h