Skip to content

Commit 29892f1

Browse files
committed
ipa: libipa: colour: Use the RGB class to model RGB values
The rec601LuminanceFromRGB() and estimateCCT() functions take RGB triplets as three variables. Replace them with instances of the RGB class and adapt the users accordingly. Only variables passed directly to these functions are converted to RGB instances, further conversion of IPA modules to the RGB class will be performed separately. While at it, fix a typo in the documentation of the estimateCCT() function. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
1 parent cb3e309 commit 29892f1

File tree

6 files changed

+55
-57
lines changed

6 files changed

+55
-57
lines changed

src/ipa/ipu3/algorithms/agc.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -178,18 +178,16 @@ Histogram Agc::parseStatistics(const ipu3_uapi_stats_3a *stats,
178178
*/
179179
double Agc::estimateLuminance(double gain) const
180180
{
181-
double redSum = 0, greenSum = 0, blueSum = 0;
181+
RGB<double> sum{ 0.0 };
182182

183183
for (unsigned int i = 0; i < rgbTriples_.size(); i++) {
184-
redSum += std::min(std::get<0>(rgbTriples_[i]) * gain, 255.0);
185-
greenSum += std::min(std::get<1>(rgbTriples_[i]) * gain, 255.0);
186-
blueSum += std::min(std::get<2>(rgbTriples_[i]) * gain, 255.0);
184+
sum.r() += std::min(std::get<0>(rgbTriples_[i]) * gain, 255.0);
185+
sum.g() += std::min(std::get<1>(rgbTriples_[i]) * gain, 255.0);
186+
sum.b() += std::min(std::get<2>(rgbTriples_[i]) * gain, 255.0);
187187
}
188188

189-
double ySum = rec601LuminanceFromRGB(redSum * rGain_,
190-
greenSum * gGain_,
191-
blueSum * bGain_);
192-
189+
RGB<double> gains{{ rGain_, gGain_, bGain_ }};
190+
double ySum = rec601LuminanceFromRGB(sum * gains);
193191
return ySum / (bdsGrid_.height * bdsGrid_.width) / 255;
194192
}
195193

src/ipa/ipu3/algorithms/awb.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ void Awb::awbGreyWorld()
412412
blueGain = sumBlue.g() / (sumBlue.b() + 1);
413413

414414
/* Color temperature is not relevant in Grey world but still useful to estimate it :-) */
415-
asyncResults_.temperatureK = estimateCCT(sumRed.r(), sumRed.g(), sumBlue.b());
415+
asyncResults_.temperatureK = estimateCCT({{ sumRed.r(), sumRed.g(), sumBlue.b() }});
416416

417417
/*
418418
* Gain values are unsigned integer value ranging [0, 8) with 13 bit

src/ipa/libipa/colours.cpp

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,31 +21,27 @@ namespace ipa {
2121

2222
/**
2323
* \brief Estimate luminance from RGB values following ITU-R BT.601
24-
* \param[in] r The red value
25-
* \param[in] g The green value
26-
* \param[in] b The blue value
24+
* \param[in] rgb The RGB value
2725
*
2826
* This function estimates a luminance value from a triplet of Red, Green and
2927
* Blue values, following the formula defined by ITU-R Recommendation BT.601-7
3028
* which can be found at https://www.itu.int/rec/R-REC-BT.601
3129
*
3230
* \return The estimated luminance value
3331
*/
34-
double rec601LuminanceFromRGB(double r, double g, double b)
32+
double rec601LuminanceFromRGB(const RGB<double> &rgb)
3533
{
36-
return (r * .299) + (g * .587) + (b * .114);
34+
return (rgb.r() * .299) + (rgb.g() * .587) + (rgb.b() * .114);
3735
}
3836

3937
/**
4038
* \brief Estimate correlated colour temperature from RGB color space input
41-
* \param[in] red The input red value
42-
* \param[in] green The input green value
43-
* \param[in] blue The input blue value
39+
* \param[in] rgb The RGB value
4440
*
4541
* This function estimates the correlated color temperature RGB color space
4642
* input. In physics and color science, the Planckian locus or black body locus
4743
* is the path or locus that the color of an incandescent black body would take
48-
* in a particular chromaticity space as the blackbody temperature changes.
44+
* in a particular chromaticity space as the black body temperature changes.
4945
*
5046
* If a narrow range of color temperatures is considered (those encapsulating
5147
* daylight being the most practical case) one can approximate the Planckian
@@ -56,12 +52,12 @@ double rec601LuminanceFromRGB(double r, double g, double b)
5652
*
5753
* \return The estimated color temperature
5854
*/
59-
uint32_t estimateCCT(double red, double green, double blue)
55+
uint32_t estimateCCT(const RGB<double> &rgb)
6056
{
6157
/* Convert the RGB values to CIE tristimulus values (XYZ) */
62-
double X = (-0.14282) * (red) + (1.54924) * (green) + (-0.95641) * (blue);
63-
double Y = (-0.32466) * (red) + (1.57837) * (green) + (-0.73191) * (blue);
64-
double Z = (-0.68202) * (red) + (0.77073) * (green) + (0.56332) * (blue);
58+
double X = (-0.14282) * rgb.r() + (1.54924) * rgb.g() + (-0.95641) * rgb.b();
59+
double Y = (-0.32466) * rgb.r() + (1.57837) * rgb.g() + (-0.73191) * rgb.b();
60+
double Z = (-0.68202) * rgb.r() + (0.77073) * rgb.g() + (0.56332) * rgb.b();
6561

6662
/* Calculate the normalized chromaticity values */
6763
double x = X / (X + Y + Z);

src/ipa/libipa/colours.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99

1010
#include <stdint.h>
1111

12+
#include "vector.h"
13+
1214
namespace libcamera {
1315

1416
namespace ipa {
1517

16-
double rec601LuminanceFromRGB(double r, double g, double b);
17-
uint32_t estimateCCT(double red, double green, double blue);
18+
double rec601LuminanceFromRGB(const RGB<double> &rgb);
19+
uint32_t estimateCCT(const RGB<double> &rgb);
1820

1921
} /* namespace ipa */
2022

src/ipa/rkisp1/algorithms/awb.cpp

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,7 @@ void Awb::process(IPAContext &context,
192192
const rkisp1_cif_isp_stat *params = &stats->params;
193193
const rkisp1_cif_isp_awb_stat *awb = &params->awb;
194194
IPAActiveState &activeState = context.activeState;
195-
double greenMean;
196-
double redMean;
197-
double blueMean;
195+
RGB<double> rgbMeans;
198196

199197
metadata.set(controls::AwbEnable, frameContext.awb.autoEnabled);
200198
metadata.set(controls::ColourGains, {
@@ -209,9 +207,11 @@ void Awb::process(IPAContext &context,
209207
}
210208

211209
if (rgbMode_) {
212-
greenMean = awb->awb_mean[0].mean_y_or_g;
213-
redMean = awb->awb_mean[0].mean_cr_or_r;
214-
blueMean = awb->awb_mean[0].mean_cb_or_b;
210+
rgbMeans = {{
211+
static_cast<double>(awb->awb_mean[0].mean_y_or_g),
212+
static_cast<double>(awb->awb_mean[0].mean_cr_or_r),
213+
static_cast<double>(awb->awb_mean[0].mean_cb_or_b)
214+
}};
215215
} else {
216216
/* Get the YCbCr mean values */
217217
double yMean = awb->awb_mean[0].mean_y_or_g;
@@ -233,39 +233,42 @@ void Awb::process(IPAContext &context,
233233
yMean -= 16;
234234
cbMean -= 128;
235235
crMean -= 128;
236-
redMean = 1.1636 * yMean - 0.0623 * cbMean + 1.6008 * crMean;
237-
greenMean = 1.1636 * yMean - 0.4045 * cbMean - 0.7949 * crMean;
238-
blueMean = 1.1636 * yMean + 1.9912 * cbMean - 0.0250 * crMean;
236+
rgbMeans = {{
237+
1.1636 * yMean - 0.0623 * cbMean + 1.6008 * crMean,
238+
1.1636 * yMean - 0.4045 * cbMean - 0.7949 * crMean,
239+
1.1636 * yMean + 1.9912 * cbMean - 0.0250 * crMean
240+
}};
239241

240242
/*
241243
* Due to hardware rounding errors in the YCbCr means, the
242244
* calculated RGB means may be negative. This would lead to
243245
* negative gains, messing up calculation. Prevent this by
244246
* clamping the means to positive values.
245247
*/
246-
redMean = std::max(redMean, 0.0);
247-
greenMean = std::max(greenMean, 0.0);
248-
blueMean = std::max(blueMean, 0.0);
248+
rgbMeans = rgbMeans.max(0.0);
249249
}
250250

251251
/*
252252
* The ISP computes the AWB means after applying the colour gains,
253253
* divide by the gains that were used to get the raw means from the
254254
* sensor.
255255
*/
256-
redMean /= frameContext.awb.gains.red;
257-
greenMean /= frameContext.awb.gains.green;
258-
blueMean /= frameContext.awb.gains.blue;
256+
RGB<double> gains{{
257+
frameContext.awb.gains.red,
258+
frameContext.awb.gains.green,
259+
frameContext.awb.gains.blue
260+
}};
261+
rgbMeans /= gains;
259262

260263
/*
261264
* If the means are too small we don't have enough information to
262265
* meaningfully calculate gains. Freeze the algorithm in that case.
263266
*/
264-
if (redMean < kMeanMinThreshold && greenMean < kMeanMinThreshold &&
265-
blueMean < kMeanMinThreshold)
267+
if (rgbMeans.r() < kMeanMinThreshold && rgbMeans.g() < kMeanMinThreshold &&
268+
rgbMeans.b() < kMeanMinThreshold)
266269
return;
267270

268-
activeState.awb.temperatureK = estimateCCT(redMean, greenMean, blueMean);
271+
activeState.awb.temperatureK = estimateCCT(rgbMeans);
269272

270273
/* Metadata shall contain the up to date measurement */
271274
metadata.set(controls::ColourTemperature, activeState.awb.temperatureK);
@@ -275,8 +278,8 @@ void Awb::process(IPAContext &context,
275278
* gain is hardcoded to 1.0. Avoid divisions by zero by clamping the
276279
* divisor to a minimum value of 1.0.
277280
*/
278-
double redGain = greenMean / std::max(redMean, 1.0);
279-
double blueGain = greenMean / std::max(blueMean, 1.0);
281+
double redGain = rgbMeans.g() / std::max(rgbMeans.r(), 1.0);
282+
double blueGain = rgbMeans.g() / std::max(rgbMeans.b(), 1.0);
280283

281284
/*
282285
* Clamp the gain values to the hardware, which expresses gains as Q2.8
@@ -298,8 +301,8 @@ void Awb::process(IPAContext &context,
298301

299302
LOG(RkISP1Awb, Debug)
300303
<< std::showpoint
301-
<< "Means [" << redMean << ", " << greenMean << ", " << blueMean
302-
<< "], gains [" << activeState.awb.gains.automatic.red << ", "
304+
<< "Means " << rgbMeans
305+
<< ", gains [" << activeState.awb.gains.automatic.red << ", "
303306
<< activeState.awb.gains.automatic.green << ", "
304307
<< activeState.awb.gains.automatic.blue << "], temp "
305308
<< activeState.awb.temperatureK << "K";

src/ipa/rpi/controller/rpi/agc_channel.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <libcamera/base/log.h>
1414

1515
#include "libipa/colours.h"
16+
#include "libipa/vector.h"
1617

1718
#include "../awb_status.h"
1819
#include "../device_status.h"
@@ -681,27 +682,25 @@ static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb,
681682
* Note that the weights are applied by the IPA to the statistics directly,
682683
* before they are given to us here.
683684
*/
684-
double rSum = 0, gSum = 0, bSum = 0, pixelSum = 0;
685+
ipa::RGB<double> sum{ 0.0 };
686+
double pixelSum = 0;
685687
for (unsigned int i = 0; i < stats->agcRegions.numRegions(); i++) {
686688
auto &region = stats->agcRegions.get(i);
687-
rSum += std::min<double>(region.val.rSum * gain, (maxVal - 1) * region.counted);
688-
gSum += std::min<double>(region.val.gSum * gain, (maxVal - 1) * region.counted);
689-
bSum += std::min<double>(region.val.bSum * gain, (maxVal - 1) * region.counted);
689+
sum.r() += std::min<double>(region.val.rSum * gain, (maxVal - 1) * region.counted);
690+
sum.g() += std::min<double>(region.val.gSum * gain, (maxVal - 1) * region.counted);
691+
sum.b() += std::min<double>(region.val.bSum * gain, (maxVal - 1) * region.counted);
690692
pixelSum += region.counted;
691693
}
692694
if (pixelSum == 0.0) {
693695
LOG(RPiAgc, Warning) << "computeInitialY: pixelSum is zero";
694696
return 0;
695697
}
696698

697-
double ySum;
698699
/* Factor in the AWB correction if needed. */
699-
if (stats->agcStatsPos == Statistics::AgcStatsPos::PreWb) {
700-
ySum = ipa::rec601LuminanceFromRGB(rSum * awb.gainR,
701-
gSum * awb.gainG,
702-
bSum * awb.gainB);
703-
} else
704-
ySum = ipa::rec601LuminanceFromRGB(rSum, gSum, bSum);
700+
if (stats->agcStatsPos == Statistics::AgcStatsPos::PreWb)
701+
sum *= ipa::RGB<double>{{ awb.gainR, awb.gainR, awb.gainB }};
702+
703+
double ySum = ipa::rec601LuminanceFromRGB(sum);
705704

706705
return ySum / pixelSum / (1 << 16);
707706
}

0 commit comments

Comments
 (0)