[PATCH v2 1/6] ipa: libipa: Add miscellaneous helpers
Jacopo Mondi
jacopo.mondi at ideasonboard.com
Fri Nov 8 16:18:07 CET 2024
Hi Dan
On Thu, Nov 07, 2024 at 10:25:03AM +0000, Daniel Scally wrote:
> We start to have functions that are effectively identical crop up
> across the IPA modules. Add a file allowing those to be centralised
> within libipa so that a single implementation can be used in all of
> the IPAs.
>
> Signed-off-by: Daniel Scally <dan.scally at ideasonboard.com>
> ---
> Changes in v2:
>
> - Dropped the Q(m, n) format helpers until they're needed.
> - \return statements after long description
> - Switched rec601LuminanceFromRGB() to return a double
>
> src/ipa/libipa/helpers.cpp | 77 ++++++++++++++++++++++++++++++++++++++
> src/ipa/libipa/helpers.h | 21 +++++++++++
> src/ipa/libipa/meson.build | 2 +
> 3 files changed, 100 insertions(+)
> create mode 100644 src/ipa/libipa/helpers.cpp
> create mode 100644 src/ipa/libipa/helpers.h
>
> diff --git a/src/ipa/libipa/helpers.cpp b/src/ipa/libipa/helpers.cpp
> new file mode 100644
> index 00000000..6c038895
> --- /dev/null
> +++ b/src/ipa/libipa/helpers.cpp
> @@ -0,0 +1,77 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +/*
> + * Copyright (C) 2024, Ideas on Board Oy
> + *
> + * libipa miscellaneous helpers
> + */
> +
> +#include "helpers.h"
> +
> +#include <algorithm>
> +#include <cmath>
> +
> +namespace libcamera {
> +
> +namespace ipa {
> +
> +/**
> + * \file helpers.h
> + * \brief Functions to reduce code duplication between IPA modules
> + */
> +
> +/**
> + * \brief Estimate luminance from RGB values following ITU-R BT.601
> + * \param[in] r The red value
> + * \param[in] g The green value
> + * \param[in] b The blue value
> + *
> + * This function estimates a luminance value from a triplet of Red, Green and
> + * Blue values, following the formula defined by ITU-R Recommendation BT.601-7
> + * which can be found at https://www.itu.int/rec/R-REC-BT.601
> + *
> + * \return The estimated luminance value
> + */
> +double rec601LuminanceFromRGB(unsigned int r, unsigned int g, unsigned int b)
Is passing arguments in as integers correct or will result in a lost
of precision ?
I see in the next patch the IPU3 IPA is converted to use this helper
double Agc::estimateLuminance(double gain) const
{
double redSum = 0, greenSum = 0, blueSum = 0;
for (unsigned int i = 0; i < rgbTriples_.size(); i++) {
redSum += std::min(std::get<0>(rgbTriples_[i]) * gain, 255.0);
greenSum += std::min(std::get<1>(rgbTriples_[i]) * gain, 255.0);
blueSum += std::min(std::get<2>(rgbTriples_[i]) * gain, 255.0);
}
- double ySum = redSum * rGain_ * 0.299
- + greenSum * gGain_ * 0.587
- + blueSum * bGain_ * 0.114;
+ double ySum = rec601LuminanceFromRGB(redSum * rGain_,
+ greenSum * gGain_,
+ blueSum * bGain_);
return ySum / (bdsGrid_.height * bdsGrid_.width) / 255;
}
Now redSum * rGain_ (and greenSum * gGain_ and blueSum * bGain_)
are indeed doubles. If you pass them in as integers I'm afraid you're
implicitly converting and rounding them. I made a little test program
double rec601LuminanceFromRGB(unsigned int r, unsigned int g, unsigned int b)
{
return (r * .299) + (g * .587) + (b * .114);
}
double rec601LuminanceFromRGBDouble(double r, double g, double b)
{
return (r * .299) + (g * .587) + (b * .114);
}
int main()
{
double r = 1.234;
double g = 2.345;
double b = 3.456;
std::cout << rec601LuminanceFromRGB(r, g, b) << std::endl;
std::cout << rec601LuminanceFromRGBDouble(r, g, b) << std::endl;
return 0;
}
And indeed it prints different results
$ ./a.out
1.815
2.13946
Have you checked in the IPU3 IPA if the results of the computation
are the same ?
> +{
> + return (r * .299) + (g * .587) + (b * .114);
> +}
> +
> +/**
> + * \brief Estimate correlated colour temperature from RGB color space input
> + * \param[in] red The input red value
> + * \param[in] green The input green value
> + * \param[in] blue The input blue value
> + *
> + * This function estimates the correlated color temperature RGB color space
> + * input. In physics and color science, the Planckian locus or black body locus
> + * is the path or locus that the color of an incandescent black body would take
> + * in a particular chromaticity space as the blackbody temperature changes.
> + *
> + * If a narrow range of color temperatures is considered (those encapsulating
> + * daylight being the most practical case) one can approximate the Planckian
> + * locus in order to calculate the CCT in terms of chromaticity coordinates.
> + *
> + * More detailed information can be found in:
> + * https://en.wikipedia.org/wiki/Color_temperature#Approximation
> + *
> + * \return The estimated color temperature
> + */
> +uint32_t estimateCCT(double red, double green, double blue)
> +{
> + /* Convert the RGB values to CIE tristimulus values (XYZ) */
> + double X = (-0.14282) * (red) + (1.54924) * (green) + (-0.95641) * (blue);
> + double Y = (-0.32466) * (red) + (1.57837) * (green) + (-0.73191) * (blue);
> + double Z = (-0.68202) * (red) + (0.77073) * (green) + (0.56332) * (blue);
> +
> + /* Calculate the normalized chromaticity values */
> + double x = X / (X + Y + Z);
> + double y = Y / (X + Y + Z);
> +
> + /* Calculate CCT */
> + double n = (x - 0.3320) / (0.1858 - y);
> + return 449 * n * n * n + 3525 * n * n + 6823.3 * n + 5520.33;
> +}
> +
> +} /* namespace ipa */
> +
> +} /* namespace libcamera */
> diff --git a/src/ipa/libipa/helpers.h b/src/ipa/libipa/helpers.h
> new file mode 100644
> index 00000000..51c74a36
> --- /dev/null
> +++ b/src/ipa/libipa/helpers.h
> @@ -0,0 +1,21 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +/*
> + * Copyright (C) 2024, Ideas on Board Oy
> + *
> + * libipa miscellaneous helpers
> + */
> +
> +#pragma once
> +
> +#include <stdint.h>
> +
> +namespace libcamera {
> +
> +namespace ipa {
> +
> +double rec601LuminanceFromRGB(unsigned int r, unsigned int g, unsigned int b);
> +uint32_t estimateCCT(double red, double green, double blue);
> +
> +} /* namespace ipa */
> +
> +} /* namespace libcamera */
> diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build
> index e78cbcd6..ca4f3e28 100644
> --- a/src/ipa/libipa/meson.build
> +++ b/src/ipa/libipa/meson.build
> @@ -6,6 +6,7 @@ libipa_headers = files([
> 'camera_sensor_helper.h',
> 'exposure_mode_helper.h',
> 'fc_queue.h',
> + 'helpers.h',
> 'histogram.h',
> 'interpolator.h',
> 'lsc_polynomial.h',
> @@ -21,6 +22,7 @@ libipa_sources = files([
> 'camera_sensor_helper.cpp',
> 'exposure_mode_helper.cpp',
> 'fc_queue.cpp',
> + 'helpers.cpp',
> 'histogram.cpp',
> 'interpolator.cpp',
> 'lsc_polynomial.cpp',
> --
> 2.30.2
>
More information about the libcamera-devel
mailing list