summaryrefslogtreecommitdiff
path: root/src/ipa/libipa/awb_grey.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipa/libipa/awb_grey.cpp')
-rw-r--r--src/ipa/libipa/awb_grey.cpp114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/ipa/libipa/awb_grey.cpp b/src/ipa/libipa/awb_grey.cpp
new file mode 100644
index 00000000..49448976
--- /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 grey world 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 colours::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[1] } };
+}
+
+} /* namespace ipa */
+
+} /* namespace libcamera */