[PATCH 4/5] libipa: histogram: Fix interQuantileMean() for small ranges

Stefan Klug stefan.klug at ideasonboard.com
Mon Mar 24 18:07:39 CET 2025


The interQuantileMean() is supposed to return a weighted mean value
between two quantiles. This works for reasonably fine histograms, but
fails for coarse histograms and small quantile ranges because the weight
is always taken from the lower border of the bin.

Fix that by rewriting the algorithm to calculate a lower and upper bound
for every (partial) bin that goes into the mean calculation and weight
the bins by the middle of these bounds.

Signed-off-by: Stefan Klug <stefan.klug at ideasonboard.com>
---
 src/ipa/libipa/histogram.cpp | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/src/ipa/libipa/histogram.cpp b/src/ipa/libipa/histogram.cpp
index c19a4cbbf3cd..31f017af3458 100644
--- a/src/ipa/libipa/histogram.cpp
+++ b/src/ipa/libipa/histogram.cpp
@@ -153,22 +153,24 @@ double Histogram::interQuantileMean(double lowQuantile, double highQuantile) con
 	double lowPoint = quantile(lowQuantile);
 	/* Proportion of pixels which lies below highQuantile */
 	double highPoint = quantile(highQuantile, static_cast<uint32_t>(lowPoint));
-	double sumBinFreq = 0, cumulFreq = 0;
+	double sumBinFreq = 0;
+	double cumulFreq = 0;
+
+	for (int bin = std::floor(lowPoint); bin < std::ceil(highPoint); bin++) {
+		double lowBound = std::max(static_cast<double>(bin), lowPoint);
+		double highBound = std::min(static_cast<double>(bin + 1), highPoint);
 
-	for (double p_next = floor(lowPoint) + 1.0;
-	     p_next <= ceil(highPoint);
-	     lowPoint = p_next, p_next += 1.0) {
-		int bin = floor(lowPoint);
 		double freq = (cumulative_[bin + 1] - cumulative_[bin])
-			* (std::min(p_next, highPoint) - lowPoint);
+			* (highBound - lowBound);
 
 		/* Accumulate weighted bin */
-		sumBinFreq += bin * freq;
+		sumBinFreq += 0.5 * (highBound + lowBound) * freq;
+
 		/* Accumulate weights */
 		cumulFreq += freq;
 	}
-	/* add 0.5 to give an average for bin mid-points */
-	return sumBinFreq / cumulFreq + 0.5;
+
+	return sumBinFreq / cumulFreq;
 }
 
 } /* namespace ipa */
-- 
2.43.0



More information about the libcamera-devel mailing list