@@ -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 */
@@ -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;
@@ -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_;
};
@@ -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 "
@@ -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);
@@ -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(-)