diff options
Diffstat (limited to 'src/ipa/libipa')
-rw-r--r-- | src/ipa/libipa/camera_sensor_helper.cpp | 140 | ||||
-rw-r--r-- | src/ipa/libipa/camera_sensor_helper.h | 6 | ||||
-rw-r--r-- | src/ipa/libipa/histogram.h | 1 | ||||
-rw-r--r-- | src/ipa/libipa/matrix.h | 1 | ||||
-rw-r--r-- | src/ipa/libipa/matrix_interpolator.cpp | 7 | ||||
-rw-r--r-- | src/ipa/libipa/matrix_interpolator.h | 2 | ||||
-rw-r--r-- | src/ipa/libipa/pwl.cpp | 2 | ||||
-rw-r--r-- | src/ipa/libipa/pwl.h | 3 | ||||
-rw-r--r-- | src/ipa/libipa/vector.h | 4 |
9 files changed, 146 insertions, 20 deletions
diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp index 782ff990..ffc7c1d7 100644 --- a/src/ipa/libipa/camera_sensor_helper.cpp +++ b/src/ipa/libipa/camera_sensor_helper.cpp @@ -8,6 +8,7 @@ #include "camera_sensor_helper.h" #include <cmath> +#include <limits> #include <libcamera/base/log.h> @@ -40,6 +41,7 @@ namespace ipa { */ /** + * \fn CameraSensorHelper::CameraSensorHelper() * \brief Construct a CameraSensorHelper instance * * CameraSensorHelper derived class instances shall never be constructed @@ -48,6 +50,33 @@ namespace ipa { */ /** + * \fn CameraSensorHelper::blackLevel() + * \brief Fetch the black level of the sensor + * + * This function returns the black level of the sensor scaled to a 16bit pixel + * width. If it is unknown an empty optional is returned. + * + * \todo Fill the blanks and add pedestal values for all supported sensors. Once + * done, drop the std::optional<>. + * + * Black levels are typically the result of the following phenomena: + * - Pedestal added by the sensor to pixel values. They are typically fixed, + * sometimes programmable and should be reported in datasheets (but + * documentation is not always available). + * - Dark currents and other physical effects that add charge to pixels in the + * absence of light. Those can depend on the integration time and the sensor + * die temperature, and their contribution to pixel values depend on the + * sensor gains. + * + * The pedestal is usually the value with the biggest contribution to the + * overall black level. In most cases it is either known before or in rare cases + * (there is not a single driver with such a control in the linux kernel) can be + * queried from the sensor. This function provides that fixed, known value. + * + * \return The black level of the sensor, or std::nullopt if not known + */ + +/** * \brief Compute gain code from the analogue gain absolute value * \param[in] gain The real gain to pass * @@ -205,6 +234,12 @@ double CameraSensorHelper::gain(uint32_t gainCode) const */ /** + * \var CameraSensorHelper::blackLevel_ + * \brief The black level of the sensor + * \sa CameraSensorHelper::blackLevel() + */ + +/** * \var CameraSensorHelper::gainType_ * \brief The analogue gain model type */ @@ -366,6 +401,99 @@ static constexpr double expGainDb(double step) return log2_10 * step / 20; } +class CameraSensorHelperAr0144 : public CameraSensorHelper +{ +public: + CameraSensorHelperAr0144() + { + /* Power-on default value: 168 at 12bits. */ + blackLevel_ = 2688; + } + + uint32_t gainCode(double gain) const override + { + /* The recommended minimum gain is 1.6842 to avoid artifacts. */ + gain = std::clamp(gain, 1.0 / (1.0 - 13.0 / 32.0), 18.45); + + /* + * The analogue gain is made of a coarse exponential gain in + * the range [2^0, 2^4] and a fine inversely linear gain in the + * range [1.0, 2.0[. There is an additional fixed 1.153125 + * multiplier when the coarse gain reaches 2^2. + */ + + if (gain > 4.0) + gain /= 1.153125; + + unsigned int coarse = std::log2(gain); + unsigned int fine = (1 - (1 << coarse) / gain) * 32; + + /* The fine gain rounding depends on the coarse gain. */ + if (coarse == 1 || coarse == 3) + fine &= ~1; + else if (coarse == 4) + fine &= ~3; + + return (coarse << 4) | (fine & 0xf); + } + + double gain(uint32_t gainCode) const override + { + unsigned int coarse = gainCode >> 4; + unsigned int fine = gainCode & 0xf; + unsigned int d1; + double d2, m; + + switch (coarse) { + default: + case 0: + d1 = 1; + d2 = 32.0; + m = 1.0; + break; + case 1: + d1 = 2; + d2 = 16.0; + m = 1.0; + break; + case 2: + d1 = 1; + d2 = 32.0; + m = 1.153125; + break; + case 3: + d1 = 2; + d2 = 16.0; + m = 1.153125; + break; + case 4: + d1 = 4; + d2 = 8.0; + m = 1.153125; + break; + } + + /* + * With infinite precision, the calculated gain would be exact, + * and the reverse conversion with gainCode() would produce the + * same gain code. In the real world, rounding errors may cause + * the calculated gain to be lower by an amount negligible for + * all purposes, except for the reverse conversion. Converting + * the gain to a gain code could then return the quantized value + * just lower than the original gain code. To avoid this, tests + * showed that adding the machine epsilon to the multiplier m is + * sufficient. + */ + m += std::numeric_limits<decltype(m)>::epsilon(); + + return m * (1 << coarse) / (1.0 - (fine / d1) / d2); + } + +private: + static constexpr double kStep_ = 16; +}; +REGISTER_CAMERA_SENSOR_HELPER("ar0144", CameraSensorHelperAr0144) + class CameraSensorHelperAr0521 : public CameraSensorHelper { public: @@ -396,6 +524,8 @@ class CameraSensorHelperImx219 : public CameraSensorHelper public: CameraSensorHelperImx219() { + /* From datasheet: 64 at 10bits. */ + blackLevel_ = 4096; gainType_ = AnalogueGainLinear; gainConstants_.linear = { 0, 256, -1, 256 }; } @@ -407,6 +537,8 @@ class CameraSensorHelperImx258 : public CameraSensorHelper public: CameraSensorHelperImx258() { + /* From datasheet: 0x40 at 10bits. */ + blackLevel_ = 4096; gainType_ = AnalogueGainLinear; gainConstants_.linear = { 0, 512, -1, 512 }; } @@ -456,6 +588,8 @@ class CameraSensorHelperImx335 : public CameraSensorHelper public: CameraSensorHelperImx335() { + /* From datasheet: 0x32 at 10bits. */ + blackLevel_ = 3200; gainType_ = AnalogueGainExponential; gainConstants_.exp = { 1.0, expGainDb(0.3) }; } @@ -515,6 +649,8 @@ class CameraSensorHelperOv4689 : public CameraSensorHelper public: CameraSensorHelperOv4689() { + /* From datasheet: 0x40 at 12bits. */ + blackLevel_ = 1024; gainType_ = AnalogueGainLinear; gainConstants_.linear = { 1, 0, 0, 128 }; } @@ -526,6 +662,8 @@ class CameraSensorHelperOv5640 : public CameraSensorHelper public: CameraSensorHelperOv5640() { + /* From datasheet: 0x10 at 10bits. */ + blackLevel_ = 1024; gainType_ = AnalogueGainLinear; gainConstants_.linear = { 1, 0, 0, 16 }; } @@ -559,6 +697,8 @@ class CameraSensorHelperOv5675 : public CameraSensorHelper public: CameraSensorHelperOv5675() { + /* From Linux kernel driver: 0x40 at 10bits. */ + blackLevel_ = 4096; gainType_ = AnalogueGainLinear; gainConstants_.linear = { 1, 0, 0, 128 }; } diff --git a/src/ipa/libipa/camera_sensor_helper.h b/src/ipa/libipa/camera_sensor_helper.h index 0d99073b..75868205 100644 --- a/src/ipa/libipa/camera_sensor_helper.h +++ b/src/ipa/libipa/camera_sensor_helper.h @@ -7,9 +7,9 @@ #pragma once -#include <stdint.h> - #include <memory> +#include <optional> +#include <stdint.h> #include <string> #include <vector> @@ -25,6 +25,7 @@ public: CameraSensorHelper() = default; virtual ~CameraSensorHelper() = default; + std::optional<int16_t> blackLevel() const { return blackLevel_; } virtual uint32_t gainCode(double gain) const; virtual double gain(uint32_t gainCode) const; @@ -51,6 +52,7 @@ protected: AnalogueGainExpConstants exp; }; + std::optional<int16_t> blackLevel_; AnalogueGainType gainType_; AnalogueGainConstants gainConstants_; diff --git a/src/ipa/libipa/histogram.h b/src/ipa/libipa/histogram.h index 032adca0..6fd64168 100644 --- a/src/ipa/libipa/histogram.h +++ b/src/ipa/libipa/histogram.h @@ -7,7 +7,6 @@ #pragma once -#include <assert.h> #include <limits.h> #include <stdint.h> #include <type_traits> diff --git a/src/ipa/libipa/matrix.h b/src/ipa/libipa/matrix.h index 8aa8f343..5471e697 100644 --- a/src/ipa/libipa/matrix.h +++ b/src/ipa/libipa/matrix.h @@ -7,7 +7,6 @@ #pragma once #include <algorithm> -#include <cmath> #include <sstream> #include <vector> diff --git a/src/ipa/libipa/matrix_interpolator.cpp b/src/ipa/libipa/matrix_interpolator.cpp index 04ca177f..d5188f8a 100644 --- a/src/ipa/libipa/matrix_interpolator.cpp +++ b/src/ipa/libipa/matrix_interpolator.cpp @@ -6,15 +6,8 @@ */ #include "matrix_interpolator.h" -#include <algorithm> -#include <string> - #include <libcamera/base/log.h> -#include "libcamera/internal/yaml_parser.h" - -#include "matrix.h" - /** * \file matrix_interpolator.h * \brief Helper class for interpolating maps of matrices diff --git a/src/ipa/libipa/matrix_interpolator.h b/src/ipa/libipa/matrix_interpolator.h index 087c4fd1..afbce538 100644 --- a/src/ipa/libipa/matrix_interpolator.h +++ b/src/ipa/libipa/matrix_interpolator.h @@ -7,10 +7,8 @@ #pragma once -#include <algorithm> #include <map> #include <string> -#include <tuple> #include <libcamera/base/log.h> diff --git a/src/ipa/libipa/pwl.cpp b/src/ipa/libipa/pwl.cpp index 9b213754..88fe2022 100644 --- a/src/ipa/libipa/pwl.cpp +++ b/src/ipa/libipa/pwl.cpp @@ -8,10 +8,8 @@ #include "pwl.h" -#include <assert.h> #include <cmath> #include <sstream> -#include <stdexcept> /** * \file pwl.h diff --git a/src/ipa/libipa/pwl.h b/src/ipa/libipa/pwl.h index b6f93494..d4ec9f4f 100644 --- a/src/ipa/libipa/pwl.h +++ b/src/ipa/libipa/pwl.h @@ -7,14 +7,11 @@ #pragma once #include <algorithm> -#include <cmath> #include <functional> #include <string> #include <utility> #include <vector> -#include "libcamera/internal/yaml_parser.h" - #include "vector.h" namespace libcamera { diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h index 556e0967..8612a06a 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -6,10 +6,10 @@ */ #pragma once -#include <algorithm> #include <array> #include <cmath> -#include <sstream> +#include <optional> +#include <ostream> #include <libcamera/base/log.h> #include <libcamera/base/span.h> |