diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ipa/ipu3/algorithms/agc.cpp | 14 | ||||
-rw-r--r-- | src/ipa/ipu3/algorithms/awb.cpp | 2 | ||||
-rw-r--r-- | src/ipa/libipa/colours.cpp | 22 | ||||
-rw-r--r-- | src/ipa/libipa/colours.h | 6 | ||||
-rw-r--r-- | src/ipa/rkisp1/algorithms/awb.cpp | 47 | ||||
-rw-r--r-- | src/ipa/rpi/controller/rpi/agc_channel.cpp | 21 |
6 files changed, 55 insertions, 57 deletions
diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp index 46669203..39d0aebb 100644 --- a/src/ipa/ipu3/algorithms/agc.cpp +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -178,18 +178,16 @@ Histogram Agc::parseStatistics(const ipu3_uapi_stats_3a *stats, */ double Agc::estimateLuminance(double gain) const { - double redSum = 0, greenSum = 0, blueSum = 0; + RGB<double> sum{ 0.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); + sum.r() += std::min(std::get<0>(rgbTriples_[i]) * gain, 255.0); + sum.g() += std::min(std::get<1>(rgbTriples_[i]) * gain, 255.0); + sum.b() += std::min(std::get<2>(rgbTriples_[i]) * gain, 255.0); } - double ySum = rec601LuminanceFromRGB(redSum * rGain_, - greenSum * gGain_, - blueSum * bGain_); - + RGB<double> gains{{ rGain_, gGain_, bGain_ }}; + double ySum = rec601LuminanceFromRGB(sum * gains); return ySum / (bdsGrid_.height * bdsGrid_.width) / 255; } diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp index 7c6bff09..55de05d9 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -412,7 +412,7 @@ void Awb::awbGreyWorld() blueGain = sumBlue.g() / (sumBlue.b() + 1); /* Color temperature is not relevant in Grey world but still useful to estimate it :-) */ - asyncResults_.temperatureK = estimateCCT(sumRed.r(), sumRed.g(), sumBlue.b()); + asyncResults_.temperatureK = estimateCCT({{ sumRed.r(), sumRed.g(), sumBlue.b() }}); /* * Gain values are unsigned integer value ranging [0, 8) with 13 bit diff --git a/src/ipa/libipa/colours.cpp b/src/ipa/libipa/colours.cpp index 9fcb53b0..6c597093 100644 --- a/src/ipa/libipa/colours.cpp +++ b/src/ipa/libipa/colours.cpp @@ -21,9 +21,7 @@ namespace ipa { /** * \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 + * \param[in] rgb The RGB 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 @@ -31,21 +29,19 @@ namespace ipa { * * \return The estimated luminance value */ -double rec601LuminanceFromRGB(double r, double g, double b) +double rec601LuminanceFromRGB(const RGB<double> &rgb) { - return (r * .299) + (g * .587) + (b * .114); + return (rgb.r() * .299) + (rgb.g() * .587) + (rgb.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 + * \param[in] rgb The RGB 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. + * in a particular chromaticity space as the black body temperature changes. * * If a narrow range of color temperatures is considered (those encapsulating * daylight being the most practical case) one can approximate the Planckian @@ -56,12 +52,12 @@ double rec601LuminanceFromRGB(double r, double g, double b) * * \return The estimated color temperature */ -uint32_t estimateCCT(double red, double green, double blue) +uint32_t estimateCCT(const RGB<double> &rgb) { /* 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); + double X = (-0.14282) * rgb.r() + (1.54924) * rgb.g() + (-0.95641) * rgb.b(); + double Y = (-0.32466) * rgb.r() + (1.57837) * rgb.g() + (-0.73191) * rgb.b(); + double Z = (-0.68202) * rgb.r() + (0.77073) * rgb.g() + (0.56332) * rgb.b(); /* Calculate the normalized chromaticity values */ double x = X / (X + Y + Z); diff --git a/src/ipa/libipa/colours.h b/src/ipa/libipa/colours.h index b42ed0ac..fa6a8b57 100644 --- a/src/ipa/libipa/colours.h +++ b/src/ipa/libipa/colours.h @@ -9,12 +9,14 @@ #include <stdint.h> +#include "vector.h" + namespace libcamera { namespace ipa { -double rec601LuminanceFromRGB(double r, double g, double b); -uint32_t estimateCCT(double red, double green, double blue); +double rec601LuminanceFromRGB(const RGB<double> &rgb); +uint32_t estimateCCT(const RGB<double> &rgb); } /* namespace ipa */ diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp index 5c1d9511..dbeaf815 100644 --- a/src/ipa/rkisp1/algorithms/awb.cpp +++ b/src/ipa/rkisp1/algorithms/awb.cpp @@ -192,9 +192,7 @@ void Awb::process(IPAContext &context, const rkisp1_cif_isp_stat *params = &stats->params; const rkisp1_cif_isp_awb_stat *awb = ¶ms->awb; IPAActiveState &activeState = context.activeState; - double greenMean; - double redMean; - double blueMean; + RGB<double> rgbMeans; metadata.set(controls::AwbEnable, frameContext.awb.autoEnabled); metadata.set(controls::ColourGains, { @@ -209,9 +207,11 @@ void Awb::process(IPAContext &context, } if (rgbMode_) { - greenMean = awb->awb_mean[0].mean_y_or_g; - redMean = awb->awb_mean[0].mean_cr_or_r; - blueMean = awb->awb_mean[0].mean_cb_or_b; + rgbMeans = {{ + static_cast<double>(awb->awb_mean[0].mean_y_or_g), + static_cast<double>(awb->awb_mean[0].mean_cr_or_r), + static_cast<double>(awb->awb_mean[0].mean_cb_or_b) + }}; } else { /* Get the YCbCr mean values */ double yMean = awb->awb_mean[0].mean_y_or_g; @@ -233,9 +233,11 @@ void Awb::process(IPAContext &context, yMean -= 16; cbMean -= 128; crMean -= 128; - redMean = 1.1636 * yMean - 0.0623 * cbMean + 1.6008 * crMean; - greenMean = 1.1636 * yMean - 0.4045 * cbMean - 0.7949 * crMean; - blueMean = 1.1636 * yMean + 1.9912 * cbMean - 0.0250 * crMean; + rgbMeans = {{ + 1.1636 * yMean - 0.0623 * cbMean + 1.6008 * crMean, + 1.1636 * yMean - 0.4045 * cbMean - 0.7949 * crMean, + 1.1636 * yMean + 1.9912 * cbMean - 0.0250 * crMean + }}; /* * Due to hardware rounding errors in the YCbCr means, the @@ -243,9 +245,7 @@ void Awb::process(IPAContext &context, * negative gains, messing up calculation. Prevent this by * clamping the means to positive values. */ - redMean = std::max(redMean, 0.0); - greenMean = std::max(greenMean, 0.0); - blueMean = std::max(blueMean, 0.0); + rgbMeans = rgbMeans.max(0.0); } /* @@ -253,19 +253,22 @@ void Awb::process(IPAContext &context, * divide by the gains that were used to get the raw means from the * sensor. */ - redMean /= frameContext.awb.gains.red; - greenMean /= frameContext.awb.gains.green; - blueMean /= frameContext.awb.gains.blue; + RGB<double> gains{{ + frameContext.awb.gains.red, + frameContext.awb.gains.green, + frameContext.awb.gains.blue + }}; + rgbMeans /= gains; /* * If the means are too small we don't have enough information to * meaningfully calculate gains. Freeze the algorithm in that case. */ - if (redMean < kMeanMinThreshold && greenMean < kMeanMinThreshold && - blueMean < kMeanMinThreshold) + if (rgbMeans.r() < kMeanMinThreshold && rgbMeans.g() < kMeanMinThreshold && + rgbMeans.b() < kMeanMinThreshold) return; - activeState.awb.temperatureK = estimateCCT(redMean, greenMean, blueMean); + activeState.awb.temperatureK = estimateCCT(rgbMeans); /* Metadata shall contain the up to date measurement */ metadata.set(controls::ColourTemperature, activeState.awb.temperatureK); @@ -275,8 +278,8 @@ void Awb::process(IPAContext &context, * gain is hardcoded to 1.0. Avoid divisions by zero by clamping the * divisor to a minimum value of 1.0. */ - double redGain = greenMean / std::max(redMean, 1.0); - double blueGain = greenMean / std::max(blueMean, 1.0); + double redGain = rgbMeans.g() / std::max(rgbMeans.r(), 1.0); + double blueGain = rgbMeans.g() / std::max(rgbMeans.b(), 1.0); /* * Clamp the gain values to the hardware, which expresses gains as Q2.8 @@ -298,8 +301,8 @@ void Awb::process(IPAContext &context, LOG(RkISP1Awb, Debug) << std::showpoint - << "Means [" << redMean << ", " << greenMean << ", " << blueMean - << "], gains [" << activeState.awb.gains.automatic.red << ", " + << "Means " << rgbMeans + << ", gains [" << activeState.awb.gains.automatic.red << ", " << activeState.awb.gains.automatic.green << ", " << activeState.awb.gains.automatic.blue << "], temp " << activeState.awb.temperatureK << "K"; diff --git a/src/ipa/rpi/controller/rpi/agc_channel.cpp b/src/ipa/rpi/controller/rpi/agc_channel.cpp index 14335943..79c45973 100644 --- a/src/ipa/rpi/controller/rpi/agc_channel.cpp +++ b/src/ipa/rpi/controller/rpi/agc_channel.cpp @@ -13,6 +13,7 @@ #include <libcamera/base/log.h> #include "libipa/colours.h" +#include "libipa/vector.h" #include "../awb_status.h" #include "../device_status.h" @@ -681,12 +682,13 @@ static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb, * Note that the weights are applied by the IPA to the statistics directly, * before they are given to us here. */ - double rSum = 0, gSum = 0, bSum = 0, pixelSum = 0; + ipa::RGB<double> sum{ 0.0 }; + double pixelSum = 0; for (unsigned int i = 0; i < stats->agcRegions.numRegions(); i++) { auto ®ion = stats->agcRegions.get(i); - rSum += std::min<double>(region.val.rSum * gain, (maxVal - 1) * region.counted); - gSum += std::min<double>(region.val.gSum * gain, (maxVal - 1) * region.counted); - bSum += std::min<double>(region.val.bSum * gain, (maxVal - 1) * region.counted); + sum.r() += std::min<double>(region.val.rSum * gain, (maxVal - 1) * region.counted); + sum.g() += std::min<double>(region.val.gSum * gain, (maxVal - 1) * region.counted); + sum.b() += std::min<double>(region.val.bSum * gain, (maxVal - 1) * region.counted); pixelSum += region.counted; } if (pixelSum == 0.0) { @@ -694,14 +696,11 @@ static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb, return 0; } - double ySum; /* Factor in the AWB correction if needed. */ - if (stats->agcStatsPos == Statistics::AgcStatsPos::PreWb) { - ySum = ipa::rec601LuminanceFromRGB(rSum * awb.gainR, - gSum * awb.gainG, - bSum * awb.gainB); - } else - ySum = ipa::rec601LuminanceFromRGB(rSum, gSum, bSum); + if (stats->agcStatsPos == Statistics::AgcStatsPos::PreWb) + sum *= ipa::RGB<double>{{ awb.gainR, awb.gainR, awb.gainB }}; + + double ySum = ipa::rec601LuminanceFromRGB(sum); return ySum / pixelSum / (1 << 16); } |