Message ID | 20241107102508.48322-2-dan.scally@ideasonboard.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
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@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 >
Hi Dan, Thank you for the patch. 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@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 +++++++++++ Could we call this colours.{cpp,h} ? I'd like to keep libipa organized, and add a generic "helpers" file only if we really can classify the helpers in any meaningful way. I expect we'll get more colour-related helpers in the future. > 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) > +{ > + 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',
Hello Laurent On 12/11/2024 08:07, Laurent Pinchart wrote: > Hi Dan, > > Thank you for the patch. > > 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@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 +++++++++++ > Could we call this colours.{cpp,h} ? I'd like to keep libipa organized, > and add a generic "helpers" file only if we really can classify the > helpers in any meaningful way. I expect we'll get more colour-related > helpers in the future. Okedokey - will do. > >> 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) >> +{ >> + 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',
Hi Jacopo On 08/11/2024 15:18, Jacopo Mondi wrote: > 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@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 ? You are right of course - I hadn't checked in the IPU3 one carefully enough, for some reason I thought they were all the same. I'll use doubles across the board so there's no rounding. >> +{ >> + 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 >>
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) +{ + 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',
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@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