Add a basic class to represent polynomials as specified in the DNG spec for vignetting correction. Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
106 lines
2.4 KiB
C++
106 lines
2.4 KiB
C++
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
/*
|
|
* Copyright (C) 2024, Ideas On Board
|
|
*
|
|
* Helper for radial polynomial used in lens shading correction.
|
|
*/
|
|
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <assert.h>
|
|
#include <cmath>
|
|
|
|
#include <libcamera/base/log.h>
|
|
#include <libcamera/base/span.h>
|
|
|
|
#include "libcamera/internal/yaml_parser.h"
|
|
|
|
namespace libcamera {
|
|
|
|
LOG_DECLARE_CATEGORY(LscPolynomial)
|
|
|
|
namespace ipa {
|
|
|
|
class LscPolynomial
|
|
{
|
|
public:
|
|
LscPolynomial(double cx = 0.0, double cy = 0.0, double k0 = 0.0,
|
|
double k1 = 0.0, double k2 = 0.0, double k3 = 0.0,
|
|
double k4 = 0.0)
|
|
: cx_(cx), cy_(cy), cnx_(0), cny_(0),
|
|
coefficients_({ k0, k1, k2, k3, k4 })
|
|
{
|
|
}
|
|
|
|
double sampleAtNormalizedPixelPos(double x, double y) const
|
|
{
|
|
double dx = x - cnx_;
|
|
double dy = y - cny_;
|
|
double r = sqrt(dx * dx + dy * dy);
|
|
double res = 1.0;
|
|
for (unsigned int i = 0; i < coefficients_.size(); i++) {
|
|
res += coefficients_[i] * std::pow(r, (i + 1) * 2);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
double getM() const
|
|
{
|
|
double cpx = imageSize_.width * cx_;
|
|
double cpy = imageSize_.height * cy_;
|
|
double mx = std::max(cpx, std::fabs(imageSize_.width - cpx));
|
|
double my = std::max(cpy, std::fabs(imageSize_.height - cpy));
|
|
|
|
return sqrt(mx * mx + my * my);
|
|
}
|
|
|
|
void setReferenceImageSize(const Size &size)
|
|
{
|
|
assert(!size.isNull());
|
|
imageSize_ = size;
|
|
|
|
/* Calculate normalized centers */
|
|
double m = getM();
|
|
cnx_ = (size.width * cx_) / m;
|
|
cny_ = (size.height * cy_) / m;
|
|
}
|
|
|
|
private:
|
|
double cx_;
|
|
double cy_;
|
|
double cnx_;
|
|
double cny_;
|
|
std::array<double, 5> coefficients_;
|
|
|
|
Size imageSize_;
|
|
};
|
|
|
|
} /* namespace ipa */
|
|
|
|
#ifndef __DOXYGEN__
|
|
|
|
template<>
|
|
struct YamlObject::Getter<ipa::LscPolynomial> {
|
|
std::optional<ipa::LscPolynomial> get(const YamlObject &obj) const
|
|
{
|
|
std::optional<double> cx = obj["cx"].get<double>();
|
|
std::optional<double> cy = obj["cy"].get<double>();
|
|
std::optional<double> k0 = obj["k0"].get<double>();
|
|
std::optional<double> k1 = obj["k1"].get<double>();
|
|
std::optional<double> k2 = obj["k2"].get<double>();
|
|
std::optional<double> k3 = obj["k3"].get<double>();
|
|
std::optional<double> k4 = obj["k4"].get<double>();
|
|
|
|
if (!(cx && cy && k0 && k1 && k2 && k3 && k4))
|
|
LOG(LscPolynomial, Error)
|
|
<< "Polynomial is missing a parameter";
|
|
|
|
return ipa::LscPolynomial(*cx, *cy, *k0, *k1, *k2, *k3, *k4);
|
|
}
|
|
};
|
|
|
|
#endif
|
|
|
|
} /* namespace libcamera */
|