libipa: Add grey world AWB algorithm

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>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
This commit is contained in:
Stefan Klug 2025-01-23 12:40:55 +01:00
parent d19ae2a228
commit 7ea83d5f7b
3 changed files with 151 additions and 0 deletions

114
src/ipa/libipa/awb_grey.cpp Normal file
View file

@ -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 */

35
src/ipa/libipa/awb_grey.h Normal file
View file

@ -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/vector.h"
#include "libcamera/internal/yaml_parser.h"
#include "awb.h"
#include "interpolator.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 colourTemperature) override;
private:
std::optional<Interpolator<Vector<double, 2>>> colourGainCurve_;
};
} /* namespace ipa */
} /* namespace libcamera */

View file

@ -3,6 +3,7 @@
libipa_headers = files([
'agc_mean_luminance.h',
'algorithm.h',
'awb_grey.h',
'awb.h',
'camera_sensor_helper.h',
'colours.h',
@ -20,6 +21,7 @@ libipa_headers = files([
libipa_sources = files([
'agc_mean_luminance.cpp',
'algorithm.cpp',
'awb_grey.cpp',
'awb.cpp',
'camera_sensor_helper.cpp',
'colours.cpp',