| Message ID | 20260720-libipa-algorithms-v6-27-ececb73f97cb@ideasonboard.com |
|---|---|
| State | Superseded |
| Headers | show |
| Series |
|
| Related | show |
2026. 07. 20. 16:59 keltezéssel, Jacopo Mondi írta: > The libIPA Lsc algorithm currently assumes the register format of > the RkISP1 platform (16 bits Q2.10 format), as that's where the > implementation has been derived from. > > Move the register quantization to the plaltform IPA and use 'floats' > as the exchange format for the table-based and polynomial-based > LSC implementations. > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> > --- > src/ipa/libipa/lsc_base.h | 2 +- > src/ipa/libipa/lsc_polynomial.cpp | 17 +++++------------ > src/ipa/libipa/lsc_polynomial.h | 8 ++++---- > src/ipa/libipa/lsc_table.cpp | 6 +++--- > src/ipa/libipa/lsc_table.h | 2 +- > src/ipa/rkisp1/algorithms/lsc.cpp | 34 ++++++++++++++++++++++++++-------- > 6 files changed, 40 insertions(+), 29 deletions(-) > > diff --git a/src/ipa/libipa/lsc_base.h b/src/ipa/libipa/lsc_base.h > index b0b9b3b0712d..386cac55be34 100644 > --- a/src/ipa/libipa/lsc_base.h > +++ b/src/ipa/libipa/lsc_base.h > @@ -26,7 +26,7 @@ namespace ipa { > > namespace lsc { > > -using Components = std::map<std::string, std::vector<uint16_t>>; > +using Components = std::map<std::string, std::vector<float>>; > using ComponentsMap = std::map<unsigned int, Components>; > > } /* namespace lsc */ > diff --git a/src/ipa/libipa/lsc_polynomial.cpp b/src/ipa/libipa/lsc_polynomial.cpp > index c61c85fbf2b2..e31a63e06cc8 100644 > --- a/src/ipa/libipa/lsc_polynomial.cpp > +++ b/src/ipa/libipa/lsc_polynomial.cpp > @@ -218,7 +218,7 @@ LscPolynomial::sampleForCrop(const Rectangle &cropRectangle, > return components; > } > > -std::vector<uint16_t> > +std::vector<float> > LscPolynomial::samplePolynomial(const lsc::Polynomial &poly, > Span<const double> xPositions, > Span<const double> yPositions, > @@ -229,7 +229,7 @@ LscPolynomial::samplePolynomial(const lsc::Polynomial &poly, > double y0 = cropRectangle.y / m; > double w = cropRectangle.width / m; > double h = cropRectangle.height / m; > - std::vector<uint16_t> samples; > + std::vector<float> samples; > > samples.reserve(xPositions.size() * yPositions.size()); > > @@ -237,16 +237,9 @@ LscPolynomial::samplePolynomial(const lsc::Polynomial &poly, > for (double x : xPositions) { > double xp = x0 + x * w; > double yp = y0 + y * h; > - /* > - * The hardware uses 2.10 fixed point format and limits > - * the legal values to [1..3.999]. Scale and clamp the > - * sampled value accordingly. > - */ > - int v = static_cast<int>( > - poly.sampleAtNormalizedPixelPos(xp, yp) * > - 1024); > - v = std::clamp(v, 1024, 4095); > - samples.push_back(v); > + > + samples.push_back(static_cast<float> > + (poly.sampleAtNormalizedPixelPos(xp, yp))); > } > } > return samples; > diff --git a/src/ipa/libipa/lsc_polynomial.h b/src/ipa/libipa/lsc_polynomial.h > index 6d19e46a50b7..8d526531075b 100644 > --- a/src/ipa/libipa/lsc_polynomial.h > +++ b/src/ipa/libipa/lsc_polynomial.h > @@ -65,10 +65,10 @@ public: > std::vector<double> xPos, std::vector<double> yPos) override; > > private: > - std::vector<uint16_t> samplePolynomial(const lsc::Polynomial &poly, > - Span<const double> xPositions, > - Span<const double> yPositions, > - const Rectangle &cropRectangle); > + std::vector<float> samplePolynomial(const lsc::Polynomial &poly, > + Span<const double> xPositions, > + Span<const double> yPositions, > + const Rectangle &cropRectangle); > PolynomialComponentsMap lscData_; > }; > > diff --git a/src/ipa/libipa/lsc_table.cpp b/src/ipa/libipa/lsc_table.cpp > index 92e24bc5160a..33f6182de1bd 100644 > --- a/src/ipa/libipa/lsc_table.cpp > +++ b/src/ipa/libipa/lsc_table.cpp > @@ -82,15 +82,15 @@ int LscTable::parseLscComponent(const ValueNode &yamlSet, > return 0; > } > > -std::vector<uint16_t> LscTable::parseTable(const ValueNode &tuningData, > +std::vector<float> LscTable::parseTable(const ValueNode &tuningData, > const char *prop, > unsigned int numHSamples, > unsigned int numVSamples) > { > unsigned int lscNumSamples = numHSamples * numVSamples; > > - std::vector<uint16_t> table = > - tuningData[prop].get<std::vector<uint16_t>>().value_or(utils::defopt); > + std::vector<float> table = > + tuningData[prop].get<std::vector<float>>().value_or(utils::defopt); > if (table.size() != lscNumSamples) { > LOG(LscTable, Error) > << "Invalid '" << prop << "' values: expected " > diff --git a/src/ipa/libipa/lsc_table.h b/src/ipa/libipa/lsc_table.h > index a33208761c15..6d9b0c692b7f 100644 > --- a/src/ipa/libipa/lsc_table.h > +++ b/src/ipa/libipa/lsc_table.h > @@ -42,7 +42,7 @@ public: > private: > int parseLscComponent(const ValueNode &yamlSet, > unsigned int ct, const LscDescriptor &descriptor); > - std::vector<uint16_t> parseTable(const ValueNode &tuningData, > + std::vector<float> parseTable(const ValueNode &tuningData, > const char *prop, > unsigned int numHSamples, > unsigned int numVSamples); > diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp > index 7a95bfcfb93a..dba1a01118ee 100644 > --- a/src/ipa/rkisp1/algorithms/lsc.cpp > +++ b/src/ipa/rkisp1/algorithms/lsc.cpp > @@ -177,14 +177,32 @@ void LensShadingCorrection::setParameters(rkisp1_cif_isp_lsc_config &config) > void LensShadingCorrection::copyTable(rkisp1_cif_isp_lsc_config &config, > const lsc::Components &set) > { > - const auto &r = set.at("r"); > - std::copy(r.begin(), r.end(), &config.r_data_tbl[0][0]); > - const auto &gr = set.at("gr"); > - std::copy(gr.begin(), gr.end(), &config.gr_data_tbl[0][0]); > - const auto &gb = set.at("gb"); > - std::copy(gb.begin(), gb.end(), &config.gb_data_tbl[0][0]); > - const auto &b = set.at("b"); > - std::copy(b.begin(), b.end(), &config.b_data_tbl[0][0]); > + /* > + * The hardware uses 2.10 fixed point format and limits the legal values > + * to [1..3.999]. Scale and clamp the sampled values accordingly. > + */ > + std::vector<uint16_t> regs; > + regs.reserve(RKISP1_CIF_ISP_LSC_SAMPLES_MAX * > + RKISP1_CIF_ISP_LSC_SAMPLES_MAX); I think this can be done without `regs` at all, e.g.: const auto quantizeSet = [&](std::string_view key, float *dst) { const auto &s = set.at(key); std::transform(s.begin(), s.end(), dst, [](float f) { return std::clamp<uint16_t>(f * 1024, 1024, 4095); }); }; quantizeSet("r", &config.r_data_tbl[0][0]); // etc. or maybe even `quantize(key, dst)` could be added as a member function to `lsc::Components`. > + > + for (const float &f : set.at("r")) > + regs.emplace_back(std::clamp(static_cast<int>(f * 1024), 1024, 4095)); > + std::copy(regs.begin(), regs.end(), &config.r_data_tbl[0][0]); > + > + regs = {}; > + for (const float &f : set.at("gr")) > + regs.emplace_back(std::clamp(static_cast<int>(f * 1024), 1024, 4095)); > + std::copy(regs.begin(), regs.end(), &config.gr_data_tbl[0][0]); > + > + regs = {}; > + for (const float &f : set.at("gb")) > + regs.emplace_back(std::clamp(static_cast<int>(f * 1024), 1024, 4095)); > + std::copy(regs.begin(), regs.end(), &config.gb_data_tbl[0][0]); > + > + regs = {}; > + for (const float &f : set.at("b")) > + regs.emplace_back(std::clamp(static_cast<int>(f * 1024), 1024, 4095)); > + std::copy(regs.begin(), regs.end(), &config.b_data_tbl[0][0]); > } > > /** >
diff --git a/src/ipa/libipa/lsc_base.h b/src/ipa/libipa/lsc_base.h index b0b9b3b0712d..386cac55be34 100644 --- a/src/ipa/libipa/lsc_base.h +++ b/src/ipa/libipa/lsc_base.h @@ -26,7 +26,7 @@ namespace ipa { namespace lsc { -using Components = std::map<std::string, std::vector<uint16_t>>; +using Components = std::map<std::string, std::vector<float>>; using ComponentsMap = std::map<unsigned int, Components>; } /* namespace lsc */ diff --git a/src/ipa/libipa/lsc_polynomial.cpp b/src/ipa/libipa/lsc_polynomial.cpp index c61c85fbf2b2..e31a63e06cc8 100644 --- a/src/ipa/libipa/lsc_polynomial.cpp +++ b/src/ipa/libipa/lsc_polynomial.cpp @@ -218,7 +218,7 @@ LscPolynomial::sampleForCrop(const Rectangle &cropRectangle, return components; } -std::vector<uint16_t> +std::vector<float> LscPolynomial::samplePolynomial(const lsc::Polynomial &poly, Span<const double> xPositions, Span<const double> yPositions, @@ -229,7 +229,7 @@ LscPolynomial::samplePolynomial(const lsc::Polynomial &poly, double y0 = cropRectangle.y / m; double w = cropRectangle.width / m; double h = cropRectangle.height / m; - std::vector<uint16_t> samples; + std::vector<float> samples; samples.reserve(xPositions.size() * yPositions.size()); @@ -237,16 +237,9 @@ LscPolynomial::samplePolynomial(const lsc::Polynomial &poly, for (double x : xPositions) { double xp = x0 + x * w; double yp = y0 + y * h; - /* - * The hardware uses 2.10 fixed point format and limits - * the legal values to [1..3.999]. Scale and clamp the - * sampled value accordingly. - */ - int v = static_cast<int>( - poly.sampleAtNormalizedPixelPos(xp, yp) * - 1024); - v = std::clamp(v, 1024, 4095); - samples.push_back(v); + + samples.push_back(static_cast<float> + (poly.sampleAtNormalizedPixelPos(xp, yp))); } } return samples; diff --git a/src/ipa/libipa/lsc_polynomial.h b/src/ipa/libipa/lsc_polynomial.h index 6d19e46a50b7..8d526531075b 100644 --- a/src/ipa/libipa/lsc_polynomial.h +++ b/src/ipa/libipa/lsc_polynomial.h @@ -65,10 +65,10 @@ public: std::vector<double> xPos, std::vector<double> yPos) override; private: - std::vector<uint16_t> samplePolynomial(const lsc::Polynomial &poly, - Span<const double> xPositions, - Span<const double> yPositions, - const Rectangle &cropRectangle); + std::vector<float> samplePolynomial(const lsc::Polynomial &poly, + Span<const double> xPositions, + Span<const double> yPositions, + const Rectangle &cropRectangle); PolynomialComponentsMap lscData_; }; diff --git a/src/ipa/libipa/lsc_table.cpp b/src/ipa/libipa/lsc_table.cpp index 92e24bc5160a..33f6182de1bd 100644 --- a/src/ipa/libipa/lsc_table.cpp +++ b/src/ipa/libipa/lsc_table.cpp @@ -82,15 +82,15 @@ int LscTable::parseLscComponent(const ValueNode &yamlSet, return 0; } -std::vector<uint16_t> LscTable::parseTable(const ValueNode &tuningData, +std::vector<float> LscTable::parseTable(const ValueNode &tuningData, const char *prop, unsigned int numHSamples, unsigned int numVSamples) { unsigned int lscNumSamples = numHSamples * numVSamples; - std::vector<uint16_t> table = - tuningData[prop].get<std::vector<uint16_t>>().value_or(utils::defopt); + std::vector<float> table = + tuningData[prop].get<std::vector<float>>().value_or(utils::defopt); if (table.size() != lscNumSamples) { LOG(LscTable, Error) << "Invalid '" << prop << "' values: expected " diff --git a/src/ipa/libipa/lsc_table.h b/src/ipa/libipa/lsc_table.h index a33208761c15..6d9b0c692b7f 100644 --- a/src/ipa/libipa/lsc_table.h +++ b/src/ipa/libipa/lsc_table.h @@ -42,7 +42,7 @@ public: private: int parseLscComponent(const ValueNode &yamlSet, unsigned int ct, const LscDescriptor &descriptor); - std::vector<uint16_t> parseTable(const ValueNode &tuningData, + std::vector<float> parseTable(const ValueNode &tuningData, const char *prop, unsigned int numHSamples, unsigned int numVSamples); diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp index 7a95bfcfb93a..dba1a01118ee 100644 --- a/src/ipa/rkisp1/algorithms/lsc.cpp +++ b/src/ipa/rkisp1/algorithms/lsc.cpp @@ -177,14 +177,32 @@ void LensShadingCorrection::setParameters(rkisp1_cif_isp_lsc_config &config) void LensShadingCorrection::copyTable(rkisp1_cif_isp_lsc_config &config, const lsc::Components &set) { - const auto &r = set.at("r"); - std::copy(r.begin(), r.end(), &config.r_data_tbl[0][0]); - const auto &gr = set.at("gr"); - std::copy(gr.begin(), gr.end(), &config.gr_data_tbl[0][0]); - const auto &gb = set.at("gb"); - std::copy(gb.begin(), gb.end(), &config.gb_data_tbl[0][0]); - const auto &b = set.at("b"); - std::copy(b.begin(), b.end(), &config.b_data_tbl[0][0]); + /* + * The hardware uses 2.10 fixed point format and limits the legal values + * to [1..3.999]. Scale and clamp the sampled values accordingly. + */ + std::vector<uint16_t> regs; + regs.reserve(RKISP1_CIF_ISP_LSC_SAMPLES_MAX * + RKISP1_CIF_ISP_LSC_SAMPLES_MAX); + + for (const float &f : set.at("r")) + regs.emplace_back(std::clamp(static_cast<int>(f * 1024), 1024, 4095)); + std::copy(regs.begin(), regs.end(), &config.r_data_tbl[0][0]); + + regs = {}; + for (const float &f : set.at("gr")) + regs.emplace_back(std::clamp(static_cast<int>(f * 1024), 1024, 4095)); + std::copy(regs.begin(), regs.end(), &config.gr_data_tbl[0][0]); + + regs = {}; + for (const float &f : set.at("gb")) + regs.emplace_back(std::clamp(static_cast<int>(f * 1024), 1024, 4095)); + std::copy(regs.begin(), regs.end(), &config.gb_data_tbl[0][0]); + + regs = {}; + for (const float &f : set.at("b")) + regs.emplace_back(std::clamp(static_cast<int>(f * 1024), 1024, 4095)); + std::copy(regs.begin(), regs.end(), &config.b_data_tbl[0][0]); } /**
The libIPA Lsc algorithm currently assumes the register format of the RkISP1 platform (16 bits Q2.10 format), as that's where the implementation has been derived from. Move the register quantization to the plaltform IPA and use 'floats' as the exchange format for the table-based and polynomial-based LSC implementations. Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> --- src/ipa/libipa/lsc_base.h | 2 +- src/ipa/libipa/lsc_polynomial.cpp | 17 +++++------------ src/ipa/libipa/lsc_polynomial.h | 8 ++++---- src/ipa/libipa/lsc_table.cpp | 6 +++--- src/ipa/libipa/lsc_table.h | 2 +- src/ipa/rkisp1/algorithms/lsc.cpp | 34 ++++++++++++++++++++++++++-------- 6 files changed, 40 insertions(+), 29 deletions(-)