diff options
author | Paul Elder <paul.elder@ideasonboard.com> | 2024-06-14 20:37:56 +0900 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2024-06-17 12:18:51 +0300 |
commit | f1959b9f313a33600eda575f32bbd06143a0cc45 (patch) | |
tree | 754ec8230040e0071392382d42da43d0bf10deb7 /src/ipa/libipa/matrix_interpolator.h | |
parent | f191c10fe180fefac418fa41a3c49f5b18f9a3d7 (diff) |
ipa: libipa: Add MatrixInterpolator class
Add a class to encapsulate the functionality of fetching a matrix based
on an integer key, and interpolating if there is no exact match. This is
expected to be used by both color correction matrices / crosstalk
correction as well as lens shading correction.
A cache is included only for exact matches of the key. The caller is
expected to decide the tolererance for rounding.
Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src/ipa/libipa/matrix_interpolator.h')
-rw-r--r-- | src/ipa/libipa/matrix_interpolator.h | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/src/ipa/libipa/matrix_interpolator.h b/src/ipa/libipa/matrix_interpolator.h new file mode 100644 index 00000000..087c4fd1 --- /dev/null +++ b/src/ipa/libipa/matrix_interpolator.h @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com> + * + * Helper class for interpolating maps of matrices + */ + +#pragma once + +#include <algorithm> +#include <map> +#include <string> +#include <tuple> + +#include <libcamera/base/log.h> + +#include "libcamera/internal/yaml_parser.h" + +#include "matrix.h" + +namespace libcamera { + +LOG_DECLARE_CATEGORY(MatrixInterpolator) + +namespace ipa { + +#ifndef __DOXYGEN__ +template<typename T, unsigned int R, unsigned int C, + std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr> +#else +template<typename T, unsigned int R, unsigned int C> +#endif /* __DOXYGEN__ */ +class MatrixInterpolator +{ +public: + MatrixInterpolator() + { + reset(); + } + + MatrixInterpolator(const std::map<unsigned int, Matrix<T, R, C>> &matrices) + { + for (const auto &pair : matrices) + matrices_[pair.first] = pair.second; + } + + ~MatrixInterpolator() {} + + void reset() + { + matrices_.clear(); + matrices_[0] = Matrix<T, R, C>::identity(); + } + + int readYaml(const libcamera::YamlObject &yaml, + const std::string &key_name, + const std::string &matrix_name) + { + matrices_.clear(); + + if (!yaml.isList()) { + LOG(MatrixInterpolator, Error) << "yaml object must be a list"; + return -EINVAL; + } + + for (const auto &value : yaml.asList()) { + unsigned int ct = std::stoul(value[key_name].get<std::string>("")); + std::optional<Matrix<T, R, C>> matrix = + value[matrix_name].get<Matrix<T, R, C>>(); + if (!matrix) { + LOG(MatrixInterpolator, Error) << "Failed to read matrix"; + return -EINVAL; + } + + matrices_[ct] = *matrix; + + LOG(MatrixInterpolator, Debug) + << "Read matrix '" << matrix_name << "' for key '" + << key_name << "' " << ct << ": " + << matrices_[ct].toString(); + } + + if (matrices_.size() < 1) { + LOG(MatrixInterpolator, Error) << "Need at least one matrix"; + return -EINVAL; + } + + return 0; + } + + Matrix<T, R, C> get(unsigned int ct) + { + ASSERT(matrices_.size() > 0); + + if (matrices_.size() == 1 || + ct <= matrices_.begin()->first) + return matrices_.begin()->second; + + if (ct >= matrices_.rbegin()->first) + return matrices_.rbegin()->second; + + if (matrices_.find(ct) != matrices_.end()) + return matrices_[ct]; + + /* The above four guarantee that this will succeed */ + auto iter = matrices_.upper_bound(ct); + unsigned int ctUpper = iter->first; + unsigned int ctLower = (--iter)->first; + + double lambda = (ct - ctLower) / static_cast<double>(ctUpper - ctLower); + Matrix<T, R, C> ret = + lambda * matrices_[ctUpper] + (1.0 - lambda) * matrices_[ctLower]; + return ret; + } + +private: + std::map<unsigned int, Matrix<T, R, C>> matrices_; +}; + +} /* namespace ipa */ + +} /* namespace libcamera */ |