libcamera  v0.3.2+116-83c5ad0f
Supporting cameras in Linux since 2019
lsc_polynomial.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /*
3  * Copyright (C) 2024, Ideas On Board
4  *
5  * Helper for radial polynomial used in lens shading correction.
6  */
7 #pragma once
8 
9 #include <algorithm>
10 #include <array>
11 #include <assert.h>
12 #include <cmath>
13 
14 #include <libcamera/base/log.h>
15 #include <libcamera/base/span.h>
16 
18 
19 namespace libcamera {
20 
21 LOG_DECLARE_CATEGORY(LscPolynomial)
22 
23 namespace ipa {
24 
26 {
27 public:
28  LscPolynomial(double cx = 0.0, double cy = 0.0, double k0 = 0.0,
29  double k1 = 0.0, double k2 = 0.0, double k3 = 0.0,
30  double k4 = 0.0)
31  : cx_(cx), cy_(cy), cnx_(0), cny_(0),
32  coefficients_({ k0, k1, k2, k3, k4 })
33  {
34  }
35 
36  double sampleAtNormalizedPixelPos(double x, double y) const
37  {
38  double dx = x - cnx_;
39  double dy = y - cny_;
40  double r = sqrt(dx * dx + dy * dy);
41  double res = 1.0;
42  for (unsigned int i = 0; i < coefficients_.size(); i++) {
43  res += coefficients_[i] * std::pow(r, (i + 1) * 2);
44  }
45  return res;
46  }
47 
48  double getM() const
49  {
50  double cpx = imageSize_.width * cx_;
51  double cpy = imageSize_.height * cy_;
52  double mx = std::max(cpx, std::fabs(imageSize_.width - cpx));
53  double my = std::max(cpy, std::fabs(imageSize_.height - cpy));
54 
55  return sqrt(mx * mx + my * my);
56  }
57 
58  void setReferenceImageSize(const Size &size)
59  {
60  assert(!size.isNull());
61  imageSize_ = size;
62 
63  /* Calculate normalized centers */
64  double m = getM();
65  cnx_ = (size.width * cx_) / m;
66  cny_ = (size.height * cy_) / m;
67  }
68 
69 private:
70  double cx_;
71  double cy_;
72  double cnx_;
73  double cny_;
74  std::array<double, 5> coefficients_;
75 
76  Size imageSize_;
77 };
78 
79 } /* namespace ipa */
80 
81 #ifndef __DOXYGEN__
82 
83 template<>
84 struct YamlObject::Getter<ipa::LscPolynomial> {
85  std::optional<ipa::LscPolynomial> get(const YamlObject &obj) const
86  {
87  std::optional<double> cx = obj["cx"].get<double>();
88  std::optional<double> cy = obj["cy"].get<double>();
89  std::optional<double> k0 = obj["k0"].get<double>();
90  std::optional<double> k1 = obj["k1"].get<double>();
91  std::optional<double> k2 = obj["k2"].get<double>();
92  std::optional<double> k3 = obj["k3"].get<double>();
93  std::optional<double> k4 = obj["k4"].get<double>();
94 
95  if (!(cx && cy && k0 && k1 && k2 && k3 && k4))
96  LOG(LscPolynomial, Error)
97  << "Polynomial is missing a parameter";
98 
99  return ipa::LscPolynomial(*cx, *cy, *k0, *k1, *k2, *k3, *k4);
100  }
101 };
102 
103 #endif
104 
105 } /* namespace libcamera */
double sampleAtNormalizedPixelPos(double x, double y) const
Sample the polynomial at the given normalized pixel position.
Definition: lsc_polynomial.h:36
#define LOG(category, severity)
Log a message.
Top-level libcamera namespace.
Definition: backtrace.h:17
Describe a two-dimensional size.
Definition: geometry.h:52
bool isNull() const
Check if the size is null.
Definition: geometry.h:68
#define LOG_DECLARE_CATEGORY(name)
Declare a category of log messages.
unsigned int width
The Size width.
Definition: geometry.h:65
unsigned int height
The Size height.
Definition: geometry.h:66
double getM() const
Get the value m as described in the dng specification.
Definition: lsc_polynomial.h:48
A class representing the tree structure of the YAML content.
Definition: yaml_parser.h:27
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)
Construct a polynomial using the given coefficients.
Definition: lsc_polynomial.h:28
Logging infrastructure.
Class for handling even polynomials used in lens shading correction.
Definition: lsc_polynomial.h:25
A YAML parser helper.
void setReferenceImageSize(const Size &size)
Set the reference image size.
Definition: lsc_polynomial.h:58