diff options
Diffstat (limited to 'src/ipa/raspberrypi')
85 files changed, 0 insertions, 12300 deletions
diff --git a/src/ipa/raspberrypi/README.md b/src/ipa/raspberrypi/README.md deleted file mode 100644 index 94a8ccc8..00000000 --- a/src/ipa/raspberrypi/README.md +++ /dev/null @@ -1,25 +0,0 @@ -.. SPDX-License-Identifier: BSD-2-Clause - -# _libcamera_ for the Raspberry Pi - -Raspberry Pi provides a fully featured pipeline handler and control algorithms -(IPAs, or "Image Processing Algorithms") to work with _libcamera_. Support is -included for all existing Raspberry Pi camera modules. - -_libcamera_ for the Raspberry Pi allows users to: - -1. Use their existing Raspberry Pi cameras. -1. Change the tuning of the image processing for their Raspberry Pi cameras. -1. Alter or amend the control algorithms (such as AGC/AEC, AWB or any others) - that control the sensor and ISP. -1. Implement their own custom control algorithms. -1. Supply new tunings and/or algorithms for completely new sensors. - -## How to install and run _libcamera_ on the Raspberry Pi - -Please follow the instructions [here](https://www.raspberrypi.com/documentation/accessories/camera.html). - -## Documentation - -Full documentation for the _Raspberry Pi Camera Algorithm and Tuning Guide_ can -be found [here](https://datasheets.raspberrypi.com/camera/raspberry-pi-camera-guide.pdf). diff --git a/src/ipa/raspberrypi/cam_helper.cpp b/src/ipa/raspberrypi/cam_helper.cpp deleted file mode 100644 index 3f81d418..00000000 --- a/src/ipa/raspberrypi/cam_helper.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * cam_helper.cpp - helper information for different sensors - */ - -#include <linux/videodev2.h> - -#include <assert.h> -#include <map> -#include <string.h> - -#include "libcamera/internal/v4l2_videodevice.h" - -#include "cam_helper.hpp" -#include "md_parser.hpp" - -using namespace RPiController; -using namespace libcamera; -using libcamera::utils::Duration; - -namespace libcamera { -LOG_DECLARE_CATEGORY(IPARPI) -} - -static std::map<std::string, CamHelperCreateFunc> cam_helpers; - -CamHelper *CamHelper::Create(std::string const &cam_name) -{ - /* - * CamHelpers get registered by static RegisterCamHelper - * initialisers. - */ - for (auto &p : cam_helpers) { - if (cam_name.find(p.first) != std::string::npos) - return p.second(); - } - - return nullptr; -} - -CamHelper::CamHelper(std::unique_ptr<MdParser> parser, unsigned int frameIntegrationDiff) - : parser_(std::move(parser)), initialized_(false), - frameIntegrationDiff_(frameIntegrationDiff) -{ -} - -CamHelper::~CamHelper() -{ -} - -void CamHelper::Prepare(Span<const uint8_t> buffer, - Metadata &metadata) -{ - parseEmbeddedData(buffer, metadata); -} - -void CamHelper::Process([[maybe_unused]] StatisticsPtr &stats, - [[maybe_unused]] Metadata &metadata) -{ -} - -uint32_t CamHelper::ExposureLines(const Duration exposure) const -{ - assert(initialized_); - return exposure / mode_.line_length; -} - -Duration CamHelper::Exposure(uint32_t exposure_lines) const -{ - assert(initialized_); - return exposure_lines * mode_.line_length; -} - -uint32_t CamHelper::GetVBlanking(Duration &exposure, - Duration minFrameDuration, - Duration maxFrameDuration) const -{ - uint32_t frameLengthMin, frameLengthMax, vblank; - uint32_t exposureLines = ExposureLines(exposure); - - assert(initialized_); - - /* - * minFrameDuration and maxFrameDuration are clamped by the caller - * based on the limits for the active sensor mode. - */ - frameLengthMin = minFrameDuration / mode_.line_length; - frameLengthMax = maxFrameDuration / mode_.line_length; - - /* - * Limit the exposure to the maximum frame duration requested, and - * re-calculate if it has been clipped. - */ - exposureLines = std::min(frameLengthMax - frameIntegrationDiff_, exposureLines); - exposure = Exposure(exposureLines); - - /* Limit the vblank to the range allowed by the frame length limits. */ - vblank = std::clamp(exposureLines + frameIntegrationDiff_, - frameLengthMin, frameLengthMax) - mode_.height; - return vblank; -} - -void CamHelper::SetCameraMode(const CameraMode &mode) -{ - mode_ = mode; - if (parser_) { - parser_->SetBitsPerPixel(mode.bitdepth); - parser_->SetLineLengthBytes(0); /* We use SetBufferSize. */ - } - initialized_ = true; -} - -void CamHelper::GetDelays(int &exposure_delay, int &gain_delay, - int &vblank_delay) const -{ - /* - * These values are correct for many sensors. Other sensors will - * need to over-ride this function. - */ - exposure_delay = 2; - gain_delay = 1; - vblank_delay = 2; -} - -bool CamHelper::SensorEmbeddedDataPresent() const -{ - return false; -} - -double CamHelper::GetModeSensitivity([[maybe_unused]] const CameraMode &mode) const -{ - /* - * Most sensors have the same sensitivity in every mode, but this - * function can be overridden for those that do not. Note that it is - * called before mode_ is set, so it must return the sensitivity - * of the mode that is passed in. - */ - return 1.0; -} - -unsigned int CamHelper::HideFramesStartup() const -{ - /* - * The number of frames when a camera first starts that shouldn't be - * displayed as they are invalid in some way. - */ - return 0; -} - -unsigned int CamHelper::HideFramesModeSwitch() const -{ - /* After a mode switch, many sensors return valid frames immediately. */ - return 0; -} - -unsigned int CamHelper::MistrustFramesStartup() const -{ - /* Many sensors return a single bad frame on start-up. */ - return 1; -} - -unsigned int CamHelper::MistrustFramesModeSwitch() const -{ - /* Many sensors return valid metadata immediately. */ - return 0; -} - -void CamHelper::parseEmbeddedData(Span<const uint8_t> buffer, - Metadata &metadata) -{ - MdParser::RegisterMap registers; - Metadata parsedMetadata; - - if (buffer.empty()) - return; - - if (parser_->Parse(buffer, registers) != MdParser::Status::OK) { - LOG(IPARPI, Error) << "Embedded data buffer parsing failed"; - return; - } - - PopulateMetadata(registers, parsedMetadata); - metadata.Merge(parsedMetadata); - - /* - * Overwrite the exposure/gain, frame length and sensor temperature values - * in the existing DeviceStatus with values from the parsed embedded buffer. - * Fetch it first in case any other fields were set meaningfully. - */ - DeviceStatus deviceStatus, parsedDeviceStatus; - if (metadata.Get("device.status", deviceStatus) || - parsedMetadata.Get("device.status", parsedDeviceStatus)) { - LOG(IPARPI, Error) << "DeviceStatus not found"; - return; - } - - deviceStatus.shutter_speed = parsedDeviceStatus.shutter_speed; - deviceStatus.analogue_gain = parsedDeviceStatus.analogue_gain; - deviceStatus.frame_length = parsedDeviceStatus.frame_length; - if (parsedDeviceStatus.sensor_temperature) - deviceStatus.sensor_temperature = parsedDeviceStatus.sensor_temperature; - - LOG(IPARPI, Debug) << "Metadata updated - " << deviceStatus; - - metadata.Set("device.status", deviceStatus); -} - -void CamHelper::PopulateMetadata([[maybe_unused]] const MdParser::RegisterMap ®isters, - [[maybe_unused]] Metadata &metadata) const -{ -} - -RegisterCamHelper::RegisterCamHelper(char const *cam_name, - CamHelperCreateFunc create_func) -{ - cam_helpers[std::string(cam_name)] = create_func; -} diff --git a/src/ipa/raspberrypi/cam_helper.hpp b/src/ipa/raspberrypi/cam_helper.hpp deleted file mode 100644 index 300f8f8a..00000000 --- a/src/ipa/raspberrypi/cam_helper.hpp +++ /dev/null @@ -1,123 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * cam_helper.hpp - helper class providing camera information - */ -#pragma once - -#include <memory> -#include <string> - -#include <libcamera/base/span.h> -#include <libcamera/base/utils.h> - -#include "camera_mode.h" -#include "controller/controller.hpp" -#include "controller/metadata.hpp" -#include "md_parser.hpp" - -#include "libcamera/internal/v4l2_videodevice.h" - -namespace RPiController { - -// The CamHelper class provides a number of facilities that anyone trying -// to drive a camera will need to know, but which are not provided by the -// standard driver framework. Specifically, it provides: -// -// A "CameraMode" structure to describe extra information about the chosen -// mode of the driver. For example, how it is cropped from the full sensor -// area, how it is scaled, whether pixels are averaged compared to the full -// resolution. -// -// The ability to convert between number of lines of exposure and actual -// exposure time, and to convert between the sensor's gain codes and actual -// gains. -// -// A function to return the number of frames of delay between updating exposure, -// analogue gain and vblanking, and for the changes to take effect. For many -// sensors these take the values 2, 1 and 2 respectively, but sensors that are -// different will need to over-ride the default function provided. -// -// A function to query if the sensor outputs embedded data that can be parsed. -// -// A function to return the sensitivity of a given camera mode. -// -// A parser to parse the embedded data buffers provided by some sensors (for -// example, the imx219 does; the ov5647 doesn't). This allows us to know for -// sure the exposure and gain of the frame we're looking at. CamHelper -// provides functions for converting analogue gains to and from the sensor's -// native gain codes. -// -// Finally, a set of functions that determine how to handle the vagaries of -// different camera modules on start-up or when switching modes. Some -// modules may produce one or more frames that are not yet correctly exposed, -// or where the metadata may be suspect. We have the following functions: -// HideFramesStartup(): Tell the pipeline handler not to return this many -// frames at start-up. This can also be used to hide initial frames -// while the AGC and other algorithms are sorting themselves out. -// HideFramesModeSwitch(): Tell the pipeline handler not to return this -// many frames after a mode switch (other than start-up). Some sensors -// may produce innvalid frames after a mode switch; others may not. -// MistrustFramesStartup(): At start-up a sensor may return frames for -// which we should not run any control algorithms (for example, metadata -// may be invalid). -// MistrustFramesModeSwitch(): The number of frames, after a mode switch -// (other than start-up), for which control algorithms should not run -// (for example, metadata may be unreliable). - -class CamHelper -{ -public: - static CamHelper *Create(std::string const &cam_name); - CamHelper(std::unique_ptr<MdParser> parser, unsigned int frameIntegrationDiff); - virtual ~CamHelper(); - void SetCameraMode(const CameraMode &mode); - virtual void Prepare(libcamera::Span<const uint8_t> buffer, - Metadata &metadata); - virtual void Process(StatisticsPtr &stats, Metadata &metadata); - virtual uint32_t ExposureLines(libcamera::utils::Duration exposure) const; - virtual libcamera::utils::Duration Exposure(uint32_t exposure_lines) const; - virtual uint32_t GetVBlanking(libcamera::utils::Duration &exposure, - libcamera::utils::Duration minFrameDuration, - libcamera::utils::Duration maxFrameDuration) const; - virtual uint32_t GainCode(double gain) const = 0; - virtual double Gain(uint32_t gain_code) const = 0; - virtual void GetDelays(int &exposure_delay, int &gain_delay, - int &vblank_delay) const; - virtual bool SensorEmbeddedDataPresent() const; - virtual double GetModeSensitivity(const CameraMode &mode) const; - virtual unsigned int HideFramesStartup() const; - virtual unsigned int HideFramesModeSwitch() const; - virtual unsigned int MistrustFramesStartup() const; - virtual unsigned int MistrustFramesModeSwitch() const; - -protected: - void parseEmbeddedData(libcamera::Span<const uint8_t> buffer, - Metadata &metadata); - virtual void PopulateMetadata(const MdParser::RegisterMap ®isters, - Metadata &metadata) const; - - std::unique_ptr<MdParser> parser_; - CameraMode mode_; - -private: - bool initialized_; - /* - * Smallest difference between the frame length and integration time, - * in units of lines. - */ - unsigned int frameIntegrationDiff_; -}; - -// This is for registering camera helpers with the system, so that the -// CamHelper::Create function picks them up automatically. - -typedef CamHelper *(*CamHelperCreateFunc)(); -struct RegisterCamHelper -{ - RegisterCamHelper(char const *cam_name, - CamHelperCreateFunc create_func); -}; - -} // namespace RPi diff --git a/src/ipa/raspberrypi/cam_helper_imx219.cpp b/src/ipa/raspberrypi/cam_helper_imx219.cpp deleted file mode 100644 index a3caab71..00000000 --- a/src/ipa/raspberrypi/cam_helper_imx219.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * cam_helper_imx219.cpp - camera helper for imx219 sensor - */ - -#include <assert.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> - -/* - * We have observed that the imx219 embedded data stream randomly returns junk - * register values. Do not rely on embedded data until this has been resolved. - */ -#define ENABLE_EMBEDDED_DATA 0 - -#include "cam_helper.hpp" -#if ENABLE_EMBEDDED_DATA -#include "md_parser.hpp" -#endif - -using namespace RPiController; - -/* - * We care about one gain register and a pair of exposure registers. Their I2C - * addresses from the Sony IMX219 datasheet: - */ -constexpr uint32_t gainReg = 0x157; -constexpr uint32_t expHiReg = 0x15a; -constexpr uint32_t expLoReg = 0x15b; -constexpr uint32_t frameLengthHiReg = 0x160; -constexpr uint32_t frameLengthLoReg = 0x161; -constexpr std::initializer_list<uint32_t> registerList [[maybe_unused]] - = { expHiReg, expLoReg, gainReg, frameLengthHiReg, frameLengthLoReg }; - -class CamHelperImx219 : public CamHelper -{ -public: - CamHelperImx219(); - uint32_t GainCode(double gain) const override; - double Gain(uint32_t gain_code) const override; - unsigned int MistrustFramesModeSwitch() const override; - bool SensorEmbeddedDataPresent() const override; - -private: - /* - * Smallest difference between the frame length and integration time, - * in units of lines. - */ - static constexpr int frameIntegrationDiff = 4; - - void PopulateMetadata(const MdParser::RegisterMap ®isters, - Metadata &metadata) const override; -}; - -CamHelperImx219::CamHelperImx219() -#if ENABLE_EMBEDDED_DATA - : CamHelper(std::make_unique<MdParserSmia>(registerList), frameIntegrationDiff) -#else - : CamHelper({}, frameIntegrationDiff) -#endif -{ -} - -uint32_t CamHelperImx219::GainCode(double gain) const -{ - return (uint32_t)(256 - 256 / gain); -} - -double CamHelperImx219::Gain(uint32_t gain_code) const -{ - return 256.0 / (256 - gain_code); -} - -unsigned int CamHelperImx219::MistrustFramesModeSwitch() const -{ - /* - * For reasons unknown, we do occasionally get a bogus metadata frame - * at a mode switch (though not at start-up). Possibly warrants some - * investigation, though not a big deal. - */ - return 1; -} - -bool CamHelperImx219::SensorEmbeddedDataPresent() const -{ - return ENABLE_EMBEDDED_DATA; -} - -void CamHelperImx219::PopulateMetadata(const MdParser::RegisterMap ®isters, - Metadata &metadata) const -{ - DeviceStatus deviceStatus; - - deviceStatus.shutter_speed = Exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg)); - deviceStatus.analogue_gain = Gain(registers.at(gainReg)); - deviceStatus.frame_length = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg); - - metadata.Set("device.status", deviceStatus); -} - -static CamHelper *Create() -{ - return new CamHelperImx219(); -} - -static RegisterCamHelper reg("imx219", &Create); diff --git a/src/ipa/raspberrypi/cam_helper_imx290.cpp b/src/ipa/raspberrypi/cam_helper_imx290.cpp deleted file mode 100644 index 871c1f8e..00000000 --- a/src/ipa/raspberrypi/cam_helper_imx290.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2021, Raspberry Pi (Trading) Limited - * - * cam_helper_imx290.cpp - camera helper for imx290 sensor - */ - -#include <math.h> - -#include "cam_helper.hpp" - -using namespace RPiController; - -class CamHelperImx290 : public CamHelper -{ -public: - CamHelperImx290(); - uint32_t GainCode(double gain) const override; - double Gain(uint32_t gain_code) const override; - void GetDelays(int &exposure_delay, int &gain_delay, - int &vblank_delay) const override; - unsigned int HideFramesModeSwitch() const override; - -private: - /* - * Smallest difference between the frame length and integration time, - * in units of lines. - */ - static constexpr int frameIntegrationDiff = 2; -}; - -CamHelperImx290::CamHelperImx290() - : CamHelper({}, frameIntegrationDiff) -{ -} - -uint32_t CamHelperImx290::GainCode(double gain) const -{ - int code = 66.6667 * log10(gain); - return std::max(0, std::min(code, 0xf0)); -} - -double CamHelperImx290::Gain(uint32_t gain_code) const -{ - return pow(10, 0.015 * gain_code); -} - -void CamHelperImx290::GetDelays(int &exposure_delay, int &gain_delay, - int &vblank_delay) const -{ - exposure_delay = 2; - gain_delay = 2; - vblank_delay = 2; -} - -unsigned int CamHelperImx290::HideFramesModeSwitch() const -{ - /* After a mode switch, we seem to get 1 bad frame. */ - return 1; -} - -static CamHelper *Create() -{ - return new CamHelperImx290(); -} - -static RegisterCamHelper reg("imx290", &Create); diff --git a/src/ipa/raspberrypi/cam_helper_imx296.cpp b/src/ipa/raspberrypi/cam_helper_imx296.cpp deleted file mode 100644 index a1a771cb..00000000 --- a/src/ipa/raspberrypi/cam_helper_imx296.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2020, Raspberry Pi (Trading) Limited - * - * cam_helper_imx296.cpp - Camera helper for IMX296 sensor - */ - -#include <algorithm> -#include <cmath> -#include <stddef.h> - -#include "cam_helper.hpp" - -using namespace RPiController; -using libcamera::utils::Duration; -using namespace std::literals::chrono_literals; - -class CamHelperImx296 : public CamHelper -{ -public: - CamHelperImx296(); - uint32_t GainCode(double gain) const override; - double Gain(uint32_t gain_code) const override; - uint32_t ExposureLines(Duration exposure) const override; - Duration Exposure(uint32_t exposure_lines) const override; - -private: - static constexpr uint32_t maxGainCode = 239; - static constexpr Duration timePerLine = 550.0 / 37.125e6 * 1.0s; - - /* - * Smallest difference between the frame length and integration time, - * in units of lines. - */ - static constexpr int frameIntegrationDiff = 4; -}; - -CamHelperImx296::CamHelperImx296() - : CamHelper(nullptr, frameIntegrationDiff) -{ -} - -uint32_t CamHelperImx296::GainCode(double gain) const -{ - uint32_t code = 20 * std::log10(gain) * 10; - return std::min(code, maxGainCode); -} - -double CamHelperImx296::Gain(uint32_t gain_code) const -{ - return std::pow(10.0, gain_code / 200.0); -} - -uint32_t CamHelperImx296::ExposureLines(Duration exposure) const -{ - return (exposure - 14.26us) / timePerLine; -} - -Duration CamHelperImx296::Exposure(uint32_t exposure_lines) const -{ - return exposure_lines * timePerLine + 14.26us; -} - -static CamHelper *Create() -{ - return new CamHelperImx296(); -} - -static RegisterCamHelper reg("imx296", &Create); diff --git a/src/ipa/raspberrypi/cam_helper_imx477.cpp b/src/ipa/raspberrypi/cam_helper_imx477.cpp deleted file mode 100644 index 0e1c0dbd..00000000 --- a/src/ipa/raspberrypi/cam_helper_imx477.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2020, Raspberry Pi (Trading) Limited - * - * cam_helper_imx477.cpp - camera helper for imx477 sensor - */ - -#include <algorithm> -#include <assert.h> -#include <cmath> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> - -#include <libcamera/base/log.h> - -#include "cam_helper.hpp" -#include "md_parser.hpp" - -using namespace RPiController; -using namespace libcamera; -using libcamera::utils::Duration; - -namespace libcamera { -LOG_DECLARE_CATEGORY(IPARPI) -} - -/* - * We care about two gain registers and a pair of exposure registers. Their - * I2C addresses from the Sony IMX477 datasheet: - */ -constexpr uint32_t expHiReg = 0x0202; -constexpr uint32_t expLoReg = 0x0203; -constexpr uint32_t gainHiReg = 0x0204; -constexpr uint32_t gainLoReg = 0x0205; -constexpr uint32_t frameLengthHiReg = 0x0340; -constexpr uint32_t frameLengthLoReg = 0x0341; -constexpr uint32_t temperatureReg = 0x013a; -constexpr std::initializer_list<uint32_t> registerList = - { expHiReg, expLoReg, gainHiReg, gainLoReg, frameLengthHiReg, frameLengthLoReg, temperatureReg }; - -class CamHelperImx477 : public CamHelper -{ -public: - CamHelperImx477(); - uint32_t GainCode(double gain) const override; - double Gain(uint32_t gain_code) const override; - void Prepare(libcamera::Span<const uint8_t> buffer, Metadata &metadata) override; - uint32_t GetVBlanking(Duration &exposure, Duration minFrameDuration, - Duration maxFrameDuration) const override; - void GetDelays(int &exposure_delay, int &gain_delay, - int &vblank_delay) const override; - bool SensorEmbeddedDataPresent() const override; - -private: - /* - * Smallest difference between the frame length and integration time, - * in units of lines. - */ - static constexpr int frameIntegrationDiff = 22; - /* Maximum frame length allowable for long exposure calculations. */ - static constexpr int frameLengthMax = 0xffdc; - /* Largest long exposure scale factor given as a left shift on the frame length. */ - static constexpr int longExposureShiftMax = 7; - - void PopulateMetadata(const MdParser::RegisterMap ®isters, - Metadata &metadata) const override; -}; - -CamHelperImx477::CamHelperImx477() - : CamHelper(std::make_unique<MdParserSmia>(registerList), frameIntegrationDiff) -{ -} - -uint32_t CamHelperImx477::GainCode(double gain) const -{ - return static_cast<uint32_t>(1024 - 1024 / gain); -} - -double CamHelperImx477::Gain(uint32_t gain_code) const -{ - return 1024.0 / (1024 - gain_code); -} - -void CamHelperImx477::Prepare(libcamera::Span<const uint8_t> buffer, Metadata &metadata) -{ - MdParser::RegisterMap registers; - DeviceStatus deviceStatus; - - if (metadata.Get("device.status", deviceStatus)) { - LOG(IPARPI, Error) << "DeviceStatus not found from DelayedControls"; - return; - } - - parseEmbeddedData(buffer, metadata); - - /* - * The DeviceStatus struct is first populated with values obtained from - * DelayedControls. If this reports frame length is > frameLengthMax, - * it means we are using a long exposure mode. Since the long exposure - * scale factor is not returned back through embedded data, we must rely - * on the existing exposure lines and frame length values returned by - * DelayedControls. - * - * Otherwise, all values are updated with what is reported in the - * embedded data. - */ - if (deviceStatus.frame_length > frameLengthMax) { - DeviceStatus parsedDeviceStatus; - - metadata.Get("device.status", parsedDeviceStatus); - parsedDeviceStatus.shutter_speed = deviceStatus.shutter_speed; - parsedDeviceStatus.frame_length = deviceStatus.frame_length; - metadata.Set("device.status", parsedDeviceStatus); - - LOG(IPARPI, Debug) << "Metadata updated for long exposure: " - << parsedDeviceStatus; - } -} - -uint32_t CamHelperImx477::GetVBlanking(Duration &exposure, - Duration minFrameDuration, - Duration maxFrameDuration) const -{ - uint32_t frameLength, exposureLines; - unsigned int shift = 0; - - frameLength = mode_.height + CamHelper::GetVBlanking(exposure, minFrameDuration, - maxFrameDuration); - /* - * Check if the frame length calculated needs to be setup for long - * exposure mode. This will require us to use a long exposure scale - * factor provided by a shift operation in the sensor. - */ - while (frameLength > frameLengthMax) { - if (++shift > longExposureShiftMax) { - shift = longExposureShiftMax; - frameLength = frameLengthMax; - break; - } - frameLength >>= 1; - } - - if (shift) { - /* Account for any rounding in the scaled frame length value. */ - frameLength <<= shift; - exposureLines = ExposureLines(exposure); - exposureLines = std::min(exposureLines, frameLength - frameIntegrationDiff); - exposure = Exposure(exposureLines); - } - - return frameLength - mode_.height; -} - -void CamHelperImx477::GetDelays(int &exposure_delay, int &gain_delay, - int &vblank_delay) const -{ - exposure_delay = 2; - gain_delay = 2; - vblank_delay = 3; -} - -bool CamHelperImx477::SensorEmbeddedDataPresent() const -{ - return true; -} - -void CamHelperImx477::PopulateMetadata(const MdParser::RegisterMap ®isters, - Metadata &metadata) const -{ - DeviceStatus deviceStatus; - - deviceStatus.shutter_speed = Exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg)); - deviceStatus.analogue_gain = Gain(registers.at(gainHiReg) * 256 + registers.at(gainLoReg)); - deviceStatus.frame_length = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg); - deviceStatus.sensor_temperature = std::clamp<int8_t>(registers.at(temperatureReg), -20, 80); - - metadata.Set("device.status", deviceStatus); -} - -static CamHelper *Create() -{ - return new CamHelperImx477(); -} - -static RegisterCamHelper reg("imx477", &Create); diff --git a/src/ipa/raspberrypi/cam_helper_imx519.cpp b/src/ipa/raspberrypi/cam_helper_imx519.cpp deleted file mode 100644 index eaf24982..00000000 --- a/src/ipa/raspberrypi/cam_helper_imx519.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Based on cam_helper_imx477.cpp - * Copyright (C) 2020, Raspberry Pi (Trading) Limited - * - * cam_helper_imx519.cpp - camera helper for imx519 sensor - * Copyright (C) 2021, Arducam Technology co., Ltd. - */ - -#include <assert.h> -#include <cmath> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> - -#include <libcamera/base/log.h> - -#include "cam_helper.hpp" -#include "md_parser.hpp" - -using namespace RPiController; -using namespace libcamera; -using libcamera::utils::Duration; - -namespace libcamera { -LOG_DECLARE_CATEGORY(IPARPI) -} - -/* - * We care about two gain registers and a pair of exposure registers. Their - * I2C addresses from the Sony IMX519 datasheet: - */ -constexpr uint32_t expHiReg = 0x0202; -constexpr uint32_t expLoReg = 0x0203; -constexpr uint32_t gainHiReg = 0x0204; -constexpr uint32_t gainLoReg = 0x0205; -constexpr uint32_t frameLengthHiReg = 0x0340; -constexpr uint32_t frameLengthLoReg = 0x0341; -constexpr std::initializer_list<uint32_t> registerList = - { expHiReg, expLoReg, gainHiReg, gainLoReg, frameLengthHiReg, frameLengthLoReg }; - -class CamHelperImx519 : public CamHelper -{ -public: - CamHelperImx519(); - uint32_t GainCode(double gain) const override; - double Gain(uint32_t gain_code) const override; - void Prepare(libcamera::Span<const uint8_t> buffer, Metadata &metadata) override; - uint32_t GetVBlanking(Duration &exposure, Duration minFrameDuration, - Duration maxFrameDuration) const override; - void GetDelays(int &exposure_delay, int &gain_delay, - int &vblank_delay) const override; - bool SensorEmbeddedDataPresent() const override; - -private: - /* - * Smallest difference between the frame length and integration time, - * in units of lines. - */ - static constexpr int frameIntegrationDiff = 32; - /* Maximum frame length allowable for long exposure calculations. */ - static constexpr int frameLengthMax = 0xffdc; - /* Largest long exposure scale factor given as a left shift on the frame length. */ - static constexpr int longExposureShiftMax = 7; - - void PopulateMetadata(const MdParser::RegisterMap ®isters, - Metadata &metadata) const override; -}; - -CamHelperImx519::CamHelperImx519() - : CamHelper(std::make_unique<MdParserSmia>(registerList), frameIntegrationDiff) -{ -} - -uint32_t CamHelperImx519::GainCode(double gain) const -{ - return static_cast<uint32_t>(1024 - 1024 / gain); -} - -double CamHelperImx519::Gain(uint32_t gain_code) const -{ - return 1024.0 / (1024 - gain_code); -} - -void CamHelperImx519::Prepare(libcamera::Span<const uint8_t> buffer, Metadata &metadata) -{ - MdParser::RegisterMap registers; - DeviceStatus deviceStatus; - - if (metadata.Get("device.status", deviceStatus)) { - LOG(IPARPI, Error) << "DeviceStatus not found from DelayedControls"; - return; - } - - parseEmbeddedData(buffer, metadata); - - /* - * The DeviceStatus struct is first populated with values obtained from - * DelayedControls. If this reports frame length is > frameLengthMax, - * it means we are using a long exposure mode. Since the long exposure - * scale factor is not returned back through embedded data, we must rely - * on the existing exposure lines and frame length values returned by - * DelayedControls. - * - * Otherwise, all values are updated with what is reported in the - * embedded data. - */ - if (deviceStatus.frame_length > frameLengthMax) { - DeviceStatus parsedDeviceStatus; - - metadata.Get("device.status", parsedDeviceStatus); - parsedDeviceStatus.shutter_speed = deviceStatus.shutter_speed; - parsedDeviceStatus.frame_length = deviceStatus.frame_length; - metadata.Set("device.status", parsedDeviceStatus); - - LOG(IPARPI, Debug) << "Metadata updated for long exposure: " - << parsedDeviceStatus; - } -} - -uint32_t CamHelperImx519::GetVBlanking(Duration &exposure, - Duration minFrameDuration, - Duration maxFrameDuration) const -{ - uint32_t frameLength, exposureLines; - unsigned int shift = 0; - - frameLength = mode_.height + CamHelper::GetVBlanking(exposure, minFrameDuration, - maxFrameDuration); - /* - * Check if the frame length calculated needs to be setup for long - * exposure mode. This will require us to use a long exposure scale - * factor provided by a shift operation in the sensor. - */ - while (frameLength > frameLengthMax) { - if (++shift > longExposureShiftMax) { - shift = longExposureShiftMax; - frameLength = frameLengthMax; - break; - } - frameLength >>= 1; - } - - if (shift) { - /* Account for any rounding in the scaled frame length value. */ - frameLength <<= shift; - exposureLines = ExposureLines(exposure); - exposureLines = std::min(exposureLines, frameLength - frameIntegrationDiff); - exposure = Exposure(exposureLines); - } - - return frameLength - mode_.height; -} - -void CamHelperImx519::GetDelays(int &exposure_delay, int &gain_delay, - int &vblank_delay) const -{ - exposure_delay = 2; - gain_delay = 2; - vblank_delay = 3; -} - -bool CamHelperImx519::SensorEmbeddedDataPresent() const -{ - return true; -} - -void CamHelperImx519::PopulateMetadata(const MdParser::RegisterMap ®isters, - Metadata &metadata) const -{ - DeviceStatus deviceStatus; - - deviceStatus.shutter_speed = Exposure(registers.at(expHiReg) * 256 + registers.at(expLoReg)); - deviceStatus.analogue_gain = Gain(registers.at(gainHiReg) * 256 + registers.at(gainLoReg)); - deviceStatus.frame_length = registers.at(frameLengthHiReg) * 256 + registers.at(frameLengthLoReg); - - metadata.Set("device.status", deviceStatus); -} - -static CamHelper *Create() -{ - return new CamHelperImx519(); -} - -static RegisterCamHelper reg("imx519", &Create); diff --git a/src/ipa/raspberrypi/cam_helper_ov5647.cpp b/src/ipa/raspberrypi/cam_helper_ov5647.cpp deleted file mode 100644 index 702c2d07..00000000 --- a/src/ipa/raspberrypi/cam_helper_ov5647.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * cam_helper_ov5647.cpp - camera information for ov5647 sensor - */ - -#include <assert.h> - -#include "cam_helper.hpp" - -using namespace RPiController; - -class CamHelperOv5647 : public CamHelper -{ -public: - CamHelperOv5647(); - uint32_t GainCode(double gain) const override; - double Gain(uint32_t gain_code) const override; - void GetDelays(int &exposure_delay, int &gain_delay, - int &vblank_delay) const override; - unsigned int HideFramesStartup() const override; - unsigned int HideFramesModeSwitch() const override; - unsigned int MistrustFramesStartup() const override; - unsigned int MistrustFramesModeSwitch() const override; - -private: - /* - * Smallest difference between the frame length and integration time, - * in units of lines. - */ - static constexpr int frameIntegrationDiff = 4; -}; - -/* - * OV5647 doesn't output metadata, so we have to use the "unicam parser" which - * works by counting frames. - */ - -CamHelperOv5647::CamHelperOv5647() - : CamHelper({}, frameIntegrationDiff) -{ -} - -uint32_t CamHelperOv5647::GainCode(double gain) const -{ - return static_cast<uint32_t>(gain * 16.0); -} - -double CamHelperOv5647::Gain(uint32_t gain_code) const -{ - return static_cast<double>(gain_code) / 16.0; -} - -void CamHelperOv5647::GetDelays(int &exposure_delay, int &gain_delay, - int &vblank_delay) const -{ - /* - * We run this sensor in a mode where the gain delay is bumped up to - * 2. It seems to be the only way to make the delays "predictable". - */ - exposure_delay = 2; - gain_delay = 2; - vblank_delay = 2; -} - -unsigned int CamHelperOv5647::HideFramesStartup() const -{ - /* - * On startup, we get a couple of under-exposed frames which - * we don't want shown. - */ - return 2; -} - -unsigned int CamHelperOv5647::HideFramesModeSwitch() const -{ - /* - * After a mode switch, we get a couple of under-exposed frames which - * we don't want shown. - */ - return 2; -} - -unsigned int CamHelperOv5647::MistrustFramesStartup() const -{ - /* - * First couple of frames are under-exposed and are no good for control - * algos. - */ - return 2; -} - -unsigned int CamHelperOv5647::MistrustFramesModeSwitch() const -{ - /* - * First couple of frames are under-exposed even after a simple - * mode switch, and are no good for control algos. - */ - return 2; -} - -static CamHelper *Create() -{ - return new CamHelperOv5647(); -} - -static RegisterCamHelper reg("ov5647", &Create); diff --git a/src/ipa/raspberrypi/cam_helper_ov9281.cpp b/src/ipa/raspberrypi/cam_helper_ov9281.cpp deleted file mode 100644 index 9de868c3..00000000 --- a/src/ipa/raspberrypi/cam_helper_ov9281.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2021, Raspberry Pi (Trading) Limited - * - * cam_helper_ov9281.cpp - camera information for ov9281 sensor - */ - -#include <assert.h> - -#include "cam_helper.hpp" - -using namespace RPiController; - -class CamHelperOv9281 : public CamHelper -{ -public: - CamHelperOv9281(); - uint32_t GainCode(double gain) const override; - double Gain(uint32_t gain_code) const override; - void GetDelays(int &exposure_delay, int &gain_delay, - int &vblank_delay) const override; - -private: - /* - * Smallest difference between the frame length and integration time, - * in units of lines. - */ - static constexpr int frameIntegrationDiff = 4; -}; - -/* - * OV9281 doesn't output metadata, so we have to use the "unicam parser" which - * works by counting frames. - */ - -CamHelperOv9281::CamHelperOv9281() - : CamHelper({}, frameIntegrationDiff) -{ -} - -uint32_t CamHelperOv9281::GainCode(double gain) const -{ - return static_cast<uint32_t>(gain * 16.0); -} - -double CamHelperOv9281::Gain(uint32_t gain_code) const -{ - return static_cast<double>(gain_code) / 16.0; -} - -void CamHelperOv9281::GetDelays(int &exposure_delay, int &gain_delay, - int &vblank_delay) const -{ - /* The driver appears to behave as follows: */ - exposure_delay = 2; - gain_delay = 2; - vblank_delay = 2; -} - -static CamHelper *Create() -{ - return new CamHelperOv9281(); -} - -static RegisterCamHelper reg("ov9281", &Create); diff --git a/src/ipa/raspberrypi/controller/agc_algorithm.hpp b/src/ipa/raspberrypi/controller/agc_algorithm.hpp deleted file mode 100644 index 61595ea2..00000000 --- a/src/ipa/raspberrypi/controller/agc_algorithm.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * agc_algorithm.hpp - AGC/AEC control algorithm interface - */ -#pragma once - -#include <libcamera/base/utils.h> - -#include "algorithm.hpp" - -namespace RPiController { - -class AgcAlgorithm : public Algorithm -{ -public: - AgcAlgorithm(Controller *controller) : Algorithm(controller) {} - // An AGC algorithm must provide the following: - virtual unsigned int GetConvergenceFrames() const = 0; - virtual void SetEv(double ev) = 0; - virtual void SetFlickerPeriod(libcamera::utils::Duration flicker_period) = 0; - virtual void SetFixedShutter(libcamera::utils::Duration fixed_shutter) = 0; - virtual void SetMaxShutter(libcamera::utils::Duration max_shutter) = 0; - virtual void SetFixedAnalogueGain(double fixed_analogue_gain) = 0; - virtual void SetMeteringMode(std::string const &metering_mode_name) = 0; - virtual void SetExposureMode(std::string const &exposure_mode_name) = 0; - virtual void - SetConstraintMode(std::string const &contraint_mode_name) = 0; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/agc_status.h b/src/ipa/raspberrypi/controller/agc_status.h deleted file mode 100644 index 20cb1b62..00000000 --- a/src/ipa/raspberrypi/controller/agc_status.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * agc_status.h - AGC/AEC control algorithm status - */ -#pragma once - -#include <libcamera/base/utils.h> - -// The AGC algorithm should post the following structure into the image's -// "agc.status" metadata. - -#ifdef __cplusplus -extern "C" { -#endif - -// Note: total_exposure_value will be reported as zero until the algorithm has -// seen statistics and calculated meaningful values. The contents should be -// ignored until then. - -struct AgcStatus { - libcamera::utils::Duration total_exposure_value; // value for all exposure and gain for this image - libcamera::utils::Duration target_exposure_value; // (unfiltered) target total exposure AGC is aiming for - libcamera::utils::Duration shutter_time; - double analogue_gain; - char exposure_mode[32]; - char constraint_mode[32]; - char metering_mode[32]; - double ev; - libcamera::utils::Duration flicker_period; - int floating_region_enable; - libcamera::utils::Duration fixed_shutter; - double fixed_analogue_gain; - double digital_gain; - int locked; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/ipa/raspberrypi/controller/algorithm.cpp b/src/ipa/raspberrypi/controller/algorithm.cpp deleted file mode 100644 index 43ad0a2b..00000000 --- a/src/ipa/raspberrypi/controller/algorithm.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * algorithm.cpp - ISP control algorithms - */ - -#include "algorithm.hpp" - -using namespace RPiController; - -void Algorithm::Read([[maybe_unused]] boost::property_tree::ptree const ¶ms) -{ -} - -void Algorithm::Initialise() {} - -void Algorithm::SwitchMode([[maybe_unused]] CameraMode const &camera_mode, - [[maybe_unused]] Metadata *metadata) -{ -} - -void Algorithm::Prepare([[maybe_unused]] Metadata *image_metadata) -{ -} - -void Algorithm::Process([[maybe_unused]] StatisticsPtr &stats, - [[maybe_unused]] Metadata *image_metadata) -{ -} - -// For registering algorithms with the system: - -static std::map<std::string, AlgoCreateFunc> algorithms; -std::map<std::string, AlgoCreateFunc> const &RPiController::GetAlgorithms() -{ - return algorithms; -} - -RegisterAlgorithm::RegisterAlgorithm(char const *name, - AlgoCreateFunc create_func) -{ - algorithms[std::string(name)] = create_func; -} diff --git a/src/ipa/raspberrypi/controller/algorithm.hpp b/src/ipa/raspberrypi/controller/algorithm.hpp deleted file mode 100644 index 5123c87b..00000000 --- a/src/ipa/raspberrypi/controller/algorithm.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * algorithm.hpp - ISP control algorithm interface - */ -#pragma once - -// All algorithms should be derived from this class and made available to the -// Controller. - -#include <string> -#include <memory> -#include <map> - -#include "controller.hpp" - -#include <boost/property_tree/ptree.hpp> - -namespace RPiController { - -// This defines the basic interface for all control algorithms. - -class Algorithm -{ -public: - Algorithm(Controller *controller) - : controller_(controller), paused_(false) - { - } - virtual ~Algorithm() = default; - virtual char const *Name() const = 0; - virtual bool IsPaused() const { return paused_; } - virtual void Pause() { paused_ = true; } - virtual void Resume() { paused_ = false; } - virtual void Read(boost::property_tree::ptree const ¶ms); - virtual void Initialise(); - virtual void SwitchMode(CameraMode const &camera_mode, Metadata *metadata); - virtual void Prepare(Metadata *image_metadata); - virtual void Process(StatisticsPtr &stats, Metadata *image_metadata); - Metadata &GetGlobalMetadata() const - { - return controller_->GetGlobalMetadata(); - } - -private: - Controller *controller_; - bool paused_; -}; - -// This code is for automatic registration of Front End algorithms with the -// system. - -typedef Algorithm *(*AlgoCreateFunc)(Controller *controller); -struct RegisterAlgorithm { - RegisterAlgorithm(char const *name, AlgoCreateFunc create_func); -}; -std::map<std::string, AlgoCreateFunc> const &GetAlgorithms(); - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/alsc_status.h b/src/ipa/raspberrypi/controller/alsc_status.h deleted file mode 100644 index d3f57971..00000000 --- a/src/ipa/raspberrypi/controller/alsc_status.h +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * alsc_status.h - ALSC (auto lens shading correction) control algorithm status - */ -#pragma once - -// The ALSC algorithm should post the following structure into the image's -// "alsc.status" metadata. - -#ifdef __cplusplus -extern "C" { -#endif - -#define ALSC_CELLS_X 16 -#define ALSC_CELLS_Y 12 - -struct AlscStatus { - double r[ALSC_CELLS_Y][ALSC_CELLS_X]; - double g[ALSC_CELLS_Y][ALSC_CELLS_X]; - double b[ALSC_CELLS_Y][ALSC_CELLS_X]; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/ipa/raspberrypi/controller/awb_algorithm.hpp b/src/ipa/raspberrypi/controller/awb_algorithm.hpp deleted file mode 100644 index 96f88afc..00000000 --- a/src/ipa/raspberrypi/controller/awb_algorithm.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * awb_algorithm.hpp - AWB control algorithm interface - */ -#pragma once - -#include "algorithm.hpp" - -namespace RPiController { - -class AwbAlgorithm : public Algorithm -{ -public: - AwbAlgorithm(Controller *controller) : Algorithm(controller) {} - // An AWB algorithm must provide the following: - virtual unsigned int GetConvergenceFrames() const = 0; - virtual void SetMode(std::string const &mode_name) = 0; - virtual void SetManualGains(double manual_r, double manual_b) = 0; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/awb_status.h b/src/ipa/raspberrypi/controller/awb_status.h deleted file mode 100644 index 46d7c842..00000000 --- a/src/ipa/raspberrypi/controller/awb_status.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * awb_status.h - AWB control algorithm status - */ -#pragma once - -// The AWB algorithm places its results into both the image and global metadata, -// under the tag "awb.status". - -#ifdef __cplusplus -extern "C" { -#endif - -struct AwbStatus { - char mode[32]; - double temperature_K; - double gain_r; - double gain_g; - double gain_b; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/ipa/raspberrypi/controller/black_level_status.h b/src/ipa/raspberrypi/controller/black_level_status.h deleted file mode 100644 index d085f64b..00000000 --- a/src/ipa/raspberrypi/controller/black_level_status.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * black_level_status.h - black level control algorithm status - */ -#pragma once - -// The "black level" algorithm stores the black levels to use. - -#ifdef __cplusplus -extern "C" { -#endif - -struct BlackLevelStatus { - uint16_t black_level_r; // out of 16 bits - uint16_t black_level_g; - uint16_t black_level_b; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/ipa/raspberrypi/controller/camera_mode.h b/src/ipa/raspberrypi/controller/camera_mode.h deleted file mode 100644 index e2b82828..00000000 --- a/src/ipa/raspberrypi/controller/camera_mode.h +++ /dev/null @@ -1,50 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019-2020, Raspberry Pi (Trading) Limited - * - * camera_mode.h - description of a particular operating mode of a sensor - */ -#pragma once - -#include <libcamera/transform.h> - -#include <libcamera/base/utils.h> - -// Description of a "camera mode", holding enough information for control -// algorithms to adapt their behaviour to the different modes of the camera, -// including binning, scaling, cropping etc. - -#ifdef __cplusplus -extern "C" { -#endif - -#define CAMERA_MODE_NAME_LEN 32 - -struct CameraMode { - // bit depth of the raw camera output - uint32_t bitdepth; - // size in pixels of frames in this mode - uint16_t width, height; - // size of full resolution uncropped frame ("sensor frame") - uint16_t sensor_width, sensor_height; - // binning factor (1 = no binning, 2 = 2-pixel binning etc.) - uint8_t bin_x, bin_y; - // location of top left pixel in the sensor frame - uint16_t crop_x, crop_y; - // scaling factor (so if uncropped, width*scale_x is sensor_width) - double scale_x, scale_y; - // scaling of the noise compared to the native sensor mode - double noise_factor; - // line time - libcamera::utils::Duration line_length; - // any camera transform *not* reflected already in the camera tuning - libcamera::Transform transform; - // minimum and maximum fame lengths in units of lines - uint32_t min_frame_length, max_frame_length; - // sensitivity of this mode - double sensitivity; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/ipa/raspberrypi/controller/ccm_algorithm.hpp b/src/ipa/raspberrypi/controller/ccm_algorithm.hpp deleted file mode 100644 index 33d0e30d..00000000 --- a/src/ipa/raspberrypi/controller/ccm_algorithm.hpp +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * ccm_algorithm.hpp - CCM (colour correction matrix) control algorithm interface - */ -#pragma once - -#include "algorithm.hpp" - -namespace RPiController { - -class CcmAlgorithm : public Algorithm -{ -public: - CcmAlgorithm(Controller *controller) : Algorithm(controller) {} - // A CCM algorithm must provide the following: - virtual void SetSaturation(double saturation) = 0; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/ccm_status.h b/src/ipa/raspberrypi/controller/ccm_status.h deleted file mode 100644 index 7e41dd1f..00000000 --- a/src/ipa/raspberrypi/controller/ccm_status.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * ccm_status.h - CCM (colour correction matrix) control algorithm status - */ -#pragma once - -// The "ccm" algorithm generates an appropriate colour matrix. - -#ifdef __cplusplus -extern "C" { -#endif - -struct CcmStatus { - double matrix[9]; - double saturation; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/ipa/raspberrypi/controller/contrast_algorithm.hpp b/src/ipa/raspberrypi/controller/contrast_algorithm.hpp deleted file mode 100644 index 7f03bba5..00000000 --- a/src/ipa/raspberrypi/controller/contrast_algorithm.hpp +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * contrast_algorithm.hpp - contrast (gamma) control algorithm interface - */ -#pragma once - -#include "algorithm.hpp" - -namespace RPiController { - -class ContrastAlgorithm : public Algorithm -{ -public: - ContrastAlgorithm(Controller *controller) : Algorithm(controller) {} - // A contrast algorithm must provide the following: - virtual void SetBrightness(double brightness) = 0; - virtual void SetContrast(double contrast) = 0; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/contrast_status.h b/src/ipa/raspberrypi/controller/contrast_status.h deleted file mode 100644 index d7edd4e9..00000000 --- a/src/ipa/raspberrypi/controller/contrast_status.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * contrast_status.h - contrast (gamma) control algorithm status - */ -#pragma once - -// The "contrast" algorithm creates a gamma curve, optionally doing a little bit -// of contrast stretching based on the AGC histogram. - -#ifdef __cplusplus -extern "C" { -#endif - -#define CONTRAST_NUM_POINTS 33 - -struct ContrastPoint { - uint16_t x; - uint16_t y; -}; - -struct ContrastStatus { - struct ContrastPoint points[CONTRAST_NUM_POINTS]; - double brightness; - double contrast; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/ipa/raspberrypi/controller/controller.cpp b/src/ipa/raspberrypi/controller/controller.cpp deleted file mode 100644 index d3433ad2..00000000 --- a/src/ipa/raspberrypi/controller/controller.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * controller.cpp - ISP controller - */ - -#include <libcamera/base/log.h> - -#include "algorithm.hpp" -#include "controller.hpp" - -#include <boost/property_tree/json_parser.hpp> -#include <boost/property_tree/ptree.hpp> - -using namespace RPiController; -using namespace libcamera; - -LOG_DEFINE_CATEGORY(RPiController) - -Controller::Controller() - : switch_mode_called_(false) {} - -Controller::Controller(char const *json_filename) - : switch_mode_called_(false) -{ - Read(json_filename); - Initialise(); -} - -Controller::~Controller() {} - -void Controller::Read(char const *filename) -{ - boost::property_tree::ptree root; - boost::property_tree::read_json(filename, root); - for (auto const &key_and_value : root) { - Algorithm *algo = CreateAlgorithm(key_and_value.first.c_str()); - if (algo) { - algo->Read(key_and_value.second); - algorithms_.push_back(AlgorithmPtr(algo)); - } else - LOG(RPiController, Warning) - << "No algorithm found for \"" << key_and_value.first << "\""; - } -} - -Algorithm *Controller::CreateAlgorithm(char const *name) -{ - auto it = GetAlgorithms().find(std::string(name)); - return it != GetAlgorithms().end() ? (*it->second)(this) : nullptr; -} - -void Controller::Initialise() -{ - for (auto &algo : algorithms_) - algo->Initialise(); -} - -void Controller::SwitchMode(CameraMode const &camera_mode, Metadata *metadata) -{ - for (auto &algo : algorithms_) - algo->SwitchMode(camera_mode, metadata); - switch_mode_called_ = true; -} - -void Controller::Prepare(Metadata *image_metadata) -{ - assert(switch_mode_called_); - for (auto &algo : algorithms_) - if (!algo->IsPaused()) - algo->Prepare(image_metadata); -} - -void Controller::Process(StatisticsPtr stats, Metadata *image_metadata) -{ - assert(switch_mode_called_); - for (auto &algo : algorithms_) - if (!algo->IsPaused()) - algo->Process(stats, image_metadata); -} - -Metadata &Controller::GetGlobalMetadata() -{ - return global_metadata_; -} - -Algorithm *Controller::GetAlgorithm(std::string const &name) const -{ - // The passed name must be the entire algorithm name, or must match the - // last part of it with a period (.) just before. - size_t name_len = name.length(); - for (auto &algo : algorithms_) { - char const *algo_name = algo->Name(); - size_t algo_name_len = strlen(algo_name); - if (algo_name_len >= name_len && - strcasecmp(name.c_str(), - algo_name + algo_name_len - name_len) == 0 && - (name_len == algo_name_len || - algo_name[algo_name_len - name_len - 1] == '.')) - return algo.get(); - } - return nullptr; -} diff --git a/src/ipa/raspberrypi/controller/controller.hpp b/src/ipa/raspberrypi/controller/controller.hpp deleted file mode 100644 index 3b50ae77..00000000 --- a/src/ipa/raspberrypi/controller/controller.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * controller.hpp - ISP controller interface - */ -#pragma once - -// The Controller is simply a container for a collecting together a number of -// "control algorithms" (such as AWB etc.) and for running them all in a -// convenient manner. - -#include <vector> -#include <string> - -#include <linux/bcm2835-isp.h> - -#include "camera_mode.h" -#include "device_status.h" -#include "metadata.hpp" - -namespace RPiController { - -class Algorithm; -typedef std::unique_ptr<Algorithm> AlgorithmPtr; -typedef std::shared_ptr<bcm2835_isp_stats> StatisticsPtr; - -// The Controller holds a pointer to some global_metadata, which is how -// different controllers and control algorithms within them can exchange -// information. The Prepare function returns a pointer to metadata for this -// specific image, and which should be passed on to the Process function. - -class Controller -{ -public: - Controller(); - Controller(char const *json_filename); - ~Controller(); - Algorithm *CreateAlgorithm(char const *name); - void Read(char const *filename); - void Initialise(); - void SwitchMode(CameraMode const &camera_mode, Metadata *metadata); - void Prepare(Metadata *image_metadata); - void Process(StatisticsPtr stats, Metadata *image_metadata); - Metadata &GetGlobalMetadata(); - Algorithm *GetAlgorithm(std::string const &name) const; - -protected: - Metadata global_metadata_; - std::vector<AlgorithmPtr> algorithms_; - bool switch_mode_called_; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/denoise_algorithm.hpp b/src/ipa/raspberrypi/controller/denoise_algorithm.hpp deleted file mode 100644 index 39fcd7e9..00000000 --- a/src/ipa/raspberrypi/controller/denoise_algorithm.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2021, Raspberry Pi (Trading) Limited - * - * denoise.hpp - Denoise control algorithm interface - */ -#pragma once - -#include "algorithm.hpp" - -namespace RPiController { - -enum class DenoiseMode { Off, ColourOff, ColourFast, ColourHighQuality }; - -class DenoiseAlgorithm : public Algorithm -{ -public: - DenoiseAlgorithm(Controller *controller) : Algorithm(controller) {} - // A Denoise algorithm must provide the following: - virtual void SetMode(DenoiseMode mode) = 0; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/denoise_status.h b/src/ipa/raspberrypi/controller/denoise_status.h deleted file mode 100644 index 67a3c361..00000000 --- a/src/ipa/raspberrypi/controller/denoise_status.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019-2021, Raspberry Pi (Trading) Limited - * - * denoise_status.h - Denoise control algorithm status - */ -#pragma once - -// This stores the parameters required for Denoise. - -#ifdef __cplusplus -extern "C" { -#endif - -struct DenoiseStatus { - double noise_constant; - double noise_slope; - double strength; - unsigned int mode; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/ipa/raspberrypi/controller/device_status.cpp b/src/ipa/raspberrypi/controller/device_status.cpp deleted file mode 100644 index a389c40d..00000000 --- a/src/ipa/raspberrypi/controller/device_status.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2021, Raspberry Pi (Trading) Limited - * - * device_status.cpp - device (image sensor) status - */ -#include "device_status.h" - -using namespace libcamera; /* for the Duration operator<< overload */ - -std::ostream &operator<<(std::ostream &out, const DeviceStatus &d) -{ - out << "Exposure: " << d.shutter_speed - << " Frame length: " << d.frame_length - << " Gain: " << d.analogue_gain; - - if (d.aperture) - out << " Aperture: " << *d.aperture; - - if (d.lens_position) - out << " Lens: " << *d.lens_position; - - if (d.flash_intensity) - out << " Flash: " << *d.flash_intensity; - - if (d.sensor_temperature) - out << " Temperature: " << *d.sensor_temperature; - - return out; -} diff --git a/src/ipa/raspberrypi/controller/device_status.h b/src/ipa/raspberrypi/controller/device_status.h deleted file mode 100644 index b33f0d09..00000000 --- a/src/ipa/raspberrypi/controller/device_status.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019-2021, Raspberry Pi (Trading) Limited - * - * device_status.h - device (image sensor) status - */ -#pragma once - -#include <iostream> -#include <optional> - -#include <libcamera/base/utils.h> - -/* - * Definition of "device metadata" which stores things like shutter time and - * analogue gain that downstream control algorithms will want to know. - */ - -struct DeviceStatus { - DeviceStatus() - : shutter_speed(std::chrono::seconds(0)), frame_length(0), - analogue_gain(0.0) - { - } - - friend std::ostream &operator<<(std::ostream &out, const DeviceStatus &d); - - /* time shutter is open */ - libcamera::utils::Duration shutter_speed; - /* frame length given in number of lines */ - uint32_t frame_length; - double analogue_gain; - /* 1.0/distance-in-metres, or 0 if unknown */ - std::optional<double> lens_position; - /* 1/f so that brightness quadruples when this doubles, or 0 if unknown */ - std::optional<double> aperture; - /* proportional to brightness with 0 = no flash, 1 = maximum flash */ - std::optional<double> flash_intensity; - /* Sensor reported temperature value (in degrees) */ - std::optional<double> sensor_temperature; -}; diff --git a/src/ipa/raspberrypi/controller/dpc_status.h b/src/ipa/raspberrypi/controller/dpc_status.h deleted file mode 100644 index a3ec2762..00000000 --- a/src/ipa/raspberrypi/controller/dpc_status.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * dpc_status.h - DPC (defective pixel correction) control algorithm status - */ -#pragma once - -// The "DPC" algorithm sets defective pixel correction strength. - -#ifdef __cplusplus -extern "C" { -#endif - -struct DpcStatus { - int strength; // 0 = "off", 1 = "normal", 2 = "strong" -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/ipa/raspberrypi/controller/focus_status.h b/src/ipa/raspberrypi/controller/focus_status.h deleted file mode 100644 index ace2fe2c..00000000 --- a/src/ipa/raspberrypi/controller/focus_status.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2020, Raspberry Pi (Trading) Limited - * - * focus_status.h - focus measurement status - */ -#pragma once - -#include <linux/bcm2835-isp.h> - -// The focus algorithm should post the following structure into the image's -// "focus.status" metadata. Recall that it's only reporting focus (contrast) -// measurements, it's not driving any kind of auto-focus algorithm! - -#ifdef __cplusplus -extern "C" { -#endif - -struct FocusStatus { - unsigned int num; - uint32_t focus_measures[FOCUS_REGIONS]; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/ipa/raspberrypi/controller/geq_status.h b/src/ipa/raspberrypi/controller/geq_status.h deleted file mode 100644 index 07fd5f03..00000000 --- a/src/ipa/raspberrypi/controller/geq_status.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * geq_status.h - GEQ (green equalisation) control algorithm status - */ -#pragma once - -// The "GEQ" algorithm calculates the green equalisation thresholds - -#ifdef __cplusplus -extern "C" { -#endif - -struct GeqStatus { - uint16_t offset; - double slope; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/ipa/raspberrypi/controller/histogram.cpp b/src/ipa/raspberrypi/controller/histogram.cpp deleted file mode 100644 index 9916b3ed..00000000 --- a/src/ipa/raspberrypi/controller/histogram.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * histogram.cpp - histogram calculations - */ -#include <math.h> -#include <stdio.h> - -#include "histogram.hpp" - -using namespace RPiController; - -uint64_t Histogram::CumulativeFreq(double bin) const -{ - if (bin <= 0) - return 0; - else if (bin >= Bins()) - return Total(); - int b = (int)bin; - return cumulative_[b] + - (bin - b) * (cumulative_[b + 1] - cumulative_[b]); -} - -double Histogram::Quantile(double q, int first, int last) const -{ - if (first == -1) - first = 0; - if (last == -1) - last = cumulative_.size() - 2; - assert(first <= last); - uint64_t items = q * Total(); - while (first < last) // binary search to find the right bin - { - int middle = (first + last) / 2; - if (cumulative_[middle + 1] > items) - last = middle; // between first and middle - else - first = middle + 1; // after middle - } - assert(items >= cumulative_[first] && items <= cumulative_[last + 1]); - double frac = cumulative_[first + 1] == cumulative_[first] ? 0 - : (double)(items - cumulative_[first]) / - (cumulative_[first + 1] - cumulative_[first]); - return first + frac; -} - -double Histogram::InterQuantileMean(double q_lo, double q_hi) const -{ - assert(q_hi > q_lo); - double p_lo = Quantile(q_lo); - double p_hi = Quantile(q_hi, (int)p_lo); - double sum_bin_freq = 0, cumul_freq = 0; - for (double p_next = floor(p_lo) + 1.0; p_next <= ceil(p_hi); - p_lo = p_next, p_next += 1.0) { - int bin = floor(p_lo); - double freq = (cumulative_[bin + 1] - cumulative_[bin]) * - (std::min(p_next, p_hi) - p_lo); - sum_bin_freq += bin * freq; - cumul_freq += freq; - } - // add 0.5 to give an average for bin mid-points - return sum_bin_freq / cumul_freq + 0.5; -} diff --git a/src/ipa/raspberrypi/controller/histogram.hpp b/src/ipa/raspberrypi/controller/histogram.hpp deleted file mode 100644 index 90f5ac78..00000000 --- a/src/ipa/raspberrypi/controller/histogram.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * histogram.hpp - histogram calculation interface - */ -#pragma once - -#include <stdint.h> -#include <vector> -#include <cassert> - -// A simple histogram class, for use in particular to find "quantiles" and -// averages between "quantiles". - -namespace RPiController { - -class Histogram -{ -public: - template<typename T> Histogram(T *histogram, int num) - { - assert(num); - cumulative_.reserve(num + 1); - cumulative_.push_back(0); - for (int i = 0; i < num; i++) - cumulative_.push_back(cumulative_.back() + - histogram[i]); - } - uint32_t Bins() const { return cumulative_.size() - 1; } - uint64_t Total() const { return cumulative_[cumulative_.size() - 1]; } - // Cumulative frequency up to a (fractional) point in a bin. - uint64_t CumulativeFreq(double bin) const; - // Return the (fractional) bin of the point q (0 <= q <= 1) through the - // histogram. Optionally provide limits to help. - double Quantile(double q, int first = -1, int last = -1) const; - // Return the average histogram bin value between the two quantiles. - double InterQuantileMean(double q_lo, double q_hi) const; - -private: - std::vector<uint64_t> cumulative_; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/lux_status.h b/src/ipa/raspberrypi/controller/lux_status.h deleted file mode 100644 index 8ccfd933..00000000 --- a/src/ipa/raspberrypi/controller/lux_status.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * lux_status.h - Lux control algorithm status - */ -#pragma once - -// The "lux" algorithm looks at the (AGC) histogram statistics of the frame and -// estimates the current lux level of the scene. It does this by a simple ratio -// calculation comparing to a reference image that was taken in known conditions -// with known statistics and a properly measured lux level. There is a slight -// problem with aperture, in that it may be variable without the system knowing -// or being aware of it. In this case an external application may set a -// "current_aperture" value if it wishes, which would be used in place of the -// (presumably meaningless) value in the image metadata. - -#ifdef __cplusplus -extern "C" { -#endif - -struct LuxStatus { - double lux; - double aperture; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/ipa/raspberrypi/controller/metadata.hpp b/src/ipa/raspberrypi/controller/metadata.hpp deleted file mode 100644 index 51e576cf..00000000 --- a/src/ipa/raspberrypi/controller/metadata.hpp +++ /dev/null @@ -1,110 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019-2021, Raspberry Pi (Trading) Limited - * - * metadata.hpp - general metadata class - */ -#pragma once - -// A simple class for carrying arbitrary metadata, for example about an image. - -#include <any> -#include <map> -#include <mutex> -#include <string> - -namespace RPiController { - -class Metadata -{ -public: - Metadata() = default; - - Metadata(Metadata const &other) - { - std::scoped_lock other_lock(other.mutex_); - data_ = other.data_; - } - - Metadata(Metadata &&other) - { - std::scoped_lock other_lock(other.mutex_); - data_ = std::move(other.data_); - other.data_.clear(); - } - - template<typename T> - void Set(std::string const &tag, T const &value) - { - std::scoped_lock lock(mutex_); - data_[tag] = value; - } - - template<typename T> - int Get(std::string const &tag, T &value) const - { - std::scoped_lock lock(mutex_); - auto it = data_.find(tag); - if (it == data_.end()) - return -1; - value = std::any_cast<T>(it->second); - return 0; - } - - void Clear() - { - std::scoped_lock lock(mutex_); - data_.clear(); - } - - Metadata &operator=(Metadata const &other) - { - std::scoped_lock lock(mutex_, other.mutex_); - data_ = other.data_; - return *this; - } - - Metadata &operator=(Metadata &&other) - { - std::scoped_lock lock(mutex_, other.mutex_); - data_ = std::move(other.data_); - other.data_.clear(); - return *this; - } - - void Merge(Metadata &other) - { - std::scoped_lock lock(mutex_, other.mutex_); - data_.merge(other.data_); - } - - template<typename T> - T *GetLocked(std::string const &tag) - { - // This allows in-place access to the Metadata contents, - // for which you should be holding the lock. - auto it = data_.find(tag); - if (it == data_.end()) - return nullptr; - return std::any_cast<T>(&it->second); - } - - template<typename T> - void SetLocked(std::string const &tag, T const &value) - { - // Use this only if you're holding the lock yourself. - data_[tag] = value; - } - - // Note: use of (lowercase) lock and unlock means you can create scoped - // locks with the standard lock classes. - // e.g. std::lock_guard<RPiController::Metadata> lock(metadata) - void lock() { mutex_.lock(); } - void unlock() { mutex_.unlock(); } - -private: - mutable std::mutex mutex_; - std::map<std::string, std::any> data_; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/noise_status.h b/src/ipa/raspberrypi/controller/noise_status.h deleted file mode 100644 index 8439a402..00000000 --- a/src/ipa/raspberrypi/controller/noise_status.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * noise_status.h - Noise control algorithm status - */ -#pragma once - -// The "noise" algorithm stores an estimate of the noise profile for this image. - -#ifdef __cplusplus -extern "C" { -#endif - -struct NoiseStatus { - double noise_constant; - double noise_slope; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/ipa/raspberrypi/controller/pwl.cpp b/src/ipa/raspberrypi/controller/pwl.cpp deleted file mode 100644 index 130c820b..00000000 --- a/src/ipa/raspberrypi/controller/pwl.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * pwl.cpp - piecewise linear functions - */ - -#include <cassert> -#include <stdexcept> - -#include "pwl.hpp" - -using namespace RPiController; - -void Pwl::Read(boost::property_tree::ptree const ¶ms) -{ - for (auto it = params.begin(); it != params.end(); it++) { - double x = it->second.get_value<double>(); - assert(it == params.begin() || x > points_.back().x); - it++; - double y = it->second.get_value<double>(); - points_.push_back(Point(x, y)); - } - assert(points_.size() >= 2); -} - -void Pwl::Append(double x, double y, const double eps) -{ - if (points_.empty() || points_.back().x + eps < x) - points_.push_back(Point(x, y)); -} - -void Pwl::Prepend(double x, double y, const double eps) -{ - if (points_.empty() || points_.front().x - eps > x) - points_.insert(points_.begin(), Point(x, y)); -} - -Pwl::Interval Pwl::Domain() const -{ - return Interval(points_[0].x, points_[points_.size() - 1].x); -} - -Pwl::Interval Pwl::Range() const -{ - double lo = points_[0].y, hi = lo; - for (auto &p : points_) - lo = std::min(lo, p.y), hi = std::max(hi, p.y); - return Interval(lo, hi); -} - -bool Pwl::Empty() const -{ - return points_.empty(); -} - -double Pwl::Eval(double x, int *span_ptr, bool update_span) const -{ - int span = findSpan(x, span_ptr && *span_ptr != -1 - ? *span_ptr - : points_.size() / 2 - 1); - if (span_ptr && update_span) - *span_ptr = span; - return points_[span].y + - (x - points_[span].x) * (points_[span + 1].y - points_[span].y) / - (points_[span + 1].x - points_[span].x); -} - -int Pwl::findSpan(double x, int span) const -{ - // Pwls are generally small, so linear search may well be faster than - // binary, though could review this if large PWls start turning up. - int last_span = points_.size() - 2; - // some algorithms may call us with span pointing directly at the last - // control point - span = std::max(0, std::min(last_span, span)); - while (span < last_span && x >= points_[span + 1].x) - span++; - while (span && x < points_[span].x) - span--; - return span; -} - -Pwl::PerpType Pwl::Invert(Point const &xy, Point &perp, int &span, - const double eps) const -{ - assert(span >= -1); - bool prev_off_end = false; - for (span = span + 1; span < (int)points_.size() - 1; span++) { - Point span_vec = points_[span + 1] - points_[span]; - double t = ((xy - points_[span]) % span_vec) / span_vec.Len2(); - if (t < -eps) // off the start of this span - { - if (span == 0) { - perp = points_[span]; - return PerpType::Start; - } else if (prev_off_end) { - perp = points_[span]; - return PerpType::Vertex; - } - } else if (t > 1 + eps) // off the end of this span - { - if (span == (int)points_.size() - 2) { - perp = points_[span + 1]; - return PerpType::End; - } - prev_off_end = true; - } else // a true perpendicular - { - perp = points_[span] + span_vec * t; - return PerpType::Perpendicular; - } - } - return PerpType::None; -} - -Pwl Pwl::Inverse(bool *true_inverse, const double eps) const -{ - bool appended = false, prepended = false, neither = false; - Pwl inverse; - - for (Point const &p : points_) { - if (inverse.Empty()) - inverse.Append(p.y, p.x, eps); - else if (std::abs(inverse.points_.back().x - p.y) <= eps || - std::abs(inverse.points_.front().x - p.y) <= eps) - /* do nothing */; - else if (p.y > inverse.points_.back().x) { - inverse.Append(p.y, p.x, eps); - appended = true; - } else if (p.y < inverse.points_.front().x) { - inverse.Prepend(p.y, p.x, eps); - prepended = true; - } else - neither = true; - } - - // This is not a proper inverse if we found ourselves putting points - // onto both ends of the inverse, or if there were points that couldn't - // go on either. - if (true_inverse) - *true_inverse = !(neither || (appended && prepended)); - - return inverse; -} - -Pwl Pwl::Compose(Pwl const &other, const double eps) const -{ - double this_x = points_[0].x, this_y = points_[0].y; - int this_span = 0, other_span = other.findSpan(this_y, 0); - Pwl result({ { this_x, other.Eval(this_y, &other_span, false) } }); - while (this_span != (int)points_.size() - 1) { - double dx = points_[this_span + 1].x - points_[this_span].x, - dy = points_[this_span + 1].y - points_[this_span].y; - if (abs(dy) > eps && - other_span + 1 < (int)other.points_.size() && - points_[this_span + 1].y >= - other.points_[other_span + 1].x + eps) { - // next control point in result will be where this - // function's y reaches the next span in other - this_x = points_[this_span].x + - (other.points_[other_span + 1].x - - points_[this_span].y) * dx / dy; - this_y = other.points_[++other_span].x; - } else if (abs(dy) > eps && other_span > 0 && - points_[this_span + 1].y <= - other.points_[other_span - 1].x - eps) { - // next control point in result will be where this - // function's y reaches the previous span in other - this_x = points_[this_span].x + - (other.points_[other_span + 1].x - - points_[this_span].y) * dx / dy; - this_y = other.points_[--other_span].x; - } else { - // we stay in the same span in other - this_span++; - this_x = points_[this_span].x, - this_y = points_[this_span].y; - } - result.Append(this_x, other.Eval(this_y, &other_span, false), - eps); - } - return result; -} - -void Pwl::Map(std::function<void(double x, double y)> f) const -{ - for (auto &pt : points_) - f(pt.x, pt.y); -} - -void Pwl::Map2(Pwl const &pwl0, Pwl const &pwl1, - std::function<void(double x, double y0, double y1)> f) -{ - int span0 = 0, span1 = 0; - double x = std::min(pwl0.points_[0].x, pwl1.points_[0].x); - f(x, pwl0.Eval(x, &span0, false), pwl1.Eval(x, &span1, false)); - while (span0 < (int)pwl0.points_.size() - 1 || - span1 < (int)pwl1.points_.size() - 1) { - if (span0 == (int)pwl0.points_.size() - 1) - x = pwl1.points_[++span1].x; - else if (span1 == (int)pwl1.points_.size() - 1) - x = pwl0.points_[++span0].x; - else if (pwl0.points_[span0 + 1].x > pwl1.points_[span1 + 1].x) - x = pwl1.points_[++span1].x; - else - x = pwl0.points_[++span0].x; - f(x, pwl0.Eval(x, &span0, false), pwl1.Eval(x, &span1, false)); - } -} - -Pwl Pwl::Combine(Pwl const &pwl0, Pwl const &pwl1, - std::function<double(double x, double y0, double y1)> f, - const double eps) -{ - Pwl result; - Map2(pwl0, pwl1, [&](double x, double y0, double y1) { - result.Append(x, f(x, y0, y1), eps); - }); - return result; -} - -void Pwl::MatchDomain(Interval const &domain, bool clip, const double eps) -{ - int span = 0; - Prepend(domain.start, Eval(clip ? points_[0].x : domain.start, &span), - eps); - span = points_.size() - 2; - Append(domain.end, Eval(clip ? points_.back().x : domain.end, &span), - eps); -} - -Pwl &Pwl::operator*=(double d) -{ - for (auto &pt : points_) - pt.y *= d; - return *this; -} - -void Pwl::Debug(FILE *fp) const -{ - fprintf(fp, "Pwl {\n"); - for (auto &p : points_) - fprintf(fp, "\t(%g, %g)\n", p.x, p.y); - fprintf(fp, "}\n"); -} diff --git a/src/ipa/raspberrypi/controller/pwl.hpp b/src/ipa/raspberrypi/controller/pwl.hpp deleted file mode 100644 index 484672f6..00000000 --- a/src/ipa/raspberrypi/controller/pwl.hpp +++ /dev/null @@ -1,112 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * pwl.hpp - piecewise linear functions interface - */ -#pragma once - -#include <math.h> -#include <vector> - -#include <boost/property_tree/ptree.hpp> - -namespace RPiController { - -class Pwl -{ -public: - struct Interval { - Interval(double _start, double _end) : start(_start), end(_end) - { - } - double start, end; - bool Contains(double value) - { - return value >= start && value <= end; - } - double Clip(double value) - { - return value < start ? start - : (value > end ? end : value); - } - double Len() const { return end - start; } - }; - struct Point { - Point() : x(0), y(0) {} - Point(double _x, double _y) : x(_x), y(_y) {} - double x, y; - Point operator-(Point const &p) const - { - return Point(x - p.x, y - p.y); - } - Point operator+(Point const &p) const - { - return Point(x + p.x, y + p.y); - } - double operator%(Point const &p) const - { - return x * p.x + y * p.y; - } - Point operator*(double f) const { return Point(x * f, y * f); } - Point operator/(double f) const { return Point(x / f, y / f); } - double Len2() const { return x * x + y * y; } - double Len() const { return sqrt(Len2()); } - }; - Pwl() {} - Pwl(std::vector<Point> const &points) : points_(points) {} - void Read(boost::property_tree::ptree const ¶ms); - void Append(double x, double y, const double eps = 1e-6); - void Prepend(double x, double y, const double eps = 1e-6); - Interval Domain() const; - Interval Range() const; - bool Empty() const; - // Evaluate Pwl, optionally supplying an initial guess for the - // "span". The "span" may be optionally be updated. If you want to know - // the "span" value but don't have an initial guess you can set it to - // -1. - double Eval(double x, int *span_ptr = nullptr, - bool update_span = true) const; - // Find perpendicular closest to xy, starting from span+1 so you can - // call it repeatedly to check for multiple closest points (set span to - // -1 on the first call). Also returns "pseudo" perpendiculars; see - // PerpType enum. - enum class PerpType { - None, // no perpendicular found - Start, // start of Pwl is closest point - End, // end of Pwl is closest point - Vertex, // vertex of Pwl is closest point - Perpendicular // true perpendicular found - }; - PerpType Invert(Point const &xy, Point &perp, int &span, - const double eps = 1e-6) const; - // Compute the inverse function. Indicate if it is a proper (true) - // inverse, or only a best effort (e.g. input was non-monotonic). - Pwl Inverse(bool *true_inverse = nullptr, const double eps = 1e-6) const; - // Compose two Pwls together, doing "this" first and "other" after. - Pwl Compose(Pwl const &other, const double eps = 1e-6) const; - // Apply function to (x,y) values at every control point. - void Map(std::function<void(double x, double y)> f) const; - // Apply function to (x, y0, y1) values wherever either Pwl has a - // control point. - static void Map2(Pwl const &pwl0, Pwl const &pwl1, - std::function<void(double x, double y0, double y1)> f); - // Combine two Pwls, meaning we create a new Pwl where the y values are - // given by running f wherever either has a knot. - static Pwl - Combine(Pwl const &pwl0, Pwl const &pwl1, - std::function<double(double x, double y0, double y1)> f, - const double eps = 1e-6); - // Make "this" match (at least) the given domain. Any extension my be - // clipped or linear. - void MatchDomain(Interval const &domain, bool clip = true, - const double eps = 1e-6); - Pwl &operator*=(double d); - void Debug(FILE *fp = stdout) const; - -private: - int findSpan(double x, int span) const; - std::vector<Point> points_; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp deleted file mode 100644 index f6a9cb0a..00000000 --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp +++ /dev/null @@ -1,797 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * agc.cpp - AGC/AEC control algorithm - */ - -#include <map> - -#include <linux/bcm2835-isp.h> - -#include <libcamera/base/log.h> - -#include "../awb_status.h" -#include "../device_status.h" -#include "../histogram.hpp" -#include "../lux_status.h" -#include "../metadata.hpp" - -#include "agc.hpp" - -using namespace RPiController; -using namespace libcamera; -using libcamera::utils::Duration; -using namespace std::literals::chrono_literals; - -LOG_DEFINE_CATEGORY(RPiAgc) - -#define NAME "rpi.agc" - -#define PIPELINE_BITS 13 // seems to be a 13-bit pipeline - -void AgcMeteringMode::Read(boost::property_tree::ptree const ¶ms) -{ - int num = 0; - for (auto &p : params.get_child("weights")) { - if (num == AGC_STATS_SIZE) - throw std::runtime_error("AgcConfig: too many weights"); - weights[num++] = p.second.get_value<double>(); - } - if (num != AGC_STATS_SIZE) - throw std::runtime_error("AgcConfig: insufficient weights"); -} - -static std::string -read_metering_modes(std::map<std::string, AgcMeteringMode> &metering_modes, - boost::property_tree::ptree const ¶ms) -{ - std::string first; - for (auto &p : params) { - AgcMeteringMode metering_mode; - metering_mode.Read(p.second); - metering_modes[p.first] = std::move(metering_mode); - if (first.empty()) - first = p.first; - } - return first; -} - -static int read_list(std::vector<double> &list, - boost::property_tree::ptree const ¶ms) -{ - for (auto &p : params) - list.push_back(p.second.get_value<double>()); - return list.size(); -} - -static int read_list(std::vector<Duration> &list, - boost::property_tree::ptree const ¶ms) -{ - for (auto &p : params) - list.push_back(p.second.get_value<double>() * 1us); - return list.size(); -} - -void AgcExposureMode::Read(boost::property_tree::ptree const ¶ms) -{ - int num_shutters = read_list(shutter, params.get_child("shutter")); - int num_ags = read_list(gain, params.get_child("gain")); - if (num_shutters < 2 || num_ags < 2) - throw std::runtime_error( - "AgcConfig: must have at least two entries in exposure profile"); - if (num_shutters != num_ags) - throw std::runtime_error( - "AgcConfig: expect same number of exposure and gain entries in exposure profile"); -} - -static std::string -read_exposure_modes(std::map<std::string, AgcExposureMode> &exposure_modes, - boost::property_tree::ptree const ¶ms) -{ - std::string first; - for (auto &p : params) { - AgcExposureMode exposure_mode; - exposure_mode.Read(p.second); - exposure_modes[p.first] = std::move(exposure_mode); - if (first.empty()) - first = p.first; - } - return first; -} - -void AgcConstraint::Read(boost::property_tree::ptree const ¶ms) -{ - std::string bound_string = params.get<std::string>("bound", ""); - transform(bound_string.begin(), bound_string.end(), - bound_string.begin(), ::toupper); - if (bound_string != "UPPER" && bound_string != "LOWER") - throw std::runtime_error( - "AGC constraint type should be UPPER or LOWER"); - bound = bound_string == "UPPER" ? Bound::UPPER : Bound::LOWER; - q_lo = params.get<double>("q_lo"); - q_hi = params.get<double>("q_hi"); - Y_target.Read(params.get_child("y_target")); -} - -static AgcConstraintMode -read_constraint_mode(boost::property_tree::ptree const ¶ms) -{ - AgcConstraintMode mode; - for (auto &p : params) { - AgcConstraint constraint; - constraint.Read(p.second); - mode.push_back(std::move(constraint)); - } - return mode; -} - -static std::string read_constraint_modes( - std::map<std::string, AgcConstraintMode> &constraint_modes, - boost::property_tree::ptree const ¶ms) -{ - std::string first; - for (auto &p : params) { - constraint_modes[p.first] = read_constraint_mode(p.second); - if (first.empty()) - first = p.first; - } - return first; -} - -void AgcConfig::Read(boost::property_tree::ptree const ¶ms) -{ - LOG(RPiAgc, Debug) << "AgcConfig"; - default_metering_mode = read_metering_modes( - metering_modes, params.get_child("metering_modes")); - default_exposure_mode = read_exposure_modes( - exposure_modes, params.get_child("exposure_modes")); - default_constraint_mode = read_constraint_modes( - constraint_modes, params.get_child("constraint_modes")); - Y_target.Read(params.get_child("y_target")); - speed = params.get<double>("speed", 0.2); - startup_frames = params.get<uint16_t>("startup_frames", 10); - convergence_frames = params.get<unsigned int>("convergence_frames", 6); - fast_reduce_threshold = - params.get<double>("fast_reduce_threshold", 0.4); - base_ev = params.get<double>("base_ev", 1.0); - // Start with quite a low value as ramping up is easier than ramping down. - default_exposure_time = params.get<double>("default_exposure_time", 1000) * 1us; - default_analogue_gain = params.get<double>("default_analogue_gain", 1.0); -} - -Agc::ExposureValues::ExposureValues() - : shutter(0s), analogue_gain(0), - total_exposure(0s), total_exposure_no_dg(0s) -{ -} - -Agc::Agc(Controller *controller) - : AgcAlgorithm(controller), metering_mode_(nullptr), - exposure_mode_(nullptr), constraint_mode_(nullptr), - frame_count_(0), lock_count_(0), - last_target_exposure_(0s), last_sensitivity_(0.0), - ev_(1.0), flicker_period_(0s), - max_shutter_(0s), fixed_shutter_(0s), fixed_analogue_gain_(0.0) -{ - memset(&awb_, 0, sizeof(awb_)); - // Setting status_.total_exposure_value_ to zero initially tells us - // it's not been calculated yet (i.e. Process hasn't yet run). - memset(&status_, 0, sizeof(status_)); - status_.ev = ev_; -} - -char const *Agc::Name() const -{ - return NAME; -} - -void Agc::Read(boost::property_tree::ptree const ¶ms) -{ - LOG(RPiAgc, Debug) << "Agc"; - config_.Read(params); - // Set the config's defaults (which are the first ones it read) as our - // current modes, until someone changes them. (they're all known to - // exist at this point) - metering_mode_name_ = config_.default_metering_mode; - metering_mode_ = &config_.metering_modes[metering_mode_name_]; - exposure_mode_name_ = config_.default_exposure_mode; - exposure_mode_ = &config_.exposure_modes[exposure_mode_name_]; - constraint_mode_name_ = config_.default_constraint_mode; - constraint_mode_ = &config_.constraint_modes[constraint_mode_name_]; - // Set up the "last shutter/gain" values, in case AGC starts "disabled". - status_.shutter_time = config_.default_exposure_time; - status_.analogue_gain = config_.default_analogue_gain; -} - -bool Agc::IsPaused() const -{ - return false; -} - -void Agc::Pause() -{ - fixed_shutter_ = status_.shutter_time; - fixed_analogue_gain_ = status_.analogue_gain; -} - -void Agc::Resume() -{ - fixed_shutter_ = 0s; - fixed_analogue_gain_ = 0; -} - -unsigned int Agc::GetConvergenceFrames() const -{ - // If shutter and gain have been explicitly set, there is no - // convergence to happen, so no need to drop any frames - return zero. - if (fixed_shutter_ && fixed_analogue_gain_) - return 0; - else - return config_.convergence_frames; -} - -void Agc::SetEv(double ev) -{ - ev_ = ev; -} - -void Agc::SetFlickerPeriod(Duration flicker_period) -{ - flicker_period_ = flicker_period; -} - -void Agc::SetMaxShutter(Duration max_shutter) -{ - max_shutter_ = max_shutter; -} - -void Agc::SetFixedShutter(Duration fixed_shutter) -{ - fixed_shutter_ = fixed_shutter; - // Set this in case someone calls Pause() straight after. - status_.shutter_time = clipShutter(fixed_shutter_); -} - -void Agc::SetFixedAnalogueGain(double fixed_analogue_gain) -{ - fixed_analogue_gain_ = fixed_analogue_gain; - // Set this in case someone calls Pause() straight after. - status_.analogue_gain = fixed_analogue_gain; -} - -void Agc::SetMeteringMode(std::string const &metering_mode_name) -{ - metering_mode_name_ = metering_mode_name; -} - -void Agc::SetExposureMode(std::string const &exposure_mode_name) -{ - exposure_mode_name_ = exposure_mode_name; -} - -void Agc::SetConstraintMode(std::string const &constraint_mode_name) -{ - constraint_mode_name_ = constraint_mode_name; -} - -void Agc::SwitchMode(CameraMode const &camera_mode, - Metadata *metadata) -{ - /* AGC expects the mode sensitivity always to be non-zero. */ - ASSERT(camera_mode.sensitivity); - - housekeepConfig(); - - Duration fixed_shutter = clipShutter(fixed_shutter_); - if (fixed_shutter && fixed_analogue_gain_) { - // We're going to reset the algorithm here with these fixed values. - - fetchAwbStatus(metadata); - double min_colour_gain = std::min({ awb_.gain_r, awb_.gain_g, awb_.gain_b, 1.0 }); - ASSERT(min_colour_gain != 0.0); - - // This is the equivalent of computeTargetExposure and applyDigitalGain. - target_.total_exposure_no_dg = fixed_shutter * fixed_analogue_gain_; - target_.total_exposure = target_.total_exposure_no_dg / min_colour_gain; - - // Equivalent of filterExposure. This resets any "history". - filtered_ = target_; - - // Equivalent of divideUpExposure. - filtered_.shutter = fixed_shutter; - filtered_.analogue_gain = fixed_analogue_gain_; - } else if (status_.total_exposure_value) { - // On a mode switch, various things could happen: - // - the exposure profile might change - // - a fixed exposure or gain might be set - // - the new mode's sensitivity might be different - // We cope with the last of these by scaling the target values. After - // that we just need to re-divide the exposure/gain according to the - // current exposure profile, which takes care of everything else. - - double ratio = last_sensitivity_ / camera_mode.sensitivity; - target_.total_exposure_no_dg *= ratio; - target_.total_exposure *= ratio; - filtered_.total_exposure_no_dg *= ratio; - filtered_.total_exposure *= ratio; - - divideUpExposure(); - } else { - // We come through here on startup, when at least one of the shutter - // or gain has not been fixed. We must still write those values out so - // that they will be applied immediately. We supply some arbitrary defaults - // for any that weren't set. - - // Equivalent of divideUpExposure. - filtered_.shutter = fixed_shutter ? fixed_shutter : config_.default_exposure_time; - filtered_.analogue_gain = fixed_analogue_gain_ ? fixed_analogue_gain_ : config_.default_analogue_gain; - } - - writeAndFinish(metadata, false); - - // We must remember the sensitivity of this mode for the next SwitchMode. - last_sensitivity_ = camera_mode.sensitivity; -} - -void Agc::Prepare(Metadata *image_metadata) -{ - status_.digital_gain = 1.0; - fetchAwbStatus(image_metadata); // always fetch it so that Process knows it's been done - - if (status_.total_exposure_value) { - // Process has run, so we have meaningful values. - DeviceStatus device_status; - if (image_metadata->Get("device.status", device_status) == 0) { - Duration actual_exposure = device_status.shutter_speed * - device_status.analogue_gain; - if (actual_exposure) { - status_.digital_gain = - status_.total_exposure_value / - actual_exposure; - LOG(RPiAgc, Debug) << "Want total exposure " << status_.total_exposure_value; - // Never ask for a gain < 1.0, and also impose - // some upper limit. Make it customisable? - status_.digital_gain = std::max( - 1.0, - std::min(status_.digital_gain, 4.0)); - LOG(RPiAgc, Debug) << "Actual exposure " << actual_exposure; - LOG(RPiAgc, Debug) << "Use digital_gain " << status_.digital_gain; - LOG(RPiAgc, Debug) << "Effective exposure " - << actual_exposure * status_.digital_gain; - // Decide whether AEC/AGC has converged. - updateLockStatus(device_status); - } - } else - LOG(RPiAgc, Warning) << Name() << ": no device metadata"; - image_metadata->Set("agc.status", status_); - } -} - -void Agc::Process(StatisticsPtr &stats, Metadata *image_metadata) -{ - frame_count_++; - // First a little bit of housekeeping, fetching up-to-date settings and - // configuration, that kind of thing. - housekeepConfig(); - // Get the current exposure values for the frame that's just arrived. - fetchCurrentExposure(image_metadata); - // Compute the total gain we require relative to the current exposure. - double gain, target_Y; - computeGain(stats.get(), image_metadata, gain, target_Y); - // Now compute the target (final) exposure which we think we want. - computeTargetExposure(gain); - // Some of the exposure has to be applied as digital gain, so work out - // what that is. This function also tells us whether it's decided to - // "desaturate" the image more quickly. - bool desaturate = applyDigitalGain(gain, target_Y); - // The results have to be filtered so as not to change too rapidly. - filterExposure(desaturate); - // The last thing is to divide up the exposure value into a shutter time - // and analogue_gain, according to the current exposure mode. - divideUpExposure(); - // Finally advertise what we've done. - writeAndFinish(image_metadata, desaturate); -} - -void Agc::updateLockStatus(DeviceStatus const &device_status) -{ - const double ERROR_FACTOR = 0.10; // make these customisable? - const int MAX_LOCK_COUNT = 5; - // Reset "lock count" when we exceed this multiple of ERROR_FACTOR - const double RESET_MARGIN = 1.5; - - // Add 200us to the exposure time error to allow for line quantisation. - Duration exposure_error = last_device_status_.shutter_speed * ERROR_FACTOR + 200us; - double gain_error = last_device_status_.analogue_gain * ERROR_FACTOR; - Duration target_error = last_target_exposure_ * ERROR_FACTOR; - - // Note that we don't know the exposure/gain limits of the sensor, so - // the values we keep requesting may be unachievable. For this reason - // we only insist that we're close to values in the past few frames. - if (device_status.shutter_speed > last_device_status_.shutter_speed - exposure_error && - device_status.shutter_speed < last_device_status_.shutter_speed + exposure_error && - device_status.analogue_gain > last_device_status_.analogue_gain - gain_error && - device_status.analogue_gain < last_device_status_.analogue_gain + gain_error && - status_.target_exposure_value > last_target_exposure_ - target_error && - status_.target_exposure_value < last_target_exposure_ + target_error) - lock_count_ = std::min(lock_count_ + 1, MAX_LOCK_COUNT); - else if (device_status.shutter_speed < last_device_status_.shutter_speed - RESET_MARGIN * exposure_error || - device_status.shutter_speed > last_device_status_.shutter_speed + RESET_MARGIN * exposure_error || - device_status.analogue_gain < last_device_status_.analogue_gain - RESET_MARGIN * gain_error || - device_status.analogue_gain > last_device_status_.analogue_gain + RESET_MARGIN * gain_error || - status_.target_exposure_value < last_target_exposure_ - RESET_MARGIN * target_error || - status_.target_exposure_value > last_target_exposure_ + RESET_MARGIN * target_error) - lock_count_ = 0; - - last_device_status_ = device_status; - last_target_exposure_ = status_.target_exposure_value; - - LOG(RPiAgc, Debug) << "Lock count updated to " << lock_count_; - status_.locked = lock_count_ == MAX_LOCK_COUNT; -} - -static void copy_string(std::string const &s, char *d, size_t size) -{ - size_t length = s.copy(d, size - 1); - d[length] = '\0'; -} - -void Agc::housekeepConfig() -{ - // First fetch all the up-to-date settings, so no one else has to do it. - status_.ev = ev_; - status_.fixed_shutter = clipShutter(fixed_shutter_); - status_.fixed_analogue_gain = fixed_analogue_gain_; - status_.flicker_period = flicker_period_; - LOG(RPiAgc, Debug) << "ev " << status_.ev << " fixed_shutter " - << status_.fixed_shutter << " fixed_analogue_gain " - << status_.fixed_analogue_gain; - // Make sure the "mode" pointers point to the up-to-date things, if - // they've changed. - if (strcmp(metering_mode_name_.c_str(), status_.metering_mode)) { - auto it = config_.metering_modes.find(metering_mode_name_); - if (it == config_.metering_modes.end()) - throw std::runtime_error("Agc: no metering mode " + - metering_mode_name_); - metering_mode_ = &it->second; - copy_string(metering_mode_name_, status_.metering_mode, - sizeof(status_.metering_mode)); - } - if (strcmp(exposure_mode_name_.c_str(), status_.exposure_mode)) { - auto it = config_.exposure_modes.find(exposure_mode_name_); - if (it == config_.exposure_modes.end()) - throw std::runtime_error("Agc: no exposure profile " + - exposure_mode_name_); - exposure_mode_ = &it->second; - copy_string(exposure_mode_name_, status_.exposure_mode, - sizeof(status_.exposure_mode)); - } - if (strcmp(constraint_mode_name_.c_str(), status_.constraint_mode)) { - auto it = - config_.constraint_modes.find(constraint_mode_name_); - if (it == config_.constraint_modes.end()) - throw std::runtime_error("Agc: no constraint list " + - constraint_mode_name_); - constraint_mode_ = &it->second; - copy_string(constraint_mode_name_, status_.constraint_mode, - sizeof(status_.constraint_mode)); - } - LOG(RPiAgc, Debug) << "exposure_mode " - << exposure_mode_name_ << " constraint_mode " - << constraint_mode_name_ << " metering_mode " - << metering_mode_name_; -} - -void Agc::fetchCurrentExposure(Metadata *image_metadata) -{ - std::unique_lock<Metadata> lock(*image_metadata); - DeviceStatus *device_status = - image_metadata->GetLocked<DeviceStatus>("device.status"); - if (!device_status) - throw std::runtime_error("Agc: no device metadata"); - current_.shutter = device_status->shutter_speed; - current_.analogue_gain = device_status->analogue_gain; - AgcStatus *agc_status = - image_metadata->GetLocked<AgcStatus>("agc.status"); - current_.total_exposure = agc_status ? agc_status->total_exposure_value : 0s; - current_.total_exposure_no_dg = current_.shutter * current_.analogue_gain; -} - -void Agc::fetchAwbStatus(Metadata *image_metadata) -{ - awb_.gain_r = 1.0; // in case not found in metadata - awb_.gain_g = 1.0; - awb_.gain_b = 1.0; - if (image_metadata->Get("awb.status", awb_) != 0) - LOG(RPiAgc, Debug) << "Agc: no AWB status found"; -} - -static double compute_initial_Y(bcm2835_isp_stats *stats, AwbStatus const &awb, - double weights[], double gain) -{ - bcm2835_isp_stats_region *regions = stats->agc_stats; - // Note how the calculation below means that equal weights give you - // "average" metering (i.e. all pixels equally important). - double R_sum = 0, G_sum = 0, B_sum = 0, pixel_sum = 0; - for (int i = 0; i < AGC_STATS_SIZE; i++) { - double counted = regions[i].counted; - double r_sum = std::min(regions[i].r_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted); - double g_sum = std::min(regions[i].g_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted); - double b_sum = std::min(regions[i].b_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted); - R_sum += r_sum * weights[i]; - G_sum += g_sum * weights[i]; - B_sum += b_sum * weights[i]; - pixel_sum += counted * weights[i]; - } - if (pixel_sum == 0.0) { - LOG(RPiAgc, Warning) << "compute_initial_Y: pixel_sum is zero"; - return 0; - } - double Y_sum = R_sum * awb.gain_r * .299 + - G_sum * awb.gain_g * .587 + - B_sum * awb.gain_b * .114; - return Y_sum / pixel_sum / (1 << PIPELINE_BITS); -} - -// We handle extra gain through EV by adjusting our Y targets. However, you -// simply can't monitor histograms once they get very close to (or beyond!) -// saturation, so we clamp the Y targets to this value. It does mean that EV -// increases don't necessarily do quite what you might expect in certain -// (contrived) cases. - -#define EV_GAIN_Y_TARGET_LIMIT 0.9 - -static double constraint_compute_gain(AgcConstraint &c, Histogram &h, - double lux, double ev_gain, - double &target_Y) -{ - target_Y = c.Y_target.Eval(c.Y_target.Domain().Clip(lux)); - target_Y = std::min(EV_GAIN_Y_TARGET_LIMIT, target_Y * ev_gain); - double iqm = h.InterQuantileMean(c.q_lo, c.q_hi); - return (target_Y * NUM_HISTOGRAM_BINS) / iqm; -} - -void Agc::computeGain(bcm2835_isp_stats *statistics, Metadata *image_metadata, - double &gain, double &target_Y) -{ - struct LuxStatus lux = {}; - lux.lux = 400; // default lux level to 400 in case no metadata found - if (image_metadata->Get("lux.status", lux) != 0) - LOG(RPiAgc, Warning) << "Agc: no lux level found"; - Histogram h(statistics->hist[0].g_hist, NUM_HISTOGRAM_BINS); - double ev_gain = status_.ev * config_.base_ev; - // The initial gain and target_Y come from some of the regions. After - // that we consider the histogram constraints. - target_Y = - config_.Y_target.Eval(config_.Y_target.Domain().Clip(lux.lux)); - target_Y = std::min(EV_GAIN_Y_TARGET_LIMIT, target_Y * ev_gain); - - // Do this calculation a few times as brightness increase can be - // non-linear when there are saturated regions. - gain = 1.0; - for (int i = 0; i < 8; i++) { - double initial_Y = compute_initial_Y(statistics, awb_, - metering_mode_->weights, gain); - double extra_gain = std::min(10.0, target_Y / (initial_Y + .001)); - gain *= extra_gain; - LOG(RPiAgc, Debug) << "Initial Y " << initial_Y << " target " << target_Y - << " gives gain " << gain; - if (extra_gain < 1.01) // close enough - break; - } - - for (auto &c : *constraint_mode_) { - double new_target_Y; - double new_gain = - constraint_compute_gain(c, h, lux.lux, ev_gain, - new_target_Y); - LOG(RPiAgc, Debug) << "Constraint has target_Y " - << new_target_Y << " giving gain " << new_gain; - if (c.bound == AgcConstraint::Bound::LOWER && - new_gain > gain) { - LOG(RPiAgc, Debug) << "Lower bound constraint adopted"; - gain = new_gain, target_Y = new_target_Y; - } else if (c.bound == AgcConstraint::Bound::UPPER && - new_gain < gain) { - LOG(RPiAgc, Debug) << "Upper bound constraint adopted"; - gain = new_gain, target_Y = new_target_Y; - } - } - LOG(RPiAgc, Debug) << "Final gain " << gain << " (target_Y " << target_Y << " ev " - << status_.ev << " base_ev " << config_.base_ev - << ")"; -} - -void Agc::computeTargetExposure(double gain) -{ - if (status_.fixed_shutter && status_.fixed_analogue_gain) { - // When ag and shutter are both fixed, we need to drive the - // total exposure so that we end up with a digital gain of at least - // 1/min_colour_gain. Otherwise we'd desaturate channels causing - // white to go cyan or magenta. - double min_colour_gain = std::min({ awb_.gain_r, awb_.gain_g, awb_.gain_b, 1.0 }); - ASSERT(min_colour_gain != 0.0); - target_.total_exposure = - status_.fixed_shutter * status_.fixed_analogue_gain / min_colour_gain; - } else { - // The statistics reflect the image without digital gain, so the final - // total exposure we're aiming for is: - target_.total_exposure = current_.total_exposure_no_dg * gain; - // The final target exposure is also limited to what the exposure - // mode allows. - Duration max_shutter = status_.fixed_shutter - ? status_.fixed_shutter - : exposure_mode_->shutter.back(); - max_shutter = clipShutter(max_shutter); - Duration max_total_exposure = - max_shutter * - (status_.fixed_analogue_gain != 0.0 - ? status_.fixed_analogue_gain - : exposure_mode_->gain.back()); - target_.total_exposure = std::min(target_.total_exposure, - max_total_exposure); - } - LOG(RPiAgc, Debug) << "Target total_exposure " << target_.total_exposure; -} - -bool Agc::applyDigitalGain(double gain, double target_Y) -{ - double min_colour_gain = std::min({ awb_.gain_r, awb_.gain_g, awb_.gain_b, 1.0 }); - ASSERT(min_colour_gain != 0.0); - double dg = 1.0 / min_colour_gain; - // I think this pipeline subtracts black level and rescales before we - // get the stats, so no need to worry about it. - LOG(RPiAgc, Debug) << "after AWB, target dg " << dg << " gain " << gain - << " target_Y " << target_Y; - // Finally, if we're trying to reduce exposure but the target_Y is - // "close" to 1.0, then the gain computed for that constraint will be - // only slightly less than one, because the measured Y can never be - // larger than 1.0. When this happens, demand a large digital gain so - // that the exposure can be reduced, de-saturating the image much more - // quickly (and we then approach the correct value more quickly from - // below). - bool desaturate = target_Y > config_.fast_reduce_threshold && - gain < sqrt(target_Y); - if (desaturate) - dg /= config_.fast_reduce_threshold; - LOG(RPiAgc, Debug) << "Digital gain " << dg << " desaturate? " << desaturate; - target_.total_exposure_no_dg = target_.total_exposure / dg; - LOG(RPiAgc, Debug) << "Target total_exposure_no_dg " << target_.total_exposure_no_dg; - return desaturate; -} - -void Agc::filterExposure(bool desaturate) -{ - double speed = config_.speed; - // AGC adapts instantly if both shutter and gain are directly specified - // or we're in the startup phase. - if ((status_.fixed_shutter && status_.fixed_analogue_gain) || - frame_count_ <= config_.startup_frames) - speed = 1.0; - if (!filtered_.total_exposure) { - filtered_.total_exposure = target_.total_exposure; - filtered_.total_exposure_no_dg = target_.total_exposure_no_dg; - } else { - // If close to the result go faster, to save making so many - // micro-adjustments on the way. (Make this customisable?) - if (filtered_.total_exposure < 1.2 * target_.total_exposure && - filtered_.total_exposure > 0.8 * target_.total_exposure) - speed = sqrt(speed); - filtered_.total_exposure = speed * target_.total_exposure + - filtered_.total_exposure * (1.0 - speed); - // When desaturing, take a big jump down in exposure_no_dg, - // which we'll hide with digital gain. - if (desaturate) - filtered_.total_exposure_no_dg = - target_.total_exposure_no_dg; - else - filtered_.total_exposure_no_dg = - speed * target_.total_exposure_no_dg + - filtered_.total_exposure_no_dg * (1.0 - speed); - } - // We can't let the no_dg exposure deviate too far below the - // total exposure, as there might not be enough digital gain available - // in the ISP to hide it (which will cause nasty oscillation). - if (filtered_.total_exposure_no_dg < - filtered_.total_exposure * config_.fast_reduce_threshold) - filtered_.total_exposure_no_dg = filtered_.total_exposure * - config_.fast_reduce_threshold; - LOG(RPiAgc, Debug) << "After filtering, total_exposure " << filtered_.total_exposure - << " no dg " << filtered_.total_exposure_no_dg; -} - -void Agc::divideUpExposure() -{ - // Sending the fixed shutter/gain cases through the same code may seem - // unnecessary, but it will make more sense when extend this to cover - // variable aperture. - Duration exposure_value = filtered_.total_exposure_no_dg; - Duration shutter_time; - double analogue_gain; - shutter_time = status_.fixed_shutter - ? status_.fixed_shutter - : exposure_mode_->shutter[0]; - shutter_time = clipShutter(shutter_time); - analogue_gain = status_.fixed_analogue_gain != 0.0 - ? status_.fixed_analogue_gain - : exposure_mode_->gain[0]; - if (shutter_time * analogue_gain < exposure_value) { - for (unsigned int stage = 1; - stage < exposure_mode_->gain.size(); stage++) { - if (!status_.fixed_shutter) { - Duration stage_shutter = - clipShutter(exposure_mode_->shutter[stage]); - if (stage_shutter * analogue_gain >= - exposure_value) { - shutter_time = - exposure_value / analogue_gain; - break; - } - shutter_time = stage_shutter; - } - if (status_.fixed_analogue_gain == 0.0) { - if (exposure_mode_->gain[stage] * - shutter_time >= - exposure_value) { - analogue_gain = - exposure_value / shutter_time; - break; - } - analogue_gain = exposure_mode_->gain[stage]; - } - } - } - LOG(RPiAgc, Debug) << "Divided up shutter and gain are " << shutter_time << " and " - << analogue_gain; - // Finally adjust shutter time for flicker avoidance (require both - // shutter and gain not to be fixed). - if (!status_.fixed_shutter && !status_.fixed_analogue_gain && - status_.flicker_period) { - int flicker_periods = shutter_time / status_.flicker_period; - if (flicker_periods) { - Duration new_shutter_time = flicker_periods * status_.flicker_period; - analogue_gain *= shutter_time / new_shutter_time; - // We should still not allow the ag to go over the - // largest value in the exposure mode. Note that this - // may force more of the total exposure into the digital - // gain as a side-effect. - analogue_gain = std::min(analogue_gain, - exposure_mode_->gain.back()); - shutter_time = new_shutter_time; - } - LOG(RPiAgc, Debug) << "After flicker avoidance, shutter " - << shutter_time << " gain " << analogue_gain; - } - filtered_.shutter = shutter_time; - filtered_.analogue_gain = analogue_gain; -} - -void Agc::writeAndFinish(Metadata *image_metadata, bool desaturate) -{ - status_.total_exposure_value = filtered_.total_exposure; - status_.target_exposure_value = desaturate ? 0s : target_.total_exposure_no_dg; - status_.shutter_time = filtered_.shutter; - status_.analogue_gain = filtered_.analogue_gain; - // Write to metadata as well, in case anyone wants to update the camera - // immediately. - image_metadata->Set("agc.status", status_); - LOG(RPiAgc, Debug) << "Output written, total exposure requested is " - << filtered_.total_exposure; - LOG(RPiAgc, Debug) << "Camera exposure update: shutter time " << filtered_.shutter - << " analogue gain " << filtered_.analogue_gain; -} - -Duration Agc::clipShutter(Duration shutter) -{ - if (max_shutter_) - shutter = std::min(shutter, max_shutter_); - return shutter; -} - -// Register algorithm with the system. -static Algorithm *Create(Controller *controller) -{ - return (Algorithm *)new Agc(controller); -} -static RegisterAlgorithm reg(NAME, &Create); diff --git a/src/ipa/raspberrypi/controller/rpi/agc.hpp b/src/ipa/raspberrypi/controller/rpi/agc.hpp deleted file mode 100644 index c100d312..00000000 --- a/src/ipa/raspberrypi/controller/rpi/agc.hpp +++ /dev/null @@ -1,139 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * agc.hpp - AGC/AEC control algorithm - */ -#pragma once - -#include <vector> -#include <mutex> - -#include <libcamera/base/utils.h> - -#include "../agc_algorithm.hpp" -#include "../agc_status.h" -#include "../pwl.hpp" - -// This is our implementation of AGC. - -// This is the number actually set up by the firmware, not the maximum possible -// number (which is 16). - -#define AGC_STATS_SIZE 15 - -namespace RPiController { - -struct AgcMeteringMode { - double weights[AGC_STATS_SIZE]; - void Read(boost::property_tree::ptree const ¶ms); -}; - -struct AgcExposureMode { - std::vector<libcamera::utils::Duration> shutter; - std::vector<double> gain; - void Read(boost::property_tree::ptree const ¶ms); -}; - -struct AgcConstraint { - enum class Bound { LOWER = 0, UPPER = 1 }; - Bound bound; - double q_lo; - double q_hi; - Pwl Y_target; - void Read(boost::property_tree::ptree const ¶ms); -}; - -typedef std::vector<AgcConstraint> AgcConstraintMode; - -struct AgcConfig { - void Read(boost::property_tree::ptree const ¶ms); - std::map<std::string, AgcMeteringMode> metering_modes; - std::map<std::string, AgcExposureMode> exposure_modes; - std::map<std::string, AgcConstraintMode> constraint_modes; - Pwl Y_target; - double speed; - uint16_t startup_frames; - unsigned int convergence_frames; - double max_change; - double min_change; - double fast_reduce_threshold; - double speed_up_threshold; - std::string default_metering_mode; - std::string default_exposure_mode; - std::string default_constraint_mode; - double base_ev; - libcamera::utils::Duration default_exposure_time; - double default_analogue_gain; -}; - -class Agc : public AgcAlgorithm -{ -public: - Agc(Controller *controller); - char const *Name() const override; - void Read(boost::property_tree::ptree const ¶ms) override; - // AGC handles "pausing" for itself. - bool IsPaused() const override; - void Pause() override; - void Resume() override; - unsigned int GetConvergenceFrames() const override; - void SetEv(double ev) override; - void SetFlickerPeriod(libcamera::utils::Duration flicker_period) override; - void SetMaxShutter(libcamera::utils::Duration max_shutter) override; - void SetFixedShutter(libcamera::utils::Duration fixed_shutter) override; - void SetFixedAnalogueGain(double fixed_analogue_gain) override; - void SetMeteringMode(std::string const &metering_mode_name) override; - void SetExposureMode(std::string const &exposure_mode_name) override; - void SetConstraintMode(std::string const &contraint_mode_name) override; - void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override; - void Prepare(Metadata *image_metadata) override; - void Process(StatisticsPtr &stats, Metadata *image_metadata) override; - -private: - void updateLockStatus(DeviceStatus const &device_status); - AgcConfig config_; - void housekeepConfig(); - void fetchCurrentExposure(Metadata *image_metadata); - void fetchAwbStatus(Metadata *image_metadata); - void computeGain(bcm2835_isp_stats *statistics, Metadata *image_metadata, - double &gain, double &target_Y); - void computeTargetExposure(double gain); - bool applyDigitalGain(double gain, double target_Y); - void filterExposure(bool desaturate); - void divideUpExposure(); - void writeAndFinish(Metadata *image_metadata, bool desaturate); - libcamera::utils::Duration clipShutter(libcamera::utils::Duration shutter); - AgcMeteringMode *metering_mode_; - AgcExposureMode *exposure_mode_; - AgcConstraintMode *constraint_mode_; - uint64_t frame_count_; - AwbStatus awb_; - struct ExposureValues { - ExposureValues(); - - libcamera::utils::Duration shutter; - double analogue_gain; - libcamera::utils::Duration total_exposure; - libcamera::utils::Duration total_exposure_no_dg; // without digital gain - }; - ExposureValues current_; // values for the current frame - ExposureValues target_; // calculate the values we want here - ExposureValues filtered_; // these values are filtered towards target - AgcStatus status_; - int lock_count_; - DeviceStatus last_device_status_; - libcamera::utils::Duration last_target_exposure_; - double last_sensitivity_; // sensitivity of the previous camera mode - // Below here the "settings" that applications can change. - std::string metering_mode_name_; - std::string exposure_mode_name_; - std::string constraint_mode_name_; - double ev_; - libcamera::utils::Duration flicker_period_; - libcamera::utils::Duration max_shutter_; - libcamera::utils::Duration fixed_shutter_; - double fixed_analogue_gain_; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.cpp b/src/ipa/raspberrypi/controller/rpi/alsc.cpp deleted file mode 100644 index e575c14a..00000000 --- a/src/ipa/raspberrypi/controller/rpi/alsc.cpp +++ /dev/null @@ -1,787 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * alsc.cpp - ALSC (auto lens shading correction) control algorithm - */ - -#include <math.h> -#include <numeric> - -#include <libcamera/base/log.h> -#include <libcamera/base/span.h> - -#include "../awb_status.h" -#include "alsc.hpp" - -// Raspberry Pi ALSC (Auto Lens Shading Correction) algorithm. - -using namespace RPiController; -using namespace libcamera; - -LOG_DEFINE_CATEGORY(RPiAlsc) - -#define NAME "rpi.alsc" - -static const int X = ALSC_CELLS_X; -static const int Y = ALSC_CELLS_Y; -static const int XY = X * Y; -static const double INSUFFICIENT_DATA = -1.0; - -Alsc::Alsc(Controller *controller) - : Algorithm(controller) -{ - async_abort_ = async_start_ = async_started_ = async_finished_ = false; - async_thread_ = std::thread(std::bind(&Alsc::asyncFunc, this)); -} - -Alsc::~Alsc() -{ - { - std::lock_guard<std::mutex> lock(mutex_); - async_abort_ = true; - } - async_signal_.notify_one(); - async_thread_.join(); -} - -char const *Alsc::Name() const -{ - return NAME; -} - -static void generate_lut(double *lut, boost::property_tree::ptree const ¶ms) -{ - double cstrength = params.get<double>("corner_strength", 2.0); - if (cstrength <= 1.0) - throw std::runtime_error("Alsc: corner_strength must be > 1.0"); - double asymmetry = params.get<double>("asymmetry", 1.0); - if (asymmetry < 0) - throw std::runtime_error("Alsc: asymmetry must be >= 0"); - double f1 = cstrength - 1, f2 = 1 + sqrt(cstrength); - double R2 = X * Y / 4 * (1 + asymmetry * asymmetry); - int num = 0; - for (int y = 0; y < Y; y++) { - for (int x = 0; x < X; x++) { - double dy = y - Y / 2 + 0.5, - dx = (x - X / 2 + 0.5) * asymmetry; - double r2 = (dx * dx + dy * dy) / R2; - lut[num++] = - (f1 * r2 + f2) * (f1 * r2 + f2) / - (f2 * f2); // this reproduces the cos^4 rule - } - } -} - -static void read_lut(double *lut, boost::property_tree::ptree const ¶ms) -{ - int num = 0; - const int max_num = XY; - for (auto &p : params) { - if (num == max_num) - throw std::runtime_error( - "Alsc: too many entries in LSC table"); - lut[num++] = p.second.get_value<double>(); - } - if (num < max_num) - throw std::runtime_error("Alsc: too few entries in LSC table"); -} - -static void read_calibrations(std::vector<AlscCalibration> &calibrations, - boost::property_tree::ptree const ¶ms, - std::string const &name) -{ - if (params.get_child_optional(name)) { - double last_ct = 0; - for (auto &p : params.get_child(name)) { - double ct = p.second.get<double>("ct"); - if (ct <= last_ct) - throw std::runtime_error( - "Alsc: entries in " + name + - " must be in increasing ct order"); - AlscCalibration calibration; - calibration.ct = last_ct = ct; - boost::property_tree::ptree const &table = - p.second.get_child("table"); - int num = 0; - for (auto it = table.begin(); it != table.end(); it++) { - if (num == XY) - throw std::runtime_error( - "Alsc: too many values for ct " + - std::to_string(ct) + " in " + - name); - calibration.table[num++] = - it->second.get_value<double>(); - } - if (num != XY) - throw std::runtime_error( - "Alsc: too few values for ct " + - std::to_string(ct) + " in " + name); - calibrations.push_back(calibration); - LOG(RPiAlsc, Debug) - << "Read " << name << " calibration for ct " << ct; - } - } -} - -void Alsc::Read(boost::property_tree::ptree const ¶ms) -{ - config_.frame_period = params.get<uint16_t>("frame_period", 12); - config_.startup_frames = params.get<uint16_t>("startup_frames", 10); - config_.speed = params.get<double>("speed", 0.05); - double sigma = params.get<double>("sigma", 0.01); - config_.sigma_Cr = params.get<double>("sigma_Cr", sigma); - config_.sigma_Cb = params.get<double>("sigma_Cb", sigma); - config_.min_count = params.get<double>("min_count", 10.0); - config_.min_G = params.get<uint16_t>("min_G", 50); - config_.omega = params.get<double>("omega", 1.3); - config_.n_iter = params.get<uint32_t>("n_iter", X + Y); - config_.luminance_strength = - params.get<double>("luminance_strength", 1.0); - for (int i = 0; i < XY; i++) - config_.luminance_lut[i] = 1.0; - if (params.get_child_optional("corner_strength")) - generate_lut(config_.luminance_lut, params); - else if (params.get_child_optional("luminance_lut")) - read_lut(config_.luminance_lut, - params.get_child("luminance_lut")); - else - LOG(RPiAlsc, Warning) - << "no luminance table - assume unity everywhere"; - read_calibrations(config_.calibrations_Cr, params, "calibrations_Cr"); - read_calibrations(config_.calibrations_Cb, params, "calibrations_Cb"); - config_.default_ct = params.get<double>("default_ct", 4500.0); - config_.threshold = params.get<double>("threshold", 1e-3); - config_.lambda_bound = params.get<double>("lambda_bound", 0.05); -} - -static double get_ct(Metadata *metadata, double default_ct); -static void get_cal_table(double ct, - std::vector<AlscCalibration> const &calibrations, - double cal_table[XY]); -static void resample_cal_table(double const cal_table_in[XY], - CameraMode const &camera_mode, - double cal_table_out[XY]); -static void compensate_lambdas_for_cal(double const cal_table[XY], - double const old_lambdas[XY], - double new_lambdas[XY]); -static void add_luminance_to_tables(double results[3][Y][X], - double const lambda_r[XY], double lambda_g, - double const lambda_b[XY], - double const luminance_lut[XY], - double luminance_strength); - -void Alsc::Initialise() -{ - frame_count2_ = frame_count_ = frame_phase_ = 0; - first_time_ = true; - ct_ = config_.default_ct; - // The lambdas are initialised in the SwitchMode. -} - -void Alsc::waitForAysncThread() -{ - if (async_started_) { - async_started_ = false; - std::unique_lock<std::mutex> lock(mutex_); - sync_signal_.wait(lock, [&] { - return async_finished_; - }); - async_finished_ = false; - } -} - -static bool compare_modes(CameraMode const &cm0, CameraMode const &cm1) -{ - // Return true if the modes crop from the sensor significantly differently, - // or if the user transform has changed. - if (cm0.transform != cm1.transform) - return true; - int left_diff = abs(cm0.crop_x - cm1.crop_x); - int top_diff = abs(cm0.crop_y - cm1.crop_y); - int right_diff = fabs(cm0.crop_x + cm0.scale_x * cm0.width - - cm1.crop_x - cm1.scale_x * cm1.width); - int bottom_diff = fabs(cm0.crop_y + cm0.scale_y * cm0.height - - cm1.crop_y - cm1.scale_y * cm1.height); - // These thresholds are a rather arbitrary amount chosen to trigger - // when carrying on with the previously calculated tables might be - // worse than regenerating them (but without the adaptive algorithm). - int threshold_x = cm0.sensor_width >> 4; - int threshold_y = cm0.sensor_height >> 4; - return left_diff > threshold_x || right_diff > threshold_x || - top_diff > threshold_y || bottom_diff > threshold_y; -} - -void Alsc::SwitchMode(CameraMode const &camera_mode, - [[maybe_unused]] Metadata *metadata) -{ - // We're going to start over with the tables if there's any "significant" - // change. - bool reset_tables = first_time_ || compare_modes(camera_mode_, camera_mode); - - // Believe the colour temperature from the AWB, if there is one. - ct_ = get_ct(metadata, ct_); - - // Ensure the other thread isn't running while we do this. - waitForAysncThread(); - - camera_mode_ = camera_mode; - - // We must resample the luminance table like we do the others, but it's - // fixed so we can simply do it up front here. - resample_cal_table(config_.luminance_lut, camera_mode_, luminance_table_); - - if (reset_tables) { - // Upon every "table reset", arrange for something sensible to be - // generated. Construct the tables for the previous recorded colour - // temperature. In order to start over from scratch we initialise - // the lambdas, but the rest of this code then echoes the code in - // doAlsc, without the adaptive algorithm. - for (int i = 0; i < XY; i++) - lambda_r_[i] = lambda_b_[i] = 1.0; - double cal_table_r[XY], cal_table_b[XY], cal_table_tmp[XY]; - get_cal_table(ct_, config_.calibrations_Cr, cal_table_tmp); - resample_cal_table(cal_table_tmp, camera_mode_, cal_table_r); - get_cal_table(ct_, config_.calibrations_Cb, cal_table_tmp); - resample_cal_table(cal_table_tmp, camera_mode_, cal_table_b); - compensate_lambdas_for_cal(cal_table_r, lambda_r_, - async_lambda_r_); - compensate_lambdas_for_cal(cal_table_b, lambda_b_, - async_lambda_b_); - add_luminance_to_tables(sync_results_, async_lambda_r_, 1.0, - async_lambda_b_, luminance_table_, - config_.luminance_strength); - memcpy(prev_sync_results_, sync_results_, - sizeof(prev_sync_results_)); - frame_phase_ = config_.frame_period; // run the algo again asap - first_time_ = false; - } -} - -void Alsc::fetchAsyncResults() -{ - LOG(RPiAlsc, Debug) << "Fetch ALSC results"; - async_finished_ = false; - async_started_ = false; - memcpy(sync_results_, async_results_, sizeof(sync_results_)); -} - -double get_ct(Metadata *metadata, double default_ct) -{ - AwbStatus awb_status; - awb_status.temperature_K = default_ct; // in case nothing found - if (metadata->Get("awb.status", awb_status) != 0) - LOG(RPiAlsc, Debug) << "no AWB results found, using " - << awb_status.temperature_K; - else - LOG(RPiAlsc, Debug) << "AWB results found, using " - << awb_status.temperature_K; - return awb_status.temperature_K; -} - -static void copy_stats(bcm2835_isp_stats_region regions[XY], StatisticsPtr &stats, - AlscStatus const &status) -{ - bcm2835_isp_stats_region *input_regions = stats->awb_stats; - double *r_table = (double *)status.r; - double *g_table = (double *)status.g; - double *b_table = (double *)status.b; - for (int i = 0; i < XY; i++) { - regions[i].r_sum = input_regions[i].r_sum / r_table[i]; - regions[i].g_sum = input_regions[i].g_sum / g_table[i]; - regions[i].b_sum = input_regions[i].b_sum / b_table[i]; - regions[i].counted = input_regions[i].counted; - // (don't care about the uncounted value) - } -} - -void Alsc::restartAsync(StatisticsPtr &stats, Metadata *image_metadata) -{ - LOG(RPiAlsc, Debug) << "Starting ALSC calculation"; - // Get the current colour temperature. It's all we need from the - // metadata. Default to the last CT value (which could be the default). - ct_ = get_ct(image_metadata, ct_); - // We have to copy the statistics here, dividing out our best guess of - // the LSC table that the pipeline applied to them. - AlscStatus alsc_status; - if (image_metadata->Get("alsc.status", alsc_status) != 0) { - LOG(RPiAlsc, Warning) - << "No ALSC status found for applied gains!"; - for (int y = 0; y < Y; y++) - for (int x = 0; x < X; x++) { - alsc_status.r[y][x] = 1.0; - alsc_status.g[y][x] = 1.0; - alsc_status.b[y][x] = 1.0; - } - } - copy_stats(statistics_, stats, alsc_status); - frame_phase_ = 0; - async_started_ = true; - { - std::lock_guard<std::mutex> lock(mutex_); - async_start_ = true; - } - async_signal_.notify_one(); -} - -void Alsc::Prepare(Metadata *image_metadata) -{ - // Count frames since we started, and since we last poked the async - // thread. - if (frame_count_ < (int)config_.startup_frames) - frame_count_++; - double speed = frame_count_ < (int)config_.startup_frames - ? 1.0 - : config_.speed; - LOG(RPiAlsc, Debug) - << "frame_count " << frame_count_ << " speed " << speed; - { - std::unique_lock<std::mutex> lock(mutex_); - if (async_started_ && async_finished_) - fetchAsyncResults(); - } - // Apply IIR filter to results and program into the pipeline. - double *ptr = (double *)sync_results_, - *pptr = (double *)prev_sync_results_; - for (unsigned int i = 0; - i < sizeof(sync_results_) / sizeof(double); i++) - pptr[i] = speed * ptr[i] + (1.0 - speed) * pptr[i]; - // Put output values into status metadata. - AlscStatus status; - memcpy(status.r, prev_sync_results_[0], sizeof(status.r)); - memcpy(status.g, prev_sync_results_[1], sizeof(status.g)); - memcpy(status.b, prev_sync_results_[2], sizeof(status.b)); - image_metadata->Set("alsc.status", status); -} - -void Alsc::Process(StatisticsPtr &stats, Metadata *image_metadata) -{ - // Count frames since we started, and since we last poked the async - // thread. - if (frame_phase_ < (int)config_.frame_period) - frame_phase_++; - if (frame_count2_ < (int)config_.startup_frames) - frame_count2_++; - LOG(RPiAlsc, Debug) << "frame_phase " << frame_phase_; - if (frame_phase_ >= (int)config_.frame_period || - frame_count2_ < (int)config_.startup_frames) { - if (async_started_ == false) - restartAsync(stats, image_metadata); - } -} - -void Alsc::asyncFunc() -{ - while (true) { - { - std::unique_lock<std::mutex> lock(mutex_); - async_signal_.wait(lock, [&] { - return async_start_ || async_abort_; - }); - async_start_ = false; - if (async_abort_) - break; - } - doAlsc(); - { - std::lock_guard<std::mutex> lock(mutex_); - async_finished_ = true; - } - sync_signal_.notify_one(); - } -} - -void get_cal_table(double ct, std::vector<AlscCalibration> const &calibrations, - double cal_table[XY]) -{ - if (calibrations.empty()) { - for (int i = 0; i < XY; i++) - cal_table[i] = 1.0; - LOG(RPiAlsc, Debug) << "no calibrations found"; - } else if (ct <= calibrations.front().ct) { - memcpy(cal_table, calibrations.front().table, - XY * sizeof(double)); - LOG(RPiAlsc, Debug) << "using calibration for " - << calibrations.front().ct; - } else if (ct >= calibrations.back().ct) { - memcpy(cal_table, calibrations.back().table, - XY * sizeof(double)); - LOG(RPiAlsc, Debug) << "using calibration for " - << calibrations.back().ct; - } else { - int idx = 0; - while (ct > calibrations[idx + 1].ct) - idx++; - double ct0 = calibrations[idx].ct, - ct1 = calibrations[idx + 1].ct; - LOG(RPiAlsc, Debug) - << "ct is " << ct << ", interpolating between " - << ct0 << " and " << ct1; - for (int i = 0; i < XY; i++) - cal_table[i] = - (calibrations[idx].table[i] * (ct1 - ct) + - calibrations[idx + 1].table[i] * (ct - ct0)) / - (ct1 - ct0); - } -} - -void resample_cal_table(double const cal_table_in[XY], - CameraMode const &camera_mode, double cal_table_out[XY]) -{ - // Precalculate and cache the x sampling locations and phases to save - // recomputing them on every row. - int x_lo[X], x_hi[X]; - double xf[X]; - double scale_x = camera_mode.sensor_width / - (camera_mode.width * camera_mode.scale_x); - double x_off = camera_mode.crop_x / (double)camera_mode.sensor_width; - double x = .5 / scale_x + x_off * X - .5; - double x_inc = 1 / scale_x; - for (int i = 0; i < X; i++, x += x_inc) { - x_lo[i] = floor(x); - xf[i] = x - x_lo[i]; - x_hi[i] = std::min(x_lo[i] + 1, X - 1); - x_lo[i] = std::max(x_lo[i], 0); - if (!!(camera_mode.transform & libcamera::Transform::HFlip)) { - x_lo[i] = X - 1 - x_lo[i]; - x_hi[i] = X - 1 - x_hi[i]; - } - } - // Now march over the output table generating the new values. - double scale_y = camera_mode.sensor_height / - (camera_mode.height * camera_mode.scale_y); - double y_off = camera_mode.crop_y / (double)camera_mode.sensor_height; - double y = .5 / scale_y + y_off * Y - .5; - double y_inc = 1 / scale_y; - for (int j = 0; j < Y; j++, y += y_inc) { - int y_lo = floor(y); - double yf = y - y_lo; - int y_hi = std::min(y_lo + 1, Y - 1); - y_lo = std::max(y_lo, 0); - if (!!(camera_mode.transform & libcamera::Transform::VFlip)) { - y_lo = Y - 1 - y_lo; - y_hi = Y - 1 - y_hi; - } - double const *row_above = cal_table_in + X * y_lo; - double const *row_below = cal_table_in + X * y_hi; - for (int i = 0; i < X; i++) { - double above = row_above[x_lo[i]] * (1 - xf[i]) + - row_above[x_hi[i]] * xf[i]; - double below = row_below[x_lo[i]] * (1 - xf[i]) + - row_below[x_hi[i]] * xf[i]; - *(cal_table_out++) = above * (1 - yf) + below * yf; - } - } -} - -// Calculate chrominance statistics (R/G and B/G) for each region. -static_assert(XY == AWB_REGIONS, "ALSC/AWB statistics region mismatch"); -static void calculate_Cr_Cb(bcm2835_isp_stats_region *awb_region, double Cr[XY], - double Cb[XY], uint32_t min_count, uint16_t min_G) -{ - for (int i = 0; i < XY; i++) { - bcm2835_isp_stats_region &zone = awb_region[i]; - if (zone.counted <= min_count || - zone.g_sum / zone.counted <= min_G) { - Cr[i] = Cb[i] = INSUFFICIENT_DATA; - continue; - } - Cr[i] = zone.r_sum / (double)zone.g_sum; - Cb[i] = zone.b_sum / (double)zone.g_sum; - } -} - -static void apply_cal_table(double const cal_table[XY], double C[XY]) -{ - for (int i = 0; i < XY; i++) - if (C[i] != INSUFFICIENT_DATA) - C[i] *= cal_table[i]; -} - -void compensate_lambdas_for_cal(double const cal_table[XY], - double const old_lambdas[XY], - double new_lambdas[XY]) -{ - double min_new_lambda = std::numeric_limits<double>::max(); - for (int i = 0; i < XY; i++) { - new_lambdas[i] = old_lambdas[i] * cal_table[i]; - min_new_lambda = std::min(min_new_lambda, new_lambdas[i]); - } - for (int i = 0; i < XY; i++) - new_lambdas[i] /= min_new_lambda; -} - -[[maybe_unused]] static void print_cal_table(double const C[XY]) -{ - printf("table: [\n"); - for (int j = 0; j < Y; j++) { - for (int i = 0; i < X; i++) { - printf("%5.3f", 1.0 / C[j * X + i]); - if (i != X - 1 || j != Y - 1) - printf(","); - } - printf("\n"); - } - printf("]\n"); -} - -// Compute weight out of 1.0 which reflects how similar we wish to make the -// colours of these two regions. -static double compute_weight(double C_i, double C_j, double sigma) -{ - if (C_i == INSUFFICIENT_DATA || C_j == INSUFFICIENT_DATA) - return 0; - double diff = (C_i - C_j) / sigma; - return exp(-diff * diff / 2); -} - -// Compute all weights. -static void compute_W(double const C[XY], double sigma, double W[XY][4]) -{ - for (int i = 0; i < XY; i++) { - // Start with neighbour above and go clockwise. - W[i][0] = i >= X ? compute_weight(C[i], C[i - X], sigma) : 0; - W[i][1] = i % X < X - 1 ? compute_weight(C[i], C[i + 1], sigma) - : 0; - W[i][2] = - i < XY - X ? compute_weight(C[i], C[i + X], sigma) : 0; - W[i][3] = i % X ? compute_weight(C[i], C[i - 1], sigma) : 0; - } -} - -// Compute M, the large but sparse matrix such that M * lambdas = 0. -static void construct_M(double const C[XY], double const W[XY][4], - double M[XY][4]) -{ - double epsilon = 0.001; - for (int i = 0; i < XY; i++) { - // Note how, if C[i] == INSUFFICIENT_DATA, the weights will all - // be zero so the equation is still set up correctly. - int m = !!(i >= X) + !!(i % X < X - 1) + !!(i < XY - X) + - !!(i % X); // total number of neighbours - // we'll divide the diagonal out straight away - double diagonal = - (epsilon + W[i][0] + W[i][1] + W[i][2] + W[i][3]) * - C[i]; - M[i][0] = i >= X ? (W[i][0] * C[i - X] + epsilon / m * C[i]) / - diagonal - : 0; - M[i][1] = i % X < X - 1 - ? (W[i][1] * C[i + 1] + epsilon / m * C[i]) / - diagonal - : 0; - M[i][2] = i < XY - X - ? (W[i][2] * C[i + X] + epsilon / m * C[i]) / - diagonal - : 0; - M[i][3] = i % X ? (W[i][3] * C[i - 1] + epsilon / m * C[i]) / - diagonal - : 0; - } -} - -// In the compute_lambda_ functions, note that the matrix coefficients for the -// left/right neighbours are zero down the left/right edges, so we don't need -// need to test the i value to exclude them. -static double compute_lambda_bottom(int i, double const M[XY][4], - double lambda[XY]) -{ - return M[i][1] * lambda[i + 1] + M[i][2] * lambda[i + X] + - M[i][3] * lambda[i - 1]; -} -static double compute_lambda_bottom_start(int i, double const M[XY][4], - double lambda[XY]) -{ - return M[i][1] * lambda[i + 1] + M[i][2] * lambda[i + X]; -} -static double compute_lambda_interior(int i, double const M[XY][4], - double lambda[XY]) -{ - return M[i][0] * lambda[i - X] + M[i][1] * lambda[i + 1] + - M[i][2] * lambda[i + X] + M[i][3] * lambda[i - 1]; -} -static double compute_lambda_top(int i, double const M[XY][4], - double lambda[XY]) -{ - return M[i][0] * lambda[i - X] + M[i][1] * lambda[i + 1] + - M[i][3] * lambda[i - 1]; -} -static double compute_lambda_top_end(int i, double const M[XY][4], - double lambda[XY]) -{ - return M[i][0] * lambda[i - X] + M[i][3] * lambda[i - 1]; -} - -// Gauss-Seidel iteration with over-relaxation. -static double gauss_seidel2_SOR(double const M[XY][4], double omega, - double lambda[XY], double lambda_bound) -{ - const double min = 1 - lambda_bound, max = 1 + lambda_bound; - double old_lambda[XY]; - int i; - for (i = 0; i < XY; i++) - old_lambda[i] = lambda[i]; - lambda[0] = compute_lambda_bottom_start(0, M, lambda); - lambda[0] = std::clamp(lambda[0], min, max); - for (i = 1; i < X; i++) { - lambda[i] = compute_lambda_bottom(i, M, lambda); - lambda[i] = std::clamp(lambda[i], min, max); - } - for (; i < XY - X; i++) { - lambda[i] = compute_lambda_interior(i, M, lambda); - lambda[i] = std::clamp(lambda[i], min, max); - } - for (; i < XY - 1; i++) { - lambda[i] = compute_lambda_top(i, M, lambda); - lambda[i] = std::clamp(lambda[i], min, max); - } - lambda[i] = compute_lambda_top_end(i, M, lambda); - lambda[i] = std::clamp(lambda[i], min, max); - // Also solve the system from bottom to top, to help spread the updates - // better. - lambda[i] = compute_lambda_top_end(i, M, lambda); - lambda[i] = std::clamp(lambda[i], min, max); - for (i = XY - 2; i >= XY - X; i--) { - lambda[i] = compute_lambda_top(i, M, lambda); - lambda[i] = std::clamp(lambda[i], min, max); - } - for (; i >= X; i--) { - lambda[i] = compute_lambda_interior(i, M, lambda); - lambda[i] = std::clamp(lambda[i], min, max); - } - for (; i >= 1; i--) { - lambda[i] = compute_lambda_bottom(i, M, lambda); - lambda[i] = std::clamp(lambda[i], min, max); - } - lambda[0] = compute_lambda_bottom_start(0, M, lambda); - lambda[0] = std::clamp(lambda[0], min, max); - double max_diff = 0; - for (i = 0; i < XY; i++) { - lambda[i] = old_lambda[i] + (lambda[i] - old_lambda[i]) * omega; - if (fabs(lambda[i] - old_lambda[i]) > fabs(max_diff)) - max_diff = lambda[i] - old_lambda[i]; - } - return max_diff; -} - -// Normalise the values so that the smallest value is 1. -static void normalise(double *ptr, size_t n) -{ - double minval = ptr[0]; - for (size_t i = 1; i < n; i++) - minval = std::min(minval, ptr[i]); - for (size_t i = 0; i < n; i++) - ptr[i] /= minval; -} - -// Rescale the values so that the average value is 1. -static void reaverage(Span<double> data) -{ - double sum = std::accumulate(data.begin(), data.end(), 0.0); - double ratio = 1 / (sum / data.size()); - for (double &d : data) - d *= ratio; -} - -static void run_matrix_iterations(double const C[XY], double lambda[XY], - double const W[XY][4], double omega, - int n_iter, double threshold, double lambda_bound) -{ - double M[XY][4]; - construct_M(C, W, M); - double last_max_diff = std::numeric_limits<double>::max(); - for (int i = 0; i < n_iter; i++) { - double max_diff = fabs(gauss_seidel2_SOR(M, omega, lambda, lambda_bound)); - if (max_diff < threshold) { - LOG(RPiAlsc, Debug) - << "Stop after " << i + 1 << " iterations"; - break; - } - // this happens very occasionally (so make a note), though - // doesn't seem to matter - if (max_diff > last_max_diff) - LOG(RPiAlsc, Debug) - << "Iteration " << i << ": max_diff gone up " - << last_max_diff << " to " << max_diff; - last_max_diff = max_diff; - } - // We're going to normalise the lambdas so the total average is 1. - reaverage({ lambda, XY }); -} - -static void add_luminance_rb(double result[XY], double const lambda[XY], - double const luminance_lut[XY], - double luminance_strength) -{ - for (int i = 0; i < XY; i++) - result[i] = lambda[i] * - ((luminance_lut[i] - 1) * luminance_strength + 1); -} - -static void add_luminance_g(double result[XY], double lambda, - double const luminance_lut[XY], - double luminance_strength) -{ - for (int i = 0; i < XY; i++) - result[i] = lambda * - ((luminance_lut[i] - 1) * luminance_strength + 1); -} - -void add_luminance_to_tables(double results[3][Y][X], double const lambda_r[XY], - double lambda_g, double const lambda_b[XY], - double const luminance_lut[XY], - double luminance_strength) -{ - add_luminance_rb((double *)results[0], lambda_r, luminance_lut, - luminance_strength); - add_luminance_g((double *)results[1], lambda_g, luminance_lut, - luminance_strength); - add_luminance_rb((double *)results[2], lambda_b, luminance_lut, - luminance_strength); - normalise((double *)results, 3 * XY); -} - -void Alsc::doAlsc() -{ - double Cr[XY], Cb[XY], Wr[XY][4], Wb[XY][4], cal_table_r[XY], - cal_table_b[XY], cal_table_tmp[XY]; - // Calculate our R/B ("Cr"/"Cb") colour statistics, and assess which are - // usable. - calculate_Cr_Cb(statistics_, Cr, Cb, config_.min_count, config_.min_G); - // Fetch the new calibrations (if any) for this CT. Resample them in - // case the camera mode is not full-frame. - get_cal_table(ct_, config_.calibrations_Cr, cal_table_tmp); - resample_cal_table(cal_table_tmp, camera_mode_, cal_table_r); - get_cal_table(ct_, config_.calibrations_Cb, cal_table_tmp); - resample_cal_table(cal_table_tmp, camera_mode_, cal_table_b); - // You could print out the cal tables for this image here, if you're - // tuning the algorithm... - // Apply any calibration to the statistics, so the adaptive algorithm - // makes only the extra adjustments. - apply_cal_table(cal_table_r, Cr); - apply_cal_table(cal_table_b, Cb); - // Compute weights between zones. - compute_W(Cr, config_.sigma_Cr, Wr); - compute_W(Cb, config_.sigma_Cb, Wb); - // Run Gauss-Seidel iterations over the resulting matrix, for R and B. - run_matrix_iterations(Cr, lambda_r_, Wr, config_.omega, config_.n_iter, - config_.threshold, config_.lambda_bound); - run_matrix_iterations(Cb, lambda_b_, Wb, config_.omega, config_.n_iter, - config_.threshold, config_.lambda_bound); - // Fold the calibrated gains into our final lambda values. (Note that on - // the next run, we re-start with the lambda values that don't have the - // calibration gains included.) - compensate_lambdas_for_cal(cal_table_r, lambda_r_, async_lambda_r_); - compensate_lambdas_for_cal(cal_table_b, lambda_b_, async_lambda_b_); - // Fold in the luminance table at the appropriate strength. - add_luminance_to_tables(async_results_, async_lambda_r_, 1.0, - async_lambda_b_, luminance_table_, - config_.luminance_strength); -} - -// Register algorithm with the system. -static Algorithm *Create(Controller *controller) -{ - return (Algorithm *)new Alsc(controller); -} -static RegisterAlgorithm reg(NAME, &Create); diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.hpp b/src/ipa/raspberrypi/controller/rpi/alsc.hpp deleted file mode 100644 index d1dbe0d1..00000000 --- a/src/ipa/raspberrypi/controller/rpi/alsc.hpp +++ /dev/null @@ -1,106 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * alsc.hpp - ALSC (auto lens shading correction) control algorithm - */ -#pragma once - -#include <mutex> -#include <condition_variable> -#include <thread> - -#include "../algorithm.hpp" -#include "../alsc_status.h" - -namespace RPiController { - -// Algorithm to generate automagic LSC (Lens Shading Correction) tables. - -struct AlscCalibration { - double ct; - double table[ALSC_CELLS_X * ALSC_CELLS_Y]; -}; - -struct AlscConfig { - // Only repeat the ALSC calculation every "this many" frames - uint16_t frame_period; - // number of initial frames for which speed taken as 1.0 (maximum) - uint16_t startup_frames; - // IIR filter speed applied to algorithm results - double speed; - double sigma_Cr; - double sigma_Cb; - double min_count; - uint16_t min_G; - double omega; - uint32_t n_iter; - double luminance_lut[ALSC_CELLS_X * ALSC_CELLS_Y]; - double luminance_strength; - std::vector<AlscCalibration> calibrations_Cr; - std::vector<AlscCalibration> calibrations_Cb; - double default_ct; // colour temperature if no metadata found - double threshold; // iteration termination threshold - double lambda_bound; // upper/lower bound for lambda from a value of 1 -}; - -class Alsc : public Algorithm -{ -public: - Alsc(Controller *controller = NULL); - ~Alsc(); - char const *Name() const override; - void Initialise() override; - void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override; - void Read(boost::property_tree::ptree const ¶ms) override; - void Prepare(Metadata *image_metadata) override; - void Process(StatisticsPtr &stats, Metadata *image_metadata) override; - -private: - // configuration is read-only, and available to both threads - AlscConfig config_; - bool first_time_; - CameraMode camera_mode_; - double luminance_table_[ALSC_CELLS_X * ALSC_CELLS_Y]; - std::thread async_thread_; - void asyncFunc(); // asynchronous thread function - std::mutex mutex_; - // condvar for async thread to wait on - std::condition_variable async_signal_; - // condvar for synchronous thread to wait on - std::condition_variable sync_signal_; - // for sync thread to check if async thread finished (requires mutex) - bool async_finished_; - // for async thread to check if it's been told to run (requires mutex) - bool async_start_; - // for async thread to check if it's been told to quit (requires mutex) - bool async_abort_; - - // The following are only for the synchronous thread to use: - // for sync thread to note its has asked async thread to run - bool async_started_; - // counts up to frame_period before restarting the async thread - int frame_phase_; - // counts up to startup_frames - int frame_count_; - // counts up to startup_frames for Process function - int frame_count2_; - double sync_results_[3][ALSC_CELLS_Y][ALSC_CELLS_X]; - double prev_sync_results_[3][ALSC_CELLS_Y][ALSC_CELLS_X]; - void waitForAysncThread(); - // The following are for the asynchronous thread to use, though the main - // thread can set/reset them if the async thread is known to be idle: - void restartAsync(StatisticsPtr &stats, Metadata *image_metadata); - // copy out the results from the async thread so that it can be restarted - void fetchAsyncResults(); - double ct_; - bcm2835_isp_stats_region statistics_[ALSC_CELLS_Y * ALSC_CELLS_X]; - double async_results_[3][ALSC_CELLS_Y][ALSC_CELLS_X]; - double async_lambda_r_[ALSC_CELLS_X * ALSC_CELLS_Y]; - double async_lambda_b_[ALSC_CELLS_X * ALSC_CELLS_Y]; - void doAlsc(); - double lambda_r_[ALSC_CELLS_X * ALSC_CELLS_Y]; - double lambda_b_[ALSC_CELLS_X * ALSC_CELLS_Y]; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/rpi/awb.cpp b/src/ipa/raspberrypi/controller/rpi/awb.cpp deleted file mode 100644 index d4c93447..00000000 --- a/src/ipa/raspberrypi/controller/rpi/awb.cpp +++ /dev/null @@ -1,667 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * awb.cpp - AWB control algorithm - */ - -#include <libcamera/base/log.h> - -#include "../lux_status.h" - -#include "awb.hpp" - -using namespace RPiController; -using namespace libcamera; - -LOG_DEFINE_CATEGORY(RPiAwb) - -#define NAME "rpi.awb" - -#define AWB_STATS_SIZE_X DEFAULT_AWB_REGIONS_X -#define AWB_STATS_SIZE_Y DEFAULT_AWB_REGIONS_Y - -// todo - the locking in this algorithm needs some tidying up as has been done -// elsewhere (ALSC and AGC). - -void AwbMode::Read(boost::property_tree::ptree const ¶ms) -{ - ct_lo = params.get<double>("lo"); - ct_hi = params.get<double>("hi"); -} - -void AwbPrior::Read(boost::property_tree::ptree const ¶ms) -{ - lux = params.get<double>("lux"); - prior.Read(params.get_child("prior")); -} - -static void read_ct_curve(Pwl &ct_r, Pwl &ct_b, - boost::property_tree::ptree const ¶ms) -{ - int num = 0; - for (auto it = params.begin(); it != params.end(); it++) { - double ct = it->second.get_value<double>(); - assert(it == params.begin() || ct != ct_r.Domain().end); - if (++it == params.end()) - throw std::runtime_error( - "AwbConfig: incomplete CT curve entry"); - ct_r.Append(ct, it->second.get_value<double>()); - if (++it == params.end()) - throw std::runtime_error( - "AwbConfig: incomplete CT curve entry"); - ct_b.Append(ct, it->second.get_value<double>()); - num++; - } - if (num < 2) - throw std::runtime_error( - "AwbConfig: insufficient points in CT curve"); -} - -void AwbConfig::Read(boost::property_tree::ptree const ¶ms) -{ - bayes = params.get<int>("bayes", 1); - frame_period = params.get<uint16_t>("frame_period", 10); - startup_frames = params.get<uint16_t>("startup_frames", 10); - convergence_frames = params.get<unsigned int>("convergence_frames", 3); - speed = params.get<double>("speed", 0.05); - if (params.get_child_optional("ct_curve")) - read_ct_curve(ct_r, ct_b, params.get_child("ct_curve")); - if (params.get_child_optional("priors")) { - for (auto &p : params.get_child("priors")) { - AwbPrior prior; - prior.Read(p.second); - if (!priors.empty() && prior.lux <= priors.back().lux) - throw std::runtime_error( - "AwbConfig: Prior must be ordered in increasing lux value"); - priors.push_back(prior); - } - if (priors.empty()) - throw std::runtime_error( - "AwbConfig: no AWB priors configured"); - } - if (params.get_child_optional("modes")) { - for (auto &p : params.get_child("modes")) { - modes[p.first].Read(p.second); - if (default_mode == nullptr) - default_mode = &modes[p.first]; - } - if (default_mode == nullptr) - throw std::runtime_error( - "AwbConfig: no AWB modes configured"); - } - min_pixels = params.get<double>("min_pixels", 16.0); - min_G = params.get<uint16_t>("min_G", 32); - min_regions = params.get<uint32_t>("min_regions", 10); - delta_limit = params.get<double>("delta_limit", 0.2); - coarse_step = params.get<double>("coarse_step", 0.2); - transverse_pos = params.get<double>("transverse_pos", 0.01); - transverse_neg = params.get<double>("transverse_neg", 0.01); - if (transverse_pos <= 0 || transverse_neg <= 0) - throw std::runtime_error( - "AwbConfig: transverse_pos/neg must be > 0"); - sensitivity_r = params.get<double>("sensitivity_r", 1.0); - sensitivity_b = params.get<double>("sensitivity_b", 1.0); - if (bayes) { - if (ct_r.Empty() || ct_b.Empty() || priors.empty() || - default_mode == nullptr) { - LOG(RPiAwb, Warning) - << "Bayesian AWB mis-configured - switch to Grey method"; - bayes = false; - } - } - fast = params.get<int>( - "fast", bayes); // default to fast for Bayesian, otherwise slow - whitepoint_r = params.get<double>("whitepoint_r", 0.0); - whitepoint_b = params.get<double>("whitepoint_b", 0.0); - if (bayes == false) - sensitivity_r = sensitivity_b = - 1.0; // nor do sensitivities make any sense -} - -Awb::Awb(Controller *controller) - : AwbAlgorithm(controller) -{ - async_abort_ = async_start_ = async_started_ = async_finished_ = false; - mode_ = nullptr; - manual_r_ = manual_b_ = 0.0; - first_switch_mode_ = true; - async_thread_ = std::thread(std::bind(&Awb::asyncFunc, this)); -} - -Awb::~Awb() -{ - { - std::lock_guard<std::mutex> lock(mutex_); - async_abort_ = true; - } - async_signal_.notify_one(); - async_thread_.join(); -} - -char const *Awb::Name() const -{ - return NAME; -} - -void Awb::Read(boost::property_tree::ptree const ¶ms) -{ - config_.Read(params); -} - -void Awb::Initialise() -{ - frame_count_ = frame_phase_ = 0; - // Put something sane into the status that we are filtering towards, - // just in case the first few frames don't have anything meaningful in - // them. - if (!config_.ct_r.Empty() && !config_.ct_b.Empty()) { - sync_results_.temperature_K = config_.ct_r.Domain().Clip(4000); - sync_results_.gain_r = - 1.0 / config_.ct_r.Eval(sync_results_.temperature_K); - sync_results_.gain_g = 1.0; - sync_results_.gain_b = - 1.0 / config_.ct_b.Eval(sync_results_.temperature_K); - } else { - // random values just to stop the world blowing up - sync_results_.temperature_K = 4500; - sync_results_.gain_r = sync_results_.gain_g = - sync_results_.gain_b = 1.0; - } - prev_sync_results_ = sync_results_; - async_results_ = sync_results_; -} - -bool Awb::IsPaused() const -{ - return false; -} - -void Awb::Pause() -{ - // "Pause" by fixing everything to the most recent values. - manual_r_ = sync_results_.gain_r = prev_sync_results_.gain_r; - manual_b_ = sync_results_.gain_b = prev_sync_results_.gain_b; - sync_results_.gain_g = prev_sync_results_.gain_g; - sync_results_.temperature_K = prev_sync_results_.temperature_K; -} - -void Awb::Resume() -{ - manual_r_ = 0.0; - manual_b_ = 0.0; -} - -unsigned int Awb::GetConvergenceFrames() const -{ - // If not in auto mode, there is no convergence - // to happen, so no need to drop any frames - return zero. - if (!isAutoEnabled()) - return 0; - else - return config_.convergence_frames; -} - -void Awb::SetMode(std::string const &mode_name) -{ - mode_name_ = mode_name; -} - -void Awb::SetManualGains(double manual_r, double manual_b) -{ - // If any of these are 0.0, we swich back to auto. - manual_r_ = manual_r; - manual_b_ = manual_b; - // If not in auto mode, set these values into the sync_results which - // means that Prepare() will adopt them immediately. - if (!isAutoEnabled()) { - sync_results_.gain_r = prev_sync_results_.gain_r = manual_r_; - sync_results_.gain_g = prev_sync_results_.gain_g = 1.0; - sync_results_.gain_b = prev_sync_results_.gain_b = manual_b_; - } -} - -void Awb::SwitchMode([[maybe_unused]] CameraMode const &camera_mode, - Metadata *metadata) -{ - // On the first mode switch we'll have no meaningful colour - // temperature, so try to dead reckon one if in manual mode. - if (!isAutoEnabled() && first_switch_mode_ && config_.bayes) { - Pwl ct_r_inverse = config_.ct_r.Inverse(); - Pwl ct_b_inverse = config_.ct_b.Inverse(); - double ct_r = ct_r_inverse.Eval(ct_r_inverse.Domain().Clip(1 / manual_r_)); - double ct_b = ct_b_inverse.Eval(ct_b_inverse.Domain().Clip(1 / manual_b_)); - prev_sync_results_.temperature_K = (ct_r + ct_b) / 2; - sync_results_.temperature_K = prev_sync_results_.temperature_K; - } - // Let other algorithms know the current white balance values. - metadata->Set("awb.status", prev_sync_results_); - first_switch_mode_ = false; -} - -bool Awb::isAutoEnabled() const -{ - return manual_r_ == 0.0 || manual_b_ == 0.0; -} - -void Awb::fetchAsyncResults() -{ - LOG(RPiAwb, Debug) << "Fetch AWB results"; - async_finished_ = false; - async_started_ = false; - // It's possible manual gains could be set even while the async - // thread was running, so only copy the results if still in auto mode. - if (isAutoEnabled()) - sync_results_ = async_results_; -} - -void Awb::restartAsync(StatisticsPtr &stats, double lux) -{ - LOG(RPiAwb, Debug) << "Starting AWB calculation"; - // this makes a new reference which belongs to the asynchronous thread - statistics_ = stats; - // store the mode as it could technically change - auto m = config_.modes.find(mode_name_); - mode_ = m != config_.modes.end() - ? &m->second - : (mode_ == nullptr ? config_.default_mode : mode_); - lux_ = lux; - frame_phase_ = 0; - async_started_ = true; - size_t len = mode_name_.copy(async_results_.mode, - sizeof(async_results_.mode) - 1); - async_results_.mode[len] = '\0'; - { - std::lock_guard<std::mutex> lock(mutex_); - async_start_ = true; - } - async_signal_.notify_one(); -} - -void Awb::Prepare(Metadata *image_metadata) -{ - if (frame_count_ < (int)config_.startup_frames) - frame_count_++; - double speed = frame_count_ < (int)config_.startup_frames - ? 1.0 - : config_.speed; - LOG(RPiAwb, Debug) - << "frame_count " << frame_count_ << " speed " << speed; - { - std::unique_lock<std::mutex> lock(mutex_); - if (async_started_ && async_finished_) - fetchAsyncResults(); - } - // Finally apply IIR filter to results and put into metadata. - memcpy(prev_sync_results_.mode, sync_results_.mode, - sizeof(prev_sync_results_.mode)); - prev_sync_results_.temperature_K = - speed * sync_results_.temperature_K + - (1.0 - speed) * prev_sync_results_.temperature_K; - prev_sync_results_.gain_r = speed * sync_results_.gain_r + - (1.0 - speed) * prev_sync_results_.gain_r; - prev_sync_results_.gain_g = speed * sync_results_.gain_g + - (1.0 - speed) * prev_sync_results_.gain_g; - prev_sync_results_.gain_b = speed * sync_results_.gain_b + - (1.0 - speed) * prev_sync_results_.gain_b; - image_metadata->Set("awb.status", prev_sync_results_); - LOG(RPiAwb, Debug) - << "Using AWB gains r " << prev_sync_results_.gain_r << " g " - << prev_sync_results_.gain_g << " b " - << prev_sync_results_.gain_b; -} - -void Awb::Process(StatisticsPtr &stats, Metadata *image_metadata) -{ - // Count frames since we last poked the async thread. - if (frame_phase_ < (int)config_.frame_period) - frame_phase_++; - LOG(RPiAwb, Debug) << "frame_phase " << frame_phase_; - // We do not restart the async thread if we're not in auto mode. - if (isAutoEnabled() && - (frame_phase_ >= (int)config_.frame_period || - frame_count_ < (int)config_.startup_frames)) { - // Update any settings and any image metadata that we need. - struct LuxStatus lux_status = {}; - lux_status.lux = 400; // in case no metadata - if (image_metadata->Get("lux.status", lux_status) != 0) - LOG(RPiAwb, Debug) << "No lux metadata found"; - LOG(RPiAwb, Debug) << "Awb lux value is " << lux_status.lux; - - if (async_started_ == false) - restartAsync(stats, lux_status.lux); - } -} - -void Awb::asyncFunc() -{ - while (true) { - { - std::unique_lock<std::mutex> lock(mutex_); - async_signal_.wait(lock, [&] { - return async_start_ || async_abort_; - }); - async_start_ = false; - if (async_abort_) - break; - } - doAwb(); - { - std::lock_guard<std::mutex> lock(mutex_); - async_finished_ = true; - } - sync_signal_.notify_one(); - } -} - -static void generate_stats(std::vector<Awb::RGB> &zones, - bcm2835_isp_stats_region *stats, double min_pixels, - double min_G) -{ - for (int i = 0; i < AWB_STATS_SIZE_X * AWB_STATS_SIZE_Y; i++) { - Awb::RGB zone; - double counted = stats[i].counted; - if (counted >= min_pixels) { - zone.G = stats[i].g_sum / counted; - if (zone.G >= min_G) { - zone.R = stats[i].r_sum / counted; - zone.B = stats[i].b_sum / counted; - zones.push_back(zone); - } - } - } -} - -void Awb::prepareStats() -{ - zones_.clear(); - // LSC has already been applied to the stats in this pipeline, so stop - // any LSC compensation. We also ignore config_.fast in this version. - generate_stats(zones_, statistics_->awb_stats, config_.min_pixels, - config_.min_G); - // we're done with these; we may as well relinquish our hold on the - // pointer. - statistics_.reset(); - // apply sensitivities, so values appear to come from our "canonical" - // sensor. - for (auto &zone : zones_) - zone.R *= config_.sensitivity_r, - zone.B *= config_.sensitivity_b; -} - -double Awb::computeDelta2Sum(double gain_r, double gain_b) -{ - // Compute the sum of the squared colour error (non-greyness) as it - // appears in the log likelihood equation. - double delta2_sum = 0; - for (auto &z : zones_) { - double delta_r = gain_r * z.R - 1 - config_.whitepoint_r; - double delta_b = gain_b * z.B - 1 - config_.whitepoint_b; - double delta2 = delta_r * delta_r + delta_b * delta_b; - //LOG(RPiAwb, Debug) << "delta_r " << delta_r << " delta_b " << delta_b << " delta2 " << delta2; - delta2 = std::min(delta2, config_.delta_limit); - delta2_sum += delta2; - } - return delta2_sum; -} - -Pwl Awb::interpolatePrior() -{ - // Interpolate the prior log likelihood function for our current lux - // value. - if (lux_ <= config_.priors.front().lux) - return config_.priors.front().prior; - else if (lux_ >= config_.priors.back().lux) - return config_.priors.back().prior; - else { - int idx = 0; - // find which two we lie between - while (config_.priors[idx + 1].lux < lux_) - idx++; - double lux0 = config_.priors[idx].lux, - lux1 = config_.priors[idx + 1].lux; - return Pwl::Combine(config_.priors[idx].prior, - config_.priors[idx + 1].prior, - [&](double /*x*/, double y0, double y1) { - return y0 + (y1 - y0) * - (lux_ - lux0) / (lux1 - lux0); - }); - } -} - -static double interpolate_quadatric(Pwl::Point const &A, Pwl::Point const &B, - Pwl::Point const &C) -{ - // Given 3 points on a curve, find the extremum of the function in that - // interval by fitting a quadratic. - const double eps = 1e-3; - Pwl::Point CA = C - A, BA = B - A; - double denominator = 2 * (BA.y * CA.x - CA.y * BA.x); - if (abs(denominator) > eps) { - double numerator = BA.y * CA.x * CA.x - CA.y * BA.x * BA.x; - double result = numerator / denominator + A.x; - return std::max(A.x, std::min(C.x, result)); - } - // has degenerated to straight line segment - return A.y < C.y - eps ? A.x : (C.y < A.y - eps ? C.x : B.x); -} - -double Awb::coarseSearch(Pwl const &prior) -{ - points_.clear(); // assume doesn't deallocate memory - size_t best_point = 0; - double t = mode_->ct_lo; - int span_r = 0, span_b = 0; - // Step down the CT curve evaluating log likelihood. - while (true) { - double r = config_.ct_r.Eval(t, &span_r); - double b = config_.ct_b.Eval(t, &span_b); - double gain_r = 1 / r, gain_b = 1 / b; - double delta2_sum = computeDelta2Sum(gain_r, gain_b); - double prior_log_likelihood = - prior.Eval(prior.Domain().Clip(t)); - double final_log_likelihood = delta2_sum - prior_log_likelihood; - LOG(RPiAwb, Debug) - << "t: " << t << " gain_r " << gain_r << " gain_b " - << gain_b << " delta2_sum " << delta2_sum - << " prior " << prior_log_likelihood << " final " - << final_log_likelihood; - points_.push_back(Pwl::Point(t, final_log_likelihood)); - if (points_.back().y < points_[best_point].y) - best_point = points_.size() - 1; - if (t == mode_->ct_hi) - break; - // for even steps along the r/b curve scale them by the current t - t = std::min(t + t / 10 * config_.coarse_step, - mode_->ct_hi); - } - t = points_[best_point].x; - LOG(RPiAwb, Debug) << "Coarse search found CT " << t; - // We have the best point of the search, but refine it with a quadratic - // interpolation around its neighbours. - if (points_.size() > 2) { - unsigned long bp = std::min(best_point, points_.size() - 2); - best_point = std::max(1UL, bp); - t = interpolate_quadatric(points_[best_point - 1], - points_[best_point], - points_[best_point + 1]); - LOG(RPiAwb, Debug) - << "After quadratic refinement, coarse search has CT " - << t; - } - return t; -} - -void Awb::fineSearch(double &t, double &r, double &b, Pwl const &prior) -{ - int span_r = -1, span_b = -1; - config_.ct_r.Eval(t, &span_r); - config_.ct_b.Eval(t, &span_b); - double step = t / 10 * config_.coarse_step * 0.1; - int nsteps = 5; - double r_diff = config_.ct_r.Eval(t + nsteps * step, &span_r) - - config_.ct_r.Eval(t - nsteps * step, &span_r); - double b_diff = config_.ct_b.Eval(t + nsteps * step, &span_b) - - config_.ct_b.Eval(t - nsteps * step, &span_b); - Pwl::Point transverse(b_diff, -r_diff); - if (transverse.Len2() < 1e-6) - return; - // unit vector orthogonal to the b vs. r function (pointing outwards - // with r and b increasing) - transverse = transverse / transverse.Len(); - double best_log_likelihood = 0, best_t = 0, best_r = 0, best_b = 0; - double transverse_range = - config_.transverse_neg + config_.transverse_pos; - const int MAX_NUM_DELTAS = 12; - // a transverse step approximately every 0.01 r/b units - int num_deltas = floor(transverse_range * 100 + 0.5) + 1; - num_deltas = num_deltas < 3 ? 3 : - (num_deltas > MAX_NUM_DELTAS ? MAX_NUM_DELTAS : num_deltas); - // Step down CT curve. March a bit further if the transverse range is - // large. - nsteps += num_deltas; - for (int i = -nsteps; i <= nsteps; i++) { - double t_test = t + i * step; - double prior_log_likelihood = - prior.Eval(prior.Domain().Clip(t_test)); - double r_curve = config_.ct_r.Eval(t_test, &span_r); - double b_curve = config_.ct_b.Eval(t_test, &span_b); - // x will be distance off the curve, y the log likelihood there - Pwl::Point points[MAX_NUM_DELTAS]; - int best_point = 0; - // Take some measurements transversely *off* the CT curve. - for (int j = 0; j < num_deltas; j++) { - points[j].x = -config_.transverse_neg + - (transverse_range * j) / (num_deltas - 1); - Pwl::Point rb_test = Pwl::Point(r_curve, b_curve) + - transverse * points[j].x; - double r_test = rb_test.x, b_test = rb_test.y; - double gain_r = 1 / r_test, gain_b = 1 / b_test; - double delta2_sum = computeDelta2Sum(gain_r, gain_b); - points[j].y = delta2_sum - prior_log_likelihood; - LOG(RPiAwb, Debug) - << "At t " << t_test << " r " << r_test << " b " - << b_test << ": " << points[j].y; - if (points[j].y < points[best_point].y) - best_point = j; - } - // We have NUM_DELTAS points transversely across the CT curve, - // now let's do a quadratic interpolation for the best result. - best_point = std::max(1, std::min(best_point, num_deltas - 2)); - Pwl::Point rb_test = - Pwl::Point(r_curve, b_curve) + - transverse * - interpolate_quadatric(points[best_point - 1], - points[best_point], - points[best_point + 1]); - double r_test = rb_test.x, b_test = rb_test.y; - double gain_r = 1 / r_test, gain_b = 1 / b_test; - double delta2_sum = computeDelta2Sum(gain_r, gain_b); - double final_log_likelihood = delta2_sum - prior_log_likelihood; - LOG(RPiAwb, Debug) - << "Finally " - << t_test << " r " << r_test << " b " << b_test << ": " - << final_log_likelihood - << (final_log_likelihood < best_log_likelihood ? " BEST" : ""); - if (best_t == 0 || final_log_likelihood < best_log_likelihood) - best_log_likelihood = final_log_likelihood, - best_t = t_test, best_r = r_test, best_b = b_test; - } - t = best_t, r = best_r, b = best_b; - LOG(RPiAwb, Debug) - << "Fine search found t " << t << " r " << r << " b " << b; -} - -void Awb::awbBayes() -{ - // May as well divide out G to save computeDelta2Sum from doing it over - // and over. - for (auto &z : zones_) - z.R = z.R / (z.G + 1), z.B = z.B / (z.G + 1); - // Get the current prior, and scale according to how many zones are - // valid... not entirely sure about this. - Pwl prior = interpolatePrior(); - prior *= zones_.size() / (double)(AWB_STATS_SIZE_X * AWB_STATS_SIZE_Y); - prior.Map([](double x, double y) { - LOG(RPiAwb, Debug) << "(" << x << "," << y << ")"; - }); - double t = coarseSearch(prior); - double r = config_.ct_r.Eval(t); - double b = config_.ct_b.Eval(t); - LOG(RPiAwb, Debug) - << "After coarse search: r " << r << " b " << b << " (gains r " - << 1 / r << " b " << 1 / b << ")"; - // Not entirely sure how to handle the fine search yet. Mostly the - // estimated CT is already good enough, but the fine search allows us to - // wander transverely off the CT curve. Under some illuminants, where - // there may be more or less green light, this may prove beneficial, - // though I probably need more real datasets before deciding exactly how - // this should be controlled and tuned. - fineSearch(t, r, b, prior); - LOG(RPiAwb, Debug) - << "After fine search: r " << r << " b " << b << " (gains r " - << 1 / r << " b " << 1 / b << ")"; - // Write results out for the main thread to pick up. Remember to adjust - // the gains from the ones that the "canonical sensor" would require to - // the ones needed by *this* sensor. - async_results_.temperature_K = t; - async_results_.gain_r = 1.0 / r * config_.sensitivity_r; - async_results_.gain_g = 1.0; - async_results_.gain_b = 1.0 / b * config_.sensitivity_b; -} - -void Awb::awbGrey() -{ - LOG(RPiAwb, Debug) << "Grey world AWB"; - // Make a separate list of the derivatives for each of red and blue, so - // that we can sort them to exclude the extreme gains. We could - // consider some variations, such as normalising all the zones first, or - // doing an L2 average etc. - std::vector<RGB> &derivs_R(zones_); - std::vector<RGB> derivs_B(derivs_R); - std::sort(derivs_R.begin(), derivs_R.end(), - [](RGB const &a, RGB const &b) { - return a.G * b.R < b.G * a.R; - }); - std::sort(derivs_B.begin(), derivs_B.end(), - [](RGB const &a, RGB const &b) { - return a.G * b.B < b.G * a.B; - }); - // Average the middle half of the values. - int discard = derivs_R.size() / 4; - RGB sum_R(0, 0, 0), sum_B(0, 0, 0); - for (auto ri = derivs_R.begin() + discard, - bi = derivs_B.begin() + discard; - ri != derivs_R.end() - discard; ri++, bi++) - sum_R += *ri, sum_B += *bi; - double gain_r = sum_R.G / (sum_R.R + 1), - gain_b = sum_B.G / (sum_B.B + 1); - async_results_.temperature_K = 4500; // don't know what it is - async_results_.gain_r = gain_r; - async_results_.gain_g = 1.0; - async_results_.gain_b = gain_b; -} - -void Awb::doAwb() -{ - prepareStats(); - LOG(RPiAwb, Debug) << "Valid zones: " << zones_.size(); - if (zones_.size() > config_.min_regions) { - if (config_.bayes) - awbBayes(); - else - awbGrey(); - LOG(RPiAwb, Debug) - << "CT found is " - << async_results_.temperature_K - << " with gains r " << async_results_.gain_r - << " and b " << async_results_.gain_b; - } -} - -// Register algorithm with the system. -static Algorithm *Create(Controller *controller) -{ - return (Algorithm *)new Awb(controller); -} -static RegisterAlgorithm reg(NAME, &Create); diff --git a/src/ipa/raspberrypi/controller/rpi/awb.hpp b/src/ipa/raspberrypi/controller/rpi/awb.hpp deleted file mode 100644 index ac3dca6f..00000000 --- a/src/ipa/raspberrypi/controller/rpi/awb.hpp +++ /dev/null @@ -1,179 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * awb.hpp - AWB control algorithm - */ -#pragma once - -#include <mutex> -#include <condition_variable> -#include <thread> - -#include "../awb_algorithm.hpp" -#include "../pwl.hpp" -#include "../awb_status.h" - -namespace RPiController { - -// Control algorithm to perform AWB calculations. - -struct AwbMode { - void Read(boost::property_tree::ptree const ¶ms); - double ct_lo; // low CT value for search - double ct_hi; // high CT value for search -}; - -struct AwbPrior { - void Read(boost::property_tree::ptree const ¶ms); - double lux; // lux level - Pwl prior; // maps CT to prior log likelihood for this lux level -}; - -struct AwbConfig { - AwbConfig() : default_mode(nullptr) {} - void Read(boost::property_tree::ptree const ¶ms); - // Only repeat the AWB calculation every "this many" frames - uint16_t frame_period; - // number of initial frames for which speed taken as 1.0 (maximum) - uint16_t startup_frames; - unsigned int convergence_frames; // approx number of frames to converge - double speed; // IIR filter speed applied to algorithm results - bool fast; // "fast" mode uses a 16x16 rather than 32x32 grid - Pwl ct_r; // function maps CT to r (= R/G) - Pwl ct_b; // function maps CT to b (= B/G) - // table of illuminant priors at different lux levels - std::vector<AwbPrior> priors; - // AWB "modes" (determines the search range) - std::map<std::string, AwbMode> modes; - AwbMode *default_mode; // mode used if no mode selected - // minimum proportion of pixels counted within AWB region for it to be - // "useful" - double min_pixels; - // minimum G value of those pixels, to be regarded a "useful" - uint16_t min_G; - // number of AWB regions that must be "useful" in order to do the AWB - // calculation - uint32_t min_regions; - // clamp on colour error term (so as not to penalise non-grey excessively) - double delta_limit; - // step size control in coarse search - double coarse_step; - // how far to wander off CT curve towards "more purple" - double transverse_pos; - // how far to wander off CT curve towards "more green" - double transverse_neg; - // red sensitivity ratio (set to canonical sensor's R/G divided by this - // sensor's R/G) - double sensitivity_r; - // blue sensitivity ratio (set to canonical sensor's B/G divided by this - // sensor's B/G) - double sensitivity_b; - // The whitepoint (which we normally "aim" for) can be moved. - double whitepoint_r; - double whitepoint_b; - bool bayes; // use Bayesian algorithm -}; - -class Awb : public AwbAlgorithm -{ -public: - Awb(Controller *controller = NULL); - ~Awb(); - char const *Name() const override; - void Initialise() override; - void Read(boost::property_tree::ptree const ¶ms) override; - // AWB handles "pausing" for itself. - bool IsPaused() const override; - void Pause() override; - void Resume() override; - unsigned int GetConvergenceFrames() const override; - void SetMode(std::string const &name) override; - void SetManualGains(double manual_r, double manual_b) override; - void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override; - void Prepare(Metadata *image_metadata) override; - void Process(StatisticsPtr &stats, Metadata *image_metadata) override; - struct RGB { - RGB(double _R = 0, double _G = 0, double _B = 0) - : R(_R), G(_G), B(_B) - { - } - double R, G, B; - RGB &operator+=(RGB const &other) - { - R += other.R, G += other.G, B += other.B; - return *this; - } - }; - -private: - bool isAutoEnabled() const; - // configuration is read-only, and available to both threads - AwbConfig config_; - std::thread async_thread_; - void asyncFunc(); // asynchronous thread function - std::mutex mutex_; - // condvar for async thread to wait on - std::condition_variable async_signal_; - // condvar for synchronous thread to wait on - std::condition_variable sync_signal_; - // for sync thread to check if async thread finished (requires mutex) - bool async_finished_; - // for async thread to check if it's been told to run (requires mutex) - bool async_start_; - // for async thread to check if it's been told to quit (requires mutex) - bool async_abort_; - - // The following are only for the synchronous thread to use: - // for sync thread to note its has asked async thread to run - bool async_started_; - // counts up to frame_period before restarting the async thread - int frame_phase_; - int frame_count_; // counts up to startup_frames - AwbStatus sync_results_; - AwbStatus prev_sync_results_; - std::string mode_name_; - // The following are for the asynchronous thread to use, though the main - // thread can set/reset them if the async thread is known to be idle: - void restartAsync(StatisticsPtr &stats, double lux); - // copy out the results from the async thread so that it can be restarted - void fetchAsyncResults(); - StatisticsPtr statistics_; - AwbMode *mode_; - double lux_; - AwbStatus async_results_; - void doAwb(); - void awbBayes(); - void awbGrey(); - void prepareStats(); - double computeDelta2Sum(double gain_r, double gain_b); - Pwl interpolatePrior(); - double coarseSearch(Pwl const &prior); - void fineSearch(double &t, double &r, double &b, Pwl const &prior); - std::vector<RGB> zones_; - std::vector<Pwl::Point> points_; - // manual r setting - double manual_r_; - // manual b setting - double manual_b_; - bool first_switch_mode_; // is this the first call to SwitchMode? -}; - -static inline Awb::RGB operator+(Awb::RGB const &a, Awb::RGB const &b) -{ - return Awb::RGB(a.R + b.R, a.G + b.G, a.B + b.B); -} -static inline Awb::RGB operator-(Awb::RGB const &a, Awb::RGB const &b) -{ - return Awb::RGB(a.R - b.R, a.G - b.G, a.B - b.B); -} -static inline Awb::RGB operator*(double d, Awb::RGB const &rgb) -{ - return Awb::RGB(d * rgb.R, d * rgb.G, d * rgb.B); -} -static inline Awb::RGB operator*(Awb::RGB const &rgb, double d) -{ - return d * rgb; -} - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/rpi/black_level.cpp b/src/ipa/raspberrypi/controller/rpi/black_level.cpp deleted file mode 100644 index 6b3497f1..00000000 --- a/src/ipa/raspberrypi/controller/rpi/black_level.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * black_level.cpp - black level control algorithm - */ - -#include <math.h> -#include <stdint.h> - -#include <libcamera/base/log.h> - -#include "../black_level_status.h" - -#include "black_level.hpp" - -using namespace RPiController; -using namespace libcamera; - -LOG_DEFINE_CATEGORY(RPiBlackLevel) - -#define NAME "rpi.black_level" - -BlackLevel::BlackLevel(Controller *controller) - : Algorithm(controller) -{ -} - -char const *BlackLevel::Name() const -{ - return NAME; -} - -void BlackLevel::Read(boost::property_tree::ptree const ¶ms) -{ - uint16_t black_level = params.get<uint16_t>( - "black_level", 4096); // 64 in 10 bits scaled to 16 bits - black_level_r_ = params.get<uint16_t>("black_level_r", black_level); - black_level_g_ = params.get<uint16_t>("black_level_g", black_level); - black_level_b_ = params.get<uint16_t>("black_level_b", black_level); - LOG(RPiBlackLevel, Debug) - << " Read black levels red " << black_level_r_ - << " green " << black_level_g_ - << " blue " << black_level_b_; -} - -void BlackLevel::Prepare(Metadata *image_metadata) -{ - // Possibly we should think about doing this in a switch_mode or - // something? - struct BlackLevelStatus status; - status.black_level_r = black_level_r_; - status.black_level_g = black_level_g_; - status.black_level_b = black_level_b_; - image_metadata->Set("black_level.status", status); -} - -// Register algorithm with the system. -static Algorithm *Create(Controller *controller) -{ - return new BlackLevel(controller); -} -static RegisterAlgorithm reg(NAME, &Create); diff --git a/src/ipa/raspberrypi/controller/rpi/black_level.hpp b/src/ipa/raspberrypi/controller/rpi/black_level.hpp deleted file mode 100644 index 65ec4d0e..00000000 --- a/src/ipa/raspberrypi/controller/rpi/black_level.hpp +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * black_level.hpp - black level control algorithm - */ -#pragma once - -#include "../algorithm.hpp" -#include "../black_level_status.h" - -// This is our implementation of the "black level algorithm". - -namespace RPiController { - -class BlackLevel : public Algorithm -{ -public: - BlackLevel(Controller *controller); - char const *Name() const override; - void Read(boost::property_tree::ptree const ¶ms) override; - void Prepare(Metadata *image_metadata) override; - -private: - double black_level_r_; - double black_level_g_; - double black_level_b_; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/rpi/ccm.cpp b/src/ipa/raspberrypi/controller/rpi/ccm.cpp deleted file mode 100644 index 821a4c7c..00000000 --- a/src/ipa/raspberrypi/controller/rpi/ccm.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * ccm.cpp - CCM (colour correction matrix) control algorithm - */ - -#include <libcamera/base/log.h> - -#include "../awb_status.h" -#include "../ccm_status.h" -#include "../lux_status.h" -#include "../metadata.hpp" - -#include "ccm.hpp" - -using namespace RPiController; -using namespace libcamera; - -LOG_DEFINE_CATEGORY(RPiCcm) - -// This algorithm selects a CCM (Colour Correction Matrix) according to the -// colour temperature estimated by AWB (interpolating between known matricies as -// necessary). Additionally the amount of colour saturation can be controlled -// both according to the current estimated lux level and according to a -// saturation setting that is exposed to applications. - -#define NAME "rpi.ccm" - -Matrix::Matrix() -{ - memset(m, 0, sizeof(m)); -} -Matrix::Matrix(double m0, double m1, double m2, double m3, double m4, double m5, - double m6, double m7, double m8) -{ - m[0][0] = m0, m[0][1] = m1, m[0][2] = m2, m[1][0] = m3, m[1][1] = m4, - m[1][2] = m5, m[2][0] = m6, m[2][1] = m7, m[2][2] = m8; -} -void Matrix::Read(boost::property_tree::ptree const ¶ms) -{ - double *ptr = (double *)m; - int n = 0; - for (auto it = params.begin(); it != params.end(); it++) { - if (n++ == 9) - throw std::runtime_error("Ccm: too many values in CCM"); - *ptr++ = it->second.get_value<double>(); - } - if (n < 9) - throw std::runtime_error("Ccm: too few values in CCM"); -} - -Ccm::Ccm(Controller *controller) - : CcmAlgorithm(controller), saturation_(1.0) {} - -char const *Ccm::Name() const -{ - return NAME; -} - -void Ccm::Read(boost::property_tree::ptree const ¶ms) -{ - if (params.get_child_optional("saturation")) - config_.saturation.Read(params.get_child("saturation")); - for (auto &p : params.get_child("ccms")) { - CtCcm ct_ccm; - ct_ccm.ct = p.second.get<double>("ct"); - ct_ccm.ccm.Read(p.second.get_child("ccm")); - if (!config_.ccms.empty() && - ct_ccm.ct <= config_.ccms.back().ct) - throw std::runtime_error( - "Ccm: CCM not in increasing colour temperature order"); - config_.ccms.push_back(std::move(ct_ccm)); - } - if (config_.ccms.empty()) - throw std::runtime_error("Ccm: no CCMs specified"); -} - -void Ccm::SetSaturation(double saturation) -{ - saturation_ = saturation; -} - -void Ccm::Initialise() {} - -template<typename T> -static bool get_locked(Metadata *metadata, std::string const &tag, T &value) -{ - T *ptr = metadata->GetLocked<T>(tag); - if (ptr == nullptr) - return false; - value = *ptr; - return true; -} - -Matrix calculate_ccm(std::vector<CtCcm> const &ccms, double ct) -{ - if (ct <= ccms.front().ct) - return ccms.front().ccm; - else if (ct >= ccms.back().ct) - return ccms.back().ccm; - else { - int i = 0; - for (; ct > ccms[i].ct; i++) - ; - double lambda = - (ct - ccms[i - 1].ct) / (ccms[i].ct - ccms[i - 1].ct); - return lambda * ccms[i].ccm + (1.0 - lambda) * ccms[i - 1].ccm; - } -} - -Matrix apply_saturation(Matrix const &ccm, double saturation) -{ - Matrix RGB2Y(0.299, 0.587, 0.114, -0.169, -0.331, 0.500, 0.500, -0.419, - -0.081); - Matrix Y2RGB(1.000, 0.000, 1.402, 1.000, -0.345, -0.714, 1.000, 1.771, - 0.000); - Matrix S(1, 0, 0, 0, saturation, 0, 0, 0, saturation); - return Y2RGB * S * RGB2Y * ccm; -} - -void Ccm::Prepare(Metadata *image_metadata) -{ - bool awb_ok = false, lux_ok = false; - struct AwbStatus awb = {}; - awb.temperature_K = 4000; // in case no metadata - struct LuxStatus lux = {}; - lux.lux = 400; // in case no metadata - { - // grab mutex just once to get everything - std::lock_guard<Metadata> lock(*image_metadata); - awb_ok = get_locked(image_metadata, "awb.status", awb); - lux_ok = get_locked(image_metadata, "lux.status", lux); - } - if (!awb_ok) - LOG(RPiCcm, Warning) << "no colour temperature found"; - if (!lux_ok) - LOG(RPiCcm, Warning) << "no lux value found"; - Matrix ccm = calculate_ccm(config_.ccms, awb.temperature_K); - double saturation = saturation_; - struct CcmStatus ccm_status; - ccm_status.saturation = saturation; - if (!config_.saturation.Empty()) - saturation *= config_.saturation.Eval( - config_.saturation.Domain().Clip(lux.lux)); - ccm = apply_saturation(ccm, saturation); - for (int j = 0; j < 3; j++) - for (int i = 0; i < 3; i++) - ccm_status.matrix[j * 3 + i] = - std::max(-8.0, std::min(7.9999, ccm.m[j][i])); - LOG(RPiCcm, Debug) - << "colour temperature " << awb.temperature_K << "K"; - LOG(RPiCcm, Debug) - << "CCM: " << ccm_status.matrix[0] << " " << ccm_status.matrix[1] - << " " << ccm_status.matrix[2] << " " - << ccm_status.matrix[3] << " " << ccm_status.matrix[4] - << " " << ccm_status.matrix[5] << " " - << ccm_status.matrix[6] << " " << ccm_status.matrix[7] - << " " << ccm_status.matrix[8]; - image_metadata->Set("ccm.status", ccm_status); -} - -// Register algorithm with the system. -static Algorithm *Create(Controller *controller) -{ - return (Algorithm *)new Ccm(controller); - ; -} -static RegisterAlgorithm reg(NAME, &Create); diff --git a/src/ipa/raspberrypi/controller/rpi/ccm.hpp b/src/ipa/raspberrypi/controller/rpi/ccm.hpp deleted file mode 100644 index 330ed51f..00000000 --- a/src/ipa/raspberrypi/controller/rpi/ccm.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * ccm.hpp - CCM (colour correction matrix) control algorithm - */ -#pragma once - -#include <vector> - -#include "../ccm_algorithm.hpp" -#include "../pwl.hpp" - -namespace RPiController { - -// Algorithm to calculate colour matrix. Should be placed after AWB. - -struct Matrix { - Matrix(double m0, double m1, double m2, double m3, double m4, double m5, - double m6, double m7, double m8); - Matrix(); - double m[3][3]; - void Read(boost::property_tree::ptree const ¶ms); -}; -static inline Matrix operator*(double d, Matrix const &m) -{ - return Matrix(m.m[0][0] * d, m.m[0][1] * d, m.m[0][2] * d, - m.m[1][0] * d, m.m[1][1] * d, m.m[1][2] * d, - m.m[2][0] * d, m.m[2][1] * d, m.m[2][2] * d); -} -static inline Matrix operator*(Matrix const &m1, Matrix const &m2) -{ - Matrix m; - for (int i = 0; i < 3; i++) - for (int j = 0; j < 3; j++) - m.m[i][j] = m1.m[i][0] * m2.m[0][j] + - m1.m[i][1] * m2.m[1][j] + - m1.m[i][2] * m2.m[2][j]; - return m; -} -static inline Matrix operator+(Matrix const &m1, Matrix const &m2) -{ - Matrix m; - for (int i = 0; i < 3; i++) - for (int j = 0; j < 3; j++) - m.m[i][j] = m1.m[i][j] + m2.m[i][j]; - return m; -} - -struct CtCcm { - double ct; - Matrix ccm; -}; - -struct CcmConfig { - std::vector<CtCcm> ccms; - Pwl saturation; -}; - -class Ccm : public CcmAlgorithm -{ -public: - Ccm(Controller *controller = NULL); - char const *Name() const override; - void Read(boost::property_tree::ptree const ¶ms) override; - void SetSaturation(double saturation) override; - void Initialise() override; - void Prepare(Metadata *image_metadata) override; - -private: - CcmConfig config_; - double saturation_; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/rpi/contrast.cpp b/src/ipa/raspberrypi/controller/rpi/contrast.cpp deleted file mode 100644 index ae55aad5..00000000 --- a/src/ipa/raspberrypi/controller/rpi/contrast.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * contrast.cpp - contrast (gamma) control algorithm - */ -#include <stdint.h> - -#include <libcamera/base/log.h> - -#include "../contrast_status.h" -#include "../histogram.hpp" - -#include "contrast.hpp" - -using namespace RPiController; -using namespace libcamera; - -LOG_DEFINE_CATEGORY(RPiContrast) - -// This is a very simple control algorithm which simply retrieves the results of -// AGC and AWB via their "status" metadata, and applies digital gain to the -// colour channels in accordance with those instructions. We take care never to -// apply less than unity gains, as that would cause fully saturated pixels to go -// off-white. - -#define NAME "rpi.contrast" - -Contrast::Contrast(Controller *controller) - : ContrastAlgorithm(controller), brightness_(0.0), contrast_(1.0) -{ -} - -char const *Contrast::Name() const -{ - return NAME; -} - -void Contrast::Read(boost::property_tree::ptree const ¶ms) -{ - // enable adaptive enhancement by default - config_.ce_enable = params.get<int>("ce_enable", 1); - // the point near the bottom of the histogram to move - config_.lo_histogram = params.get<double>("lo_histogram", 0.01); - // where in the range to try and move it to - config_.lo_level = params.get<double>("lo_level", 0.015); - // but don't move by more than this - config_.lo_max = params.get<double>("lo_max", 500); - // equivalent values for the top of the histogram... - config_.hi_histogram = params.get<double>("hi_histogram", 0.95); - config_.hi_level = params.get<double>("hi_level", 0.95); - config_.hi_max = params.get<double>("hi_max", 2000); - config_.gamma_curve.Read(params.get_child("gamma_curve")); -} - -void Contrast::SetBrightness(double brightness) -{ - brightness_ = brightness; -} - -void Contrast::SetContrast(double contrast) -{ - contrast_ = contrast; -} - -static void fill_in_status(ContrastStatus &status, double brightness, - double contrast, Pwl &gamma_curve) -{ - status.brightness = brightness; - status.contrast = contrast; - for (int i = 0; i < CONTRAST_NUM_POINTS - 1; i++) { - int x = i < 16 ? i * 1024 - : (i < 24 ? (i - 16) * 2048 + 16384 - : (i - 24) * 4096 + 32768); - status.points[i].x = x; - status.points[i].y = std::min(65535.0, gamma_curve.Eval(x)); - } - status.points[CONTRAST_NUM_POINTS - 1].x = 65535; - status.points[CONTRAST_NUM_POINTS - 1].y = 65535; -} - -void Contrast::Initialise() -{ - // Fill in some default values as Prepare will run before Process gets - // called. - fill_in_status(status_, brightness_, contrast_, config_.gamma_curve); -} - -void Contrast::Prepare(Metadata *image_metadata) -{ - std::unique_lock<std::mutex> lock(mutex_); - image_metadata->Set("contrast.status", status_); -} - -Pwl compute_stretch_curve(Histogram const &histogram, - ContrastConfig const &config) -{ - Pwl enhance; - enhance.Append(0, 0); - // If the start of the histogram is rather empty, try to pull it down a - // bit. - double hist_lo = histogram.Quantile(config.lo_histogram) * - (65536 / NUM_HISTOGRAM_BINS); - double level_lo = config.lo_level * 65536; - LOG(RPiContrast, Debug) - << "Move histogram point " << hist_lo << " to " << level_lo; - hist_lo = std::max( - level_lo, - std::min(65535.0, std::min(hist_lo, level_lo + config.lo_max))); - LOG(RPiContrast, Debug) - << "Final values " << hist_lo << " -> " << level_lo; - enhance.Append(hist_lo, level_lo); - // Keep the mid-point (median) in the same place, though, to limit the - // apparent amount of global brightness shift. - double mid = histogram.Quantile(0.5) * (65536 / NUM_HISTOGRAM_BINS); - enhance.Append(mid, mid); - - // If the top to the histogram is empty, try to pull the pixel values - // there up. - double hist_hi = histogram.Quantile(config.hi_histogram) * - (65536 / NUM_HISTOGRAM_BINS); - double level_hi = config.hi_level * 65536; - LOG(RPiContrast, Debug) - << "Move histogram point " << hist_hi << " to " << level_hi; - hist_hi = std::min( - level_hi, - std::max(0.0, std::max(hist_hi, level_hi - config.hi_max))); - LOG(RPiContrast, Debug) - << "Final values " << hist_hi << " -> " << level_hi; - enhance.Append(hist_hi, level_hi); - enhance.Append(65535, 65535); - return enhance; -} - -Pwl apply_manual_contrast(Pwl const &gamma_curve, double brightness, - double contrast) -{ - Pwl new_gamma_curve; - LOG(RPiContrast, Debug) - << "Manual brightness " << brightness << " contrast " << contrast; - gamma_curve.Map([&](double x, double y) { - new_gamma_curve.Append( - x, std::max(0.0, std::min(65535.0, - (y - 32768) * contrast + - 32768 + brightness))); - }); - return new_gamma_curve; -} - -void Contrast::Process(StatisticsPtr &stats, - [[maybe_unused]] Metadata *image_metadata) -{ - Histogram histogram(stats->hist[0].g_hist, NUM_HISTOGRAM_BINS); - // We look at the histogram and adjust the gamma curve in the following - // ways: 1. Adjust the gamma curve so as to pull the start of the - // histogram down, and possibly push the end up. - Pwl gamma_curve = config_.gamma_curve; - if (config_.ce_enable) { - if (config_.lo_max != 0 || config_.hi_max != 0) - gamma_curve = compute_stretch_curve(histogram, config_) - .Compose(gamma_curve); - // We could apply other adjustments (e.g. partial equalisation) - // based on the histogram...? - } - // 2. Finally apply any manually selected brightness/contrast - // adjustment. - if (brightness_ != 0 || contrast_ != 1.0) - gamma_curve = apply_manual_contrast(gamma_curve, brightness_, - contrast_); - // And fill in the status for output. Use more points towards the bottom - // of the curve. - ContrastStatus status; - fill_in_status(status, brightness_, contrast_, gamma_curve); - { - std::unique_lock<std::mutex> lock(mutex_); - status_ = status; - } -} - -// Register algorithm with the system. -static Algorithm *Create(Controller *controller) -{ - return (Algorithm *)new Contrast(controller); -} -static RegisterAlgorithm reg(NAME, &Create); diff --git a/src/ipa/raspberrypi/controller/rpi/contrast.hpp b/src/ipa/raspberrypi/controller/rpi/contrast.hpp deleted file mode 100644 index 85624539..00000000 --- a/src/ipa/raspberrypi/controller/rpi/contrast.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * contrast.hpp - contrast (gamma) control algorithm - */ -#pragma once - -#include <mutex> - -#include "../contrast_algorithm.hpp" -#include "../pwl.hpp" - -namespace RPiController { - -// Back End algorithm to appaly correct digital gain. Should be placed after -// Back End AWB. - -struct ContrastConfig { - bool ce_enable; - double lo_histogram; - double lo_level; - double lo_max; - double hi_histogram; - double hi_level; - double hi_max; - Pwl gamma_curve; -}; - -class Contrast : public ContrastAlgorithm -{ -public: - Contrast(Controller *controller = NULL); - char const *Name() const override; - void Read(boost::property_tree::ptree const ¶ms) override; - void SetBrightness(double brightness) override; - void SetContrast(double contrast) override; - void Initialise() override; - void Prepare(Metadata *image_metadata) override; - void Process(StatisticsPtr &stats, Metadata *image_metadata) override; - -private: - ContrastConfig config_; - double brightness_; - double contrast_; - ContrastStatus status_; - std::mutex mutex_; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/rpi/dpc.cpp b/src/ipa/raspberrypi/controller/rpi/dpc.cpp deleted file mode 100644 index 110f5056..00000000 --- a/src/ipa/raspberrypi/controller/rpi/dpc.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * dpc.cpp - DPC (defective pixel correction) control algorithm - */ - -#include <libcamera/base/log.h> - -#include "dpc.hpp" - -using namespace RPiController; -using namespace libcamera; - -LOG_DEFINE_CATEGORY(RPiDpc) - -// We use the lux status so that we can apply stronger settings in darkness (if -// necessary). - -#define NAME "rpi.dpc" - -Dpc::Dpc(Controller *controller) - : Algorithm(controller) -{ -} - -char const *Dpc::Name() const -{ - return NAME; -} - -void Dpc::Read(boost::property_tree::ptree const ¶ms) -{ - config_.strength = params.get<int>("strength", 1); - if (config_.strength < 0 || config_.strength > 2) - throw std::runtime_error("Dpc: bad strength value"); -} - -void Dpc::Prepare(Metadata *image_metadata) -{ - DpcStatus dpc_status = {}; - // Should we vary this with lux level or analogue gain? TBD. - dpc_status.strength = config_.strength; - LOG(RPiDpc, Debug) << "strength " << dpc_status.strength; - image_metadata->Set("dpc.status", dpc_status); -} - -// Register algorithm with the system. -static Algorithm *Create(Controller *controller) -{ - return (Algorithm *)new Dpc(controller); -} -static RegisterAlgorithm reg(NAME, &Create); diff --git a/src/ipa/raspberrypi/controller/rpi/dpc.hpp b/src/ipa/raspberrypi/controller/rpi/dpc.hpp deleted file mode 100644 index d90285c4..00000000 --- a/src/ipa/raspberrypi/controller/rpi/dpc.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * dpc.hpp - DPC (defective pixel correction) control algorithm - */ -#pragma once - -#include "../algorithm.hpp" -#include "../dpc_status.h" - -namespace RPiController { - -// Back End algorithm to apply appropriate GEQ settings. - -struct DpcConfig { - int strength; -}; - -class Dpc : public Algorithm -{ -public: - Dpc(Controller *controller); - char const *Name() const override; - void Read(boost::property_tree::ptree const ¶ms) override; - void Prepare(Metadata *image_metadata) override; - -private: - DpcConfig config_; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/rpi/focus.cpp b/src/ipa/raspberrypi/controller/rpi/focus.cpp deleted file mode 100644 index a87ec802..00000000 --- a/src/ipa/raspberrypi/controller/rpi/focus.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2020, Raspberry Pi (Trading) Limited - * - * focus.cpp - focus algorithm - */ -#include <stdint.h> - -#include <libcamera/base/log.h> - -#include "../focus_status.h" -#include "focus.hpp" - -using namespace RPiController; -using namespace libcamera; - -LOG_DEFINE_CATEGORY(RPiFocus) - -#define NAME "rpi.focus" - -Focus::Focus(Controller *controller) - : Algorithm(controller) -{ -} - -char const *Focus::Name() const -{ - return NAME; -} - -void Focus::Process(StatisticsPtr &stats, Metadata *image_metadata) -{ - FocusStatus status; - unsigned int i; - for (i = 0; i < FOCUS_REGIONS; i++) - status.focus_measures[i] = stats->focus_stats[i].contrast_val[1][1] / 1000; - status.num = i; - image_metadata->Set("focus.status", status); - - LOG(RPiFocus, Debug) - << "Focus contrast measure: " - << (status.focus_measures[5] + status.focus_measures[6]) / 10; -} - -/* Register algorithm with the system. */ -static Algorithm *Create(Controller *controller) -{ - return new Focus(controller); -} -static RegisterAlgorithm reg(NAME, &Create); diff --git a/src/ipa/raspberrypi/controller/rpi/focus.hpp b/src/ipa/raspberrypi/controller/rpi/focus.hpp deleted file mode 100644 index 131b1d0f..00000000 --- a/src/ipa/raspberrypi/controller/rpi/focus.hpp +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2020, Raspberry Pi (Trading) Limited - * - * focus.hpp - focus algorithm - */ -#pragma once - -#include "../algorithm.hpp" -#include "../metadata.hpp" - -/* - * The "focus" algorithm. All it does it print out a version of the - * focus contrast measure; there is no actual auto-focus mechanism to - * control. - */ - -namespace RPiController { - -class Focus : public Algorithm -{ -public: - Focus(Controller *controller); - char const *Name() const override; - void Process(StatisticsPtr &stats, Metadata *image_metadata) override; -}; - -} /* namespace RPiController */ diff --git a/src/ipa/raspberrypi/controller/rpi/geq.cpp b/src/ipa/raspberrypi/controller/rpi/geq.cpp deleted file mode 100644 index 4530cb75..00000000 --- a/src/ipa/raspberrypi/controller/rpi/geq.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * geq.cpp - GEQ (green equalisation) control algorithm - */ - -#include <libcamera/base/log.h> - -#include "../device_status.h" -#include "../lux_status.h" -#include "../pwl.hpp" - -#include "geq.hpp" - -using namespace RPiController; -using namespace libcamera; - -LOG_DEFINE_CATEGORY(RPiGeq) - -// We use the lux status so that we can apply stronger settings in darkness (if -// necessary). - -#define NAME "rpi.geq" - -Geq::Geq(Controller *controller) - : Algorithm(controller) -{ -} - -char const *Geq::Name() const -{ - return NAME; -} - -void Geq::Read(boost::property_tree::ptree const ¶ms) -{ - config_.offset = params.get<uint16_t>("offset", 0); - config_.slope = params.get<double>("slope", 0.0); - if (config_.slope < 0.0 || config_.slope >= 1.0) - throw std::runtime_error("Geq: bad slope value"); - if (params.get_child_optional("strength")) - config_.strength.Read(params.get_child("strength")); -} - -void Geq::Prepare(Metadata *image_metadata) -{ - LuxStatus lux_status = {}; - lux_status.lux = 400; - if (image_metadata->Get("lux.status", lux_status)) - LOG(RPiGeq, Warning) << "no lux data found"; - DeviceStatus device_status; - device_status.analogue_gain = 1.0; // in case not found - if (image_metadata->Get("device.status", device_status)) - LOG(RPiGeq, Warning) - << "no device metadata - use analogue gain of 1x"; - GeqStatus geq_status = {}; - double strength = - config_.strength.Empty() - ? 1.0 - : config_.strength.Eval(config_.strength.Domain().Clip( - lux_status.lux)); - strength *= device_status.analogue_gain; - double offset = config_.offset * strength; - double slope = config_.slope * strength; - geq_status.offset = std::min(65535.0, std::max(0.0, offset)); - geq_status.slope = std::min(.99999, std::max(0.0, slope)); - LOG(RPiGeq, Debug) - << "offset " << geq_status.offset << " slope " - << geq_status.slope << " (analogue gain " - << device_status.analogue_gain << " lux " - << lux_status.lux << ")"; - image_metadata->Set("geq.status", geq_status); -} - -// Register algorithm with the system. -static Algorithm *Create(Controller *controller) -{ - return (Algorithm *)new Geq(controller); -} -static RegisterAlgorithm reg(NAME, &Create); diff --git a/src/ipa/raspberrypi/controller/rpi/geq.hpp b/src/ipa/raspberrypi/controller/rpi/geq.hpp deleted file mode 100644 index 8ba3046b..00000000 --- a/src/ipa/raspberrypi/controller/rpi/geq.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * geq.hpp - GEQ (green equalisation) control algorithm - */ -#pragma once - -#include "../algorithm.hpp" -#include "../geq_status.h" - -namespace RPiController { - -// Back End algorithm to apply appropriate GEQ settings. - -struct GeqConfig { - uint16_t offset; - double slope; - Pwl strength; // lux to strength factor -}; - -class Geq : public Algorithm -{ -public: - Geq(Controller *controller); - char const *Name() const override; - void Read(boost::property_tree::ptree const ¶ms) override; - void Prepare(Metadata *image_metadata) override; - -private: - GeqConfig config_; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp b/src/ipa/raspberrypi/controller/rpi/lux.cpp deleted file mode 100644 index 4d145b6f..00000000 --- a/src/ipa/raspberrypi/controller/rpi/lux.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * lux.cpp - Lux control algorithm - */ -#include <math.h> - -#include <linux/bcm2835-isp.h> - -#include <libcamera/base/log.h> - -#include "../device_status.h" - -#include "lux.hpp" - -using namespace RPiController; -using namespace libcamera; -using namespace std::literals::chrono_literals; - -LOG_DEFINE_CATEGORY(RPiLux) - -#define NAME "rpi.lux" - -Lux::Lux(Controller *controller) - : Algorithm(controller) -{ - // Put in some defaults as there will be no meaningful values until - // Process has run. - status_.aperture = 1.0; - status_.lux = 400; -} - -char const *Lux::Name() const -{ - return NAME; -} - -void Lux::Read(boost::property_tree::ptree const ¶ms) -{ - reference_shutter_speed_ = - params.get<double>("reference_shutter_speed") * 1.0us; - reference_gain_ = params.get<double>("reference_gain"); - reference_aperture_ = params.get<double>("reference_aperture", 1.0); - reference_Y_ = params.get<double>("reference_Y"); - reference_lux_ = params.get<double>("reference_lux"); - current_aperture_ = reference_aperture_; -} - -void Lux::SetCurrentAperture(double aperture) -{ - current_aperture_ = aperture; -} - -void Lux::Prepare(Metadata *image_metadata) -{ - std::unique_lock<std::mutex> lock(mutex_); - image_metadata->Set("lux.status", status_); -} - -void Lux::Process(StatisticsPtr &stats, Metadata *image_metadata) -{ - DeviceStatus device_status; - if (image_metadata->Get("device.status", device_status) == 0) { - double current_gain = device_status.analogue_gain; - double current_aperture = device_status.aperture.value_or(current_aperture_); - uint64_t sum = 0; - uint32_t num = 0; - uint32_t *bin = stats->hist[0].g_hist; - const int num_bins = sizeof(stats->hist[0].g_hist) / - sizeof(stats->hist[0].g_hist[0]); - for (int i = 0; i < num_bins; i++) - sum += bin[i] * (uint64_t)i, num += bin[i]; - // add .5 to reflect the mid-points of bins - double current_Y = sum / (double)num + .5; - double gain_ratio = reference_gain_ / current_gain; - double shutter_speed_ratio = - reference_shutter_speed_ / device_status.shutter_speed; - double aperture_ratio = reference_aperture_ / current_aperture; - double Y_ratio = current_Y * (65536 / num_bins) / reference_Y_; - double estimated_lux = shutter_speed_ratio * gain_ratio * - aperture_ratio * aperture_ratio * - Y_ratio * reference_lux_; - LuxStatus status; - status.lux = estimated_lux; - status.aperture = current_aperture; - LOG(RPiLux, Debug) << ": estimated lux " << estimated_lux; - { - std::unique_lock<std::mutex> lock(mutex_); - status_ = status; - } - // Overwrite the metadata here as well, so that downstream - // algorithms get the latest value. - image_metadata->Set("lux.status", status); - } else - LOG(RPiLux, Warning) << ": no device metadata"; -} - -// Register algorithm with the system. -static Algorithm *Create(Controller *controller) -{ - return (Algorithm *)new Lux(controller); -} -static RegisterAlgorithm reg(NAME, &Create); diff --git a/src/ipa/raspberrypi/controller/rpi/lux.hpp b/src/ipa/raspberrypi/controller/rpi/lux.hpp deleted file mode 100644 index 3ebd35d1..00000000 --- a/src/ipa/raspberrypi/controller/rpi/lux.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * lux.hpp - Lux control algorithm - */ -#pragma once - -#include <mutex> - -#include <libcamera/base/utils.h> - -#include "../lux_status.h" -#include "../algorithm.hpp" - -// This is our implementation of the "lux control algorithm". - -namespace RPiController { - -class Lux : public Algorithm -{ -public: - Lux(Controller *controller); - char const *Name() const override; - void Read(boost::property_tree::ptree const ¶ms) override; - void Prepare(Metadata *image_metadata) override; - void Process(StatisticsPtr &stats, Metadata *image_metadata) override; - void SetCurrentAperture(double aperture); - -private: - // These values define the conditions of the reference image, against - // which we compare the new image. - libcamera::utils::Duration reference_shutter_speed_; - double reference_gain_; - double reference_aperture_; // units of 1/f - double reference_Y_; // out of 65536 - double reference_lux_; - double current_aperture_; - LuxStatus status_; - std::mutex mutex_; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/rpi/noise.cpp b/src/ipa/raspberrypi/controller/rpi/noise.cpp deleted file mode 100644 index 63cad639..00000000 --- a/src/ipa/raspberrypi/controller/rpi/noise.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * noise.cpp - Noise control algorithm - */ - -#include <math.h> - -#include <libcamera/base/log.h> - -#include "../device_status.h" -#include "../noise_status.h" - -#include "noise.hpp" - -using namespace RPiController; -using namespace libcamera; - -LOG_DEFINE_CATEGORY(RPiNoise) - -#define NAME "rpi.noise" - -Noise::Noise(Controller *controller) - : Algorithm(controller), mode_factor_(1.0) -{ -} - -char const *Noise::Name() const -{ - return NAME; -} - -void Noise::SwitchMode(CameraMode const &camera_mode, - [[maybe_unused]] Metadata *metadata) -{ - // For example, we would expect a 2x2 binned mode to have a "noise - // factor" of sqrt(2x2) = 2. (can't be less than one, right?) - mode_factor_ = std::max(1.0, camera_mode.noise_factor); -} - -void Noise::Read(boost::property_tree::ptree const ¶ms) -{ - reference_constant_ = params.get<double>("reference_constant"); - reference_slope_ = params.get<double>("reference_slope"); -} - -void Noise::Prepare(Metadata *image_metadata) -{ - struct DeviceStatus device_status; - device_status.analogue_gain = 1.0; // keep compiler calm - if (image_metadata->Get("device.status", device_status) == 0) { - // There is a slight question as to exactly how the noise - // profile, specifically the constant part of it, scales. For - // now we assume it all scales the same, and we'll revisit this - // if it proves substantially wrong. NOTE: we may also want to - // make some adjustments based on the camera mode (such as - // binning), if we knew how to discover it... - double factor = sqrt(device_status.analogue_gain) / mode_factor_; - struct NoiseStatus status; - status.noise_constant = reference_constant_ * factor; - status.noise_slope = reference_slope_ * factor; - image_metadata->Set("noise.status", status); - LOG(RPiNoise, Debug) - << "constant " << status.noise_constant - << " slope " << status.noise_slope; - } else - LOG(RPiNoise, Warning) << " no metadata"; -} - -// Register algorithm with the system. -static Algorithm *Create(Controller *controller) -{ - return new Noise(controller); -} -static RegisterAlgorithm reg(NAME, &Create); diff --git a/src/ipa/raspberrypi/controller/rpi/noise.hpp b/src/ipa/raspberrypi/controller/rpi/noise.hpp deleted file mode 100644 index 1c9de5c8..00000000 --- a/src/ipa/raspberrypi/controller/rpi/noise.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * noise.hpp - Noise control algorithm - */ -#pragma once - -#include "../algorithm.hpp" -#include "../noise_status.h" - -// This is our implementation of the "noise algorithm". - -namespace RPiController { - -class Noise : public Algorithm -{ -public: - Noise(Controller *controller); - char const *Name() const override; - void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override; - void Read(boost::property_tree::ptree const ¶ms) override; - void Prepare(Metadata *image_metadata) override; - -private: - // the noise profile for analogue gain of 1.0 - double reference_constant_; - double reference_slope_; - double mode_factor_; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/rpi/sdn.cpp b/src/ipa/raspberrypi/controller/rpi/sdn.cpp deleted file mode 100644 index 93845509..00000000 --- a/src/ipa/raspberrypi/controller/rpi/sdn.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019-2021, Raspberry Pi (Trading) Limited - * - * sdn.cpp - SDN (spatial denoise) control algorithm - */ - -#include <libcamera/base/log.h> - -#include "../denoise_status.h" -#include "../noise_status.h" - -#include "sdn.hpp" - -using namespace RPiController; -using namespace libcamera; - -LOG_DEFINE_CATEGORY(RPiSdn) - -// Calculate settings for the spatial denoise block using the noise profile in -// the image metadata. - -#define NAME "rpi.sdn" - -Sdn::Sdn(Controller *controller) - : DenoiseAlgorithm(controller), mode_(DenoiseMode::ColourOff) -{ -} - -char const *Sdn::Name() const -{ - return NAME; -} - -void Sdn::Read(boost::property_tree::ptree const ¶ms) -{ - deviation_ = params.get<double>("deviation", 3.2); - strength_ = params.get<double>("strength", 0.75); -} - -void Sdn::Initialise() {} - -void Sdn::Prepare(Metadata *image_metadata) -{ - struct NoiseStatus noise_status = {}; - noise_status.noise_slope = 3.0; // in case no metadata - if (image_metadata->Get("noise.status", noise_status) != 0) - LOG(RPiSdn, Warning) << "no noise profile found"; - LOG(RPiSdn, Debug) - << "Noise profile: constant " << noise_status.noise_constant - << " slope " << noise_status.noise_slope; - struct DenoiseStatus status; - status.noise_constant = noise_status.noise_constant * deviation_; - status.noise_slope = noise_status.noise_slope * deviation_; - status.strength = strength_; - status.mode = static_cast<std::underlying_type_t<DenoiseMode>>(mode_); - image_metadata->Set("denoise.status", status); - LOG(RPiSdn, Debug) - << "programmed constant " << status.noise_constant - << " slope " << status.noise_slope - << " strength " << status.strength; -} - -void Sdn::SetMode(DenoiseMode mode) -{ - // We only distinguish between off and all other modes. - mode_ = mode; -} - -// Register algorithm with the system. -static Algorithm *Create(Controller *controller) -{ - return (Algorithm *)new Sdn(controller); -} -static RegisterAlgorithm reg(NAME, &Create); diff --git a/src/ipa/raspberrypi/controller/rpi/sdn.hpp b/src/ipa/raspberrypi/controller/rpi/sdn.hpp deleted file mode 100644 index 2371ce04..00000000 --- a/src/ipa/raspberrypi/controller/rpi/sdn.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * sdn.hpp - SDN (spatial denoise) control algorithm - */ -#pragma once - -#include "../algorithm.hpp" -#include "../denoise_algorithm.hpp" - -namespace RPiController { - -// Algorithm to calculate correct spatial denoise (SDN) settings. - -class Sdn : public DenoiseAlgorithm -{ -public: - Sdn(Controller *controller = NULL); - char const *Name() const override; - void Read(boost::property_tree::ptree const ¶ms) override; - void Initialise() override; - void Prepare(Metadata *image_metadata) override; - void SetMode(DenoiseMode mode) override; - -private: - double deviation_; - double strength_; - DenoiseMode mode_; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/rpi/sharpen.cpp b/src/ipa/raspberrypi/controller/rpi/sharpen.cpp deleted file mode 100644 index 18825a43..00000000 --- a/src/ipa/raspberrypi/controller/rpi/sharpen.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * sharpen.cpp - sharpening control algorithm - */ - -#include <math.h> - -#include <libcamera/base/log.h> - -#include "../sharpen_status.h" - -#include "sharpen.hpp" - -using namespace RPiController; -using namespace libcamera; - -LOG_DEFINE_CATEGORY(RPiSharpen) - -#define NAME "rpi.sharpen" - -Sharpen::Sharpen(Controller *controller) - : SharpenAlgorithm(controller), user_strength_(1.0) -{ -} - -char const *Sharpen::Name() const -{ - return NAME; -} - -void Sharpen::SwitchMode(CameraMode const &camera_mode, - [[maybe_unused]] Metadata *metadata) -{ - // can't be less than one, right? - mode_factor_ = std::max(1.0, camera_mode.noise_factor); -} - -void Sharpen::Read(boost::property_tree::ptree const ¶ms) -{ - threshold_ = params.get<double>("threshold", 1.0); - strength_ = params.get<double>("strength", 1.0); - limit_ = params.get<double>("limit", 1.0); - LOG(RPiSharpen, Debug) - << "Read threshold " << threshold_ - << " strength " << strength_ - << " limit " << limit_; -} - -void Sharpen::SetStrength(double strength) -{ - // Note that this function is how an application sets the overall - // sharpening "strength". We call this the "user strength" field - // as there already is a strength_ field - being an internal gain - // parameter that gets passed to the ISP control code. Negative - // values are not allowed - coerce them to zero (no sharpening). - user_strength_ = std::max(0.0, strength); -} - -void Sharpen::Prepare(Metadata *image_metadata) -{ - // The user_strength_ affects the algorithm's internal gain directly, but - // we adjust the limit and threshold less aggressively. Using a sqrt - // function is an arbitrary but gentle way of accomplishing this. - double user_strength_sqrt = sqrt(user_strength_); - struct SharpenStatus status; - // Binned modes seem to need the sharpening toned down with this - // pipeline, thus we use the mode_factor here. Also avoid - // divide-by-zero with the user_strength_sqrt. - status.threshold = threshold_ * mode_factor_ / - std::max(0.01, user_strength_sqrt); - status.strength = strength_ / mode_factor_ * user_strength_; - status.limit = limit_ / mode_factor_ * user_strength_sqrt; - // Finally, report any application-supplied parameters that were used. - status.user_strength = user_strength_; - image_metadata->Set("sharpen.status", status); -} - -// Register algorithm with the system. -static Algorithm *Create(Controller *controller) -{ - return new Sharpen(controller); -} -static RegisterAlgorithm reg(NAME, &Create); diff --git a/src/ipa/raspberrypi/controller/rpi/sharpen.hpp b/src/ipa/raspberrypi/controller/rpi/sharpen.hpp deleted file mode 100644 index 13a076a8..00000000 --- a/src/ipa/raspberrypi/controller/rpi/sharpen.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * sharpen.hpp - sharpening control algorithm - */ -#pragma once - -#include "../sharpen_algorithm.hpp" -#include "../sharpen_status.h" - -// This is our implementation of the "sharpen algorithm". - -namespace RPiController { - -class Sharpen : public SharpenAlgorithm -{ -public: - Sharpen(Controller *controller); - char const *Name() const override; - void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override; - void Read(boost::property_tree::ptree const ¶ms) override; - void SetStrength(double strength) override; - void Prepare(Metadata *image_metadata) override; - -private: - double threshold_; - double strength_; - double limit_; - double mode_factor_; - double user_strength_; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/sharpen_algorithm.hpp b/src/ipa/raspberrypi/controller/sharpen_algorithm.hpp deleted file mode 100644 index ca800308..00000000 --- a/src/ipa/raspberrypi/controller/sharpen_algorithm.hpp +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2020, Raspberry Pi (Trading) Limited - * - * sharpen_algorithm.hpp - sharpness control algorithm interface - */ -#pragma once - -#include "algorithm.hpp" - -namespace RPiController { - -class SharpenAlgorithm : public Algorithm -{ -public: - SharpenAlgorithm(Controller *controller) : Algorithm(controller) {} - // A sharpness control algorithm must provide the following: - virtual void SetStrength(double strength) = 0; -}; - -} // namespace RPiController diff --git a/src/ipa/raspberrypi/controller/sharpen_status.h b/src/ipa/raspberrypi/controller/sharpen_status.h deleted file mode 100644 index 7501b191..00000000 --- a/src/ipa/raspberrypi/controller/sharpen_status.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * sharpen_status.h - Sharpen control algorithm status - */ -#pragma once - -// The "sharpen" algorithm stores the strength to use. - -#ifdef __cplusplus -extern "C" { -#endif - -struct SharpenStatus { - // controls the smallest level of detail (or noise!) that sharpening will pick up - double threshold; - // the rate at which the sharpening response ramps once above the threshold - double strength; - // upper limit of the allowed sharpening response - double limit; - // The sharpening strength requested by the user or application. - double user_strength; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/ipa/raspberrypi/data/imx219.json b/src/ipa/raspberrypi/data/imx219.json deleted file mode 100644 index de59d936..00000000 --- a/src/ipa/raspberrypi/data/imx219.json +++ /dev/null @@ -1,412 +0,0 @@ -{ - "rpi.black_level": - { - "black_level": 4096 - }, - "rpi.dpc": - { - - }, - "rpi.lux": - { - "reference_shutter_speed": 27685, - "reference_gain": 1.0, - "reference_aperture": 1.0, - "reference_lux": 998, - "reference_Y": 12744 - }, - "rpi.noise": - { - "reference_constant": 0, - "reference_slope": 3.67 - }, - "rpi.geq": - { - "offset": 204, - "slope": 0.01633 - }, - "rpi.sdn": - { - - }, - "rpi.awb": - { - "priors": - [ - { - "lux": 0, "prior": - [ - 2000, 1.0, 3000, 0.0, 13000, 0.0 - ] - }, - { - "lux": 800, "prior": - [ - 2000, 0.0, 6000, 2.0, 13000, 2.0 - ] - }, - { - "lux": 1500, "prior": - [ - 2000, 0.0, 4000, 1.0, 6000, 6.0, 6500, 7.0, 7000, 1.0, 13000, 1.0 - ] - } - ], - "modes": - { - "auto": - { - "lo": 2500, - "hi": 8000 - }, - "incandescent": - { - "lo": 2500, - "hi": 3000 - }, - "tungsten": - { - "lo": 3000, - "hi": 3500 - }, - "fluorescent": - { - "lo": 4000, - "hi": 4700 - }, - "indoor": - { - "lo": 3000, - "hi": 5000 - }, - "daylight": - { - "lo": 5500, - "hi": 6500 - }, - "cloudy": - { - "lo": 7000, - "hi": 8600 - } - }, - "bayes": 1, - "ct_curve": - [ - 2498.0, 0.9309, 0.3599, 2911.0, 0.8682, 0.4283, 2919.0, 0.8358, 0.4621, 3627.0, 0.7646, 0.5327, 4600.0, 0.6079, 0.6721, 5716.0, - 0.5712, 0.7017, 8575.0, 0.4331, 0.8037 - ], - "sensitivity_r": 1.05, - "sensitivity_b": 1.05, - "transverse_pos": 0.04791, - "transverse_neg": 0.04881 - }, - "rpi.agc": - { - "metering_modes": - { - "centre-weighted": - { - "weights": - [ - 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 - ] - }, - "spot": - { - "weights": - [ - 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - }, - "matrix": - { - "weights": - [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - ] - } - }, - "exposure_modes": - { - "normal": - { - "shutter": - [ - 100, 10000, 30000, 60000, 66666 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "short": - { - "shutter": - [ - 100, 5000, 10000, 20000, 33333 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "long": - { - "shutter": - [ - 100, 10000, 30000, 60000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 12.0 - ] - } - }, - "constraint_modes": - { - "normal": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - } - ], - "highlight": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - }, - { - "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.8, 1000, 0.8 - ] - } - ], - "shadows": - [ - { - "bound": "LOWER", "q_lo": 0.0, "q_hi": 0.5, "y_target": - [ - 0, 0.17, 1000, 0.17 - ] - } - ] - }, - "y_target": - [ - 0, 0.16, 1000, 0.165, 10000, 0.17 - ] - }, - "rpi.alsc": - { - "omega": 1.3, - "n_iter": 100, - "luminance_strength": 0.7, - "calibrations_Cr": - [ - { - "ct": 3000, "table": - [ - 1.487, 1.481, 1.481, 1.445, 1.389, 1.327, 1.307, 1.307, 1.307, 1.309, 1.341, 1.405, 1.458, 1.494, 1.494, 1.497, - 1.491, 1.481, 1.448, 1.397, 1.331, 1.275, 1.243, 1.229, 1.229, 1.249, 1.287, 1.349, 1.409, 1.463, 1.494, 1.497, - 1.491, 1.469, 1.405, 1.331, 1.275, 1.217, 1.183, 1.172, 1.172, 1.191, 1.231, 1.287, 1.349, 1.424, 1.484, 1.499, - 1.487, 1.444, 1.363, 1.283, 1.217, 1.183, 1.148, 1.138, 1.138, 1.159, 1.191, 1.231, 1.302, 1.385, 1.461, 1.492, - 1.481, 1.423, 1.334, 1.253, 1.189, 1.148, 1.135, 1.119, 1.123, 1.137, 1.159, 1.203, 1.272, 1.358, 1.442, 1.488, - 1.479, 1.413, 1.321, 1.236, 1.176, 1.139, 1.118, 1.114, 1.116, 1.123, 1.149, 1.192, 1.258, 1.344, 1.432, 1.487, - 1.479, 1.413, 1.321, 1.236, 1.176, 1.139, 1.116, 1.114, 1.115, 1.123, 1.149, 1.192, 1.258, 1.344, 1.432, 1.487, - 1.479, 1.425, 1.336, 1.251, 1.189, 1.149, 1.136, 1.118, 1.121, 1.138, 1.158, 1.206, 1.275, 1.358, 1.443, 1.488, - 1.488, 1.448, 1.368, 1.285, 1.219, 1.189, 1.149, 1.139, 1.139, 1.158, 1.195, 1.235, 1.307, 1.387, 1.462, 1.493, - 1.496, 1.475, 1.411, 1.337, 1.284, 1.219, 1.189, 1.176, 1.176, 1.195, 1.235, 1.296, 1.356, 1.429, 1.487, 1.501, - 1.495, 1.489, 1.458, 1.407, 1.337, 1.287, 1.253, 1.239, 1.239, 1.259, 1.296, 1.356, 1.419, 1.472, 1.499, 1.499, - 1.494, 1.489, 1.489, 1.453, 1.398, 1.336, 1.317, 1.317, 1.317, 1.321, 1.351, 1.416, 1.467, 1.501, 1.501, 1.499 - ] - }, - { - "ct": 3850, "table": - [ - 1.694, 1.688, 1.688, 1.649, 1.588, 1.518, 1.495, 1.495, 1.495, 1.497, 1.532, 1.602, 1.659, 1.698, 1.698, 1.703, - 1.698, 1.688, 1.653, 1.597, 1.525, 1.464, 1.429, 1.413, 1.413, 1.437, 1.476, 1.542, 1.606, 1.665, 1.698, 1.703, - 1.697, 1.673, 1.605, 1.525, 1.464, 1.401, 1.369, 1.354, 1.354, 1.377, 1.417, 1.476, 1.542, 1.623, 1.687, 1.705, - 1.692, 1.646, 1.561, 1.472, 1.401, 1.368, 1.337, 1.323, 1.324, 1.348, 1.377, 1.417, 1.492, 1.583, 1.661, 1.697, - 1.686, 1.625, 1.528, 1.439, 1.372, 1.337, 1.321, 1.311, 1.316, 1.324, 1.348, 1.389, 1.461, 1.553, 1.642, 1.694, - 1.684, 1.613, 1.514, 1.423, 1.359, 1.328, 1.311, 1.306, 1.306, 1.316, 1.339, 1.378, 1.446, 1.541, 1.633, 1.693, - 1.684, 1.613, 1.514, 1.423, 1.359, 1.328, 1.311, 1.305, 1.305, 1.316, 1.339, 1.378, 1.446, 1.541, 1.633, 1.693, - 1.685, 1.624, 1.529, 1.438, 1.372, 1.336, 1.324, 1.309, 1.314, 1.323, 1.348, 1.392, 1.462, 1.555, 1.646, 1.694, - 1.692, 1.648, 1.561, 1.473, 1.403, 1.372, 1.336, 1.324, 1.324, 1.348, 1.378, 1.423, 1.495, 1.585, 1.667, 1.701, - 1.701, 1.677, 1.608, 1.527, 1.471, 1.403, 1.375, 1.359, 1.359, 1.378, 1.423, 1.488, 1.549, 1.631, 1.694, 1.709, - 1.702, 1.694, 1.656, 1.601, 1.527, 1.473, 1.441, 1.424, 1.424, 1.443, 1.488, 1.549, 1.621, 1.678, 1.706, 1.707, - 1.699, 1.694, 1.694, 1.654, 1.593, 1.525, 1.508, 1.508, 1.508, 1.509, 1.546, 1.614, 1.674, 1.708, 1.708, 1.707 - ] - }, - { - "ct": 6000, "table": - [ - 2.179, 2.176, 2.176, 2.125, 2.048, 1.975, 1.955, 1.954, 1.954, 1.956, 1.993, 2.071, 2.141, 2.184, 2.185, 2.188, - 2.189, 2.176, 2.128, 2.063, 1.973, 1.908, 1.872, 1.856, 1.856, 1.876, 1.922, 1.999, 2.081, 2.144, 2.184, 2.192, - 2.187, 2.152, 2.068, 1.973, 1.907, 1.831, 1.797, 1.786, 1.786, 1.804, 1.853, 1.922, 1.999, 2.089, 2.166, 2.191, - 2.173, 2.117, 2.013, 1.908, 1.831, 1.791, 1.755, 1.749, 1.749, 1.767, 1.804, 1.853, 1.939, 2.041, 2.135, 2.181, - 2.166, 2.089, 1.975, 1.869, 1.792, 1.755, 1.741, 1.731, 1.734, 1.749, 1.767, 1.818, 1.903, 2.005, 2.111, 2.173, - 2.165, 2.074, 1.956, 1.849, 1.777, 1.742, 1.729, 1.725, 1.729, 1.734, 1.758, 1.804, 1.884, 1.991, 2.099, 2.172, - 2.165, 2.074, 1.956, 1.849, 1.777, 1.742, 1.727, 1.724, 1.725, 1.734, 1.758, 1.804, 1.884, 1.991, 2.099, 2.172, - 2.166, 2.085, 1.975, 1.869, 1.791, 1.755, 1.741, 1.729, 1.733, 1.749, 1.769, 1.819, 1.904, 2.009, 2.114, 2.174, - 2.174, 2.118, 2.015, 1.913, 1.831, 1.791, 1.755, 1.749, 1.749, 1.769, 1.811, 1.855, 1.943, 2.047, 2.139, 2.183, - 2.187, 2.151, 2.072, 1.979, 1.911, 1.831, 1.801, 1.791, 1.791, 1.811, 1.855, 1.933, 2.006, 2.101, 2.173, 2.197, - 2.189, 2.178, 2.132, 2.069, 1.979, 1.913, 1.879, 1.867, 1.867, 1.891, 1.933, 2.006, 2.091, 2.156, 2.195, 2.197, - 2.181, 2.179, 2.178, 2.131, 2.057, 1.981, 1.965, 1.965, 1.965, 1.969, 1.999, 2.083, 2.153, 2.197, 2.197, 2.196 - ] - } - ], - "calibrations_Cb": - [ - { - "ct": 3000, "table": - [ - 1.967, 1.961, 1.955, 1.953, 1.954, 1.957, 1.961, 1.963, 1.963, 1.961, 1.959, 1.957, 1.954, 1.951, 1.951, 1.955, - 1.961, 1.959, 1.957, 1.956, 1.962, 1.967, 1.975, 1.979, 1.979, 1.975, 1.971, 1.967, 1.957, 1.952, 1.951, 1.951, - 1.959, 1.959, 1.959, 1.966, 1.976, 1.989, 1.999, 2.004, 2.003, 1.997, 1.991, 1.981, 1.967, 1.956, 1.951, 1.951, - 1.959, 1.962, 1.967, 1.978, 1.993, 2.009, 2.021, 2.028, 2.026, 2.021, 2.011, 1.995, 1.981, 1.964, 1.953, 1.951, - 1.961, 1.965, 1.977, 1.993, 2.009, 2.023, 2.041, 2.047, 2.047, 2.037, 2.024, 2.011, 1.995, 1.975, 1.958, 1.953, - 1.963, 1.968, 1.981, 2.001, 2.019, 2.039, 2.046, 2.052, 2.052, 2.051, 2.035, 2.021, 2.001, 1.978, 1.959, 1.955, - 1.961, 1.966, 1.981, 2.001, 2.019, 2.038, 2.043, 2.051, 2.052, 2.042, 2.034, 2.019, 2.001, 1.978, 1.959, 1.954, - 1.957, 1.961, 1.972, 1.989, 2.003, 2.021, 2.038, 2.039, 2.039, 2.034, 2.019, 2.004, 1.988, 1.971, 1.954, 1.949, - 1.952, 1.953, 1.959, 1.972, 1.989, 2.003, 2.016, 2.019, 2.019, 2.014, 2.003, 1.988, 1.971, 1.955, 1.948, 1.947, - 1.949, 1.948, 1.949, 1.957, 1.971, 1.978, 1.991, 1.994, 1.994, 1.989, 1.979, 1.967, 1.954, 1.946, 1.947, 1.947, - 1.949, 1.946, 1.944, 1.946, 1.949, 1.954, 1.962, 1.967, 1.967, 1.963, 1.956, 1.948, 1.943, 1.943, 1.946, 1.949, - 1.951, 1.946, 1.944, 1.942, 1.943, 1.943, 1.947, 1.948, 1.949, 1.947, 1.945, 1.941, 1.938, 1.939, 1.948, 1.952 - ] - }, - { - "ct": 3850, "table": - [ - 1.726, 1.724, 1.722, 1.723, 1.731, 1.735, 1.743, 1.746, 1.746, 1.741, 1.735, 1.729, 1.725, 1.721, 1.721, 1.721, - 1.724, 1.723, 1.723, 1.727, 1.735, 1.744, 1.749, 1.756, 1.756, 1.749, 1.744, 1.735, 1.727, 1.719, 1.719, 1.719, - 1.723, 1.723, 1.724, 1.735, 1.746, 1.759, 1.767, 1.775, 1.775, 1.766, 1.758, 1.746, 1.735, 1.723, 1.718, 1.716, - 1.723, 1.725, 1.732, 1.746, 1.759, 1.775, 1.782, 1.792, 1.792, 1.782, 1.772, 1.759, 1.745, 1.729, 1.718, 1.716, - 1.725, 1.729, 1.738, 1.756, 1.775, 1.785, 1.796, 1.803, 1.804, 1.794, 1.783, 1.772, 1.757, 1.736, 1.722, 1.718, - 1.728, 1.731, 1.741, 1.759, 1.781, 1.795, 1.803, 1.806, 1.808, 1.805, 1.791, 1.779, 1.762, 1.739, 1.722, 1.721, - 1.727, 1.731, 1.741, 1.759, 1.781, 1.791, 1.799, 1.804, 1.806, 1.801, 1.791, 1.779, 1.762, 1.739, 1.722, 1.717, - 1.722, 1.724, 1.733, 1.751, 1.768, 1.781, 1.791, 1.796, 1.799, 1.791, 1.781, 1.766, 1.754, 1.731, 1.717, 1.714, - 1.718, 1.718, 1.724, 1.737, 1.752, 1.768, 1.776, 1.782, 1.784, 1.781, 1.766, 1.754, 1.737, 1.724, 1.713, 1.709, - 1.716, 1.715, 1.716, 1.725, 1.737, 1.749, 1.756, 1.763, 1.764, 1.762, 1.749, 1.737, 1.724, 1.717, 1.709, 1.708, - 1.715, 1.714, 1.712, 1.715, 1.722, 1.729, 1.736, 1.741, 1.742, 1.739, 1.731, 1.723, 1.717, 1.712, 1.711, 1.709, - 1.716, 1.714, 1.711, 1.712, 1.715, 1.719, 1.723, 1.728, 1.731, 1.729, 1.723, 1.718, 1.711, 1.711, 1.713, 1.713 - ] - }, - { - "ct": 6000, "table": - [ - 1.374, 1.372, 1.373, 1.374, 1.375, 1.378, 1.378, 1.381, 1.382, 1.382, 1.378, 1.373, 1.372, 1.369, 1.365, 1.365, - 1.371, 1.371, 1.372, 1.374, 1.378, 1.381, 1.384, 1.386, 1.388, 1.387, 1.384, 1.377, 1.372, 1.368, 1.364, 1.362, - 1.369, 1.371, 1.372, 1.377, 1.383, 1.391, 1.394, 1.396, 1.397, 1.395, 1.391, 1.382, 1.374, 1.369, 1.362, 1.361, - 1.369, 1.371, 1.375, 1.383, 1.391, 1.399, 1.402, 1.404, 1.405, 1.403, 1.398, 1.391, 1.379, 1.371, 1.363, 1.361, - 1.371, 1.373, 1.378, 1.388, 1.399, 1.407, 1.411, 1.413, 1.413, 1.411, 1.405, 1.397, 1.385, 1.374, 1.366, 1.362, - 1.371, 1.374, 1.379, 1.389, 1.405, 1.411, 1.414, 1.414, 1.415, 1.415, 1.411, 1.401, 1.388, 1.376, 1.367, 1.363, - 1.371, 1.373, 1.379, 1.389, 1.405, 1.408, 1.413, 1.414, 1.414, 1.413, 1.409, 1.401, 1.388, 1.376, 1.367, 1.362, - 1.366, 1.369, 1.374, 1.384, 1.396, 1.404, 1.407, 1.408, 1.408, 1.408, 1.401, 1.395, 1.382, 1.371, 1.363, 1.359, - 1.364, 1.365, 1.368, 1.375, 1.386, 1.396, 1.399, 1.401, 1.399, 1.399, 1.395, 1.385, 1.374, 1.365, 1.359, 1.357, - 1.361, 1.363, 1.365, 1.368, 1.377, 1.384, 1.388, 1.391, 1.391, 1.388, 1.385, 1.375, 1.366, 1.361, 1.358, 1.356, - 1.361, 1.362, 1.362, 1.364, 1.367, 1.373, 1.376, 1.377, 1.377, 1.375, 1.373, 1.366, 1.362, 1.358, 1.358, 1.358, - 1.361, 1.362, 1.362, 1.362, 1.363, 1.367, 1.369, 1.368, 1.367, 1.367, 1.367, 1.364, 1.358, 1.357, 1.358, 1.359 - ] - } - ], - "luminance_lut": - [ - 2.716, 2.568, 2.299, 2.065, 1.845, 1.693, 1.605, 1.597, 1.596, 1.634, 1.738, 1.914, 2.145, 2.394, 2.719, 2.901, - 2.593, 2.357, 2.093, 1.876, 1.672, 1.528, 1.438, 1.393, 1.394, 1.459, 1.569, 1.731, 1.948, 2.169, 2.481, 2.756, - 2.439, 2.197, 1.922, 1.691, 1.521, 1.365, 1.266, 1.222, 1.224, 1.286, 1.395, 1.573, 1.747, 1.988, 2.299, 2.563, - 2.363, 2.081, 1.797, 1.563, 1.376, 1.244, 1.152, 1.099, 1.101, 1.158, 1.276, 1.421, 1.607, 1.851, 2.163, 2.455, - 2.342, 2.003, 1.715, 1.477, 1.282, 1.152, 1.074, 1.033, 1.035, 1.083, 1.163, 1.319, 1.516, 1.759, 2.064, 2.398, - 2.342, 1.985, 1.691, 1.446, 1.249, 1.111, 1.034, 1.004, 1.004, 1.028, 1.114, 1.274, 1.472, 1.716, 2.019, 2.389, - 2.342, 1.991, 1.691, 1.446, 1.249, 1.112, 1.034, 1.011, 1.005, 1.035, 1.114, 1.274, 1.472, 1.716, 2.019, 2.389, - 2.365, 2.052, 1.751, 1.499, 1.299, 1.171, 1.089, 1.039, 1.042, 1.084, 1.162, 1.312, 1.516, 1.761, 2.059, 2.393, - 2.434, 2.159, 1.856, 1.601, 1.403, 1.278, 1.166, 1.114, 1.114, 1.162, 1.266, 1.402, 1.608, 1.847, 2.146, 2.435, - 2.554, 2.306, 2.002, 1.748, 1.563, 1.396, 1.299, 1.247, 1.243, 1.279, 1.386, 1.551, 1.746, 1.977, 2.272, 2.518, - 2.756, 2.493, 2.195, 1.947, 1.739, 1.574, 1.481, 1.429, 1.421, 1.457, 1.559, 1.704, 1.929, 2.159, 2.442, 2.681, - 2.935, 2.739, 2.411, 2.151, 1.922, 1.749, 1.663, 1.628, 1.625, 1.635, 1.716, 1.872, 2.113, 2.368, 2.663, 2.824 - ], - "sigma": 0.00381, - "sigma_Cb": 0.00216 - }, - "rpi.contrast": - { - "ce_enable": 1, - "gamma_curve": - [ - 0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120, 18051, 6144, 20790, 7168, 23193, - 8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168, - 16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753, 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796, - 32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954, 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476, - 65535, 65535 - ] - }, - "rpi.ccm": - { - "ccms": - [ - { - "ct": 2498, "ccm": - [ - 1.58731, -0.18011, -0.40721, -0.60639, 2.03422, -0.42782, -0.19612, -1.69203, 2.88815 - ] - }, - { - "ct": 2811, "ccm": - [ - 1.61593, -0.33164, -0.28429, -0.55048, 1.97779, -0.42731, -0.12042, -1.42847, 2.54889 - ] - }, - { - "ct": 2911, "ccm": - [ - 1.62771, -0.41282, -0.21489, -0.57991, 2.04176, -0.46186, -0.07613, -1.13359, 2.20972 - ] - }, - { - "ct": 2919, "ccm": - [ - 1.62661, -0.37736, -0.24925, -0.52519, 1.95233, -0.42714, -0.10842, -1.34929, 2.45771 - ] - }, - { - "ct": 3627, "ccm": - [ - 1.70385, -0.57231, -0.13154, -0.47763, 1.85998, -0.38235, -0.07467, -0.82678, 1.90145 - ] - }, - { - "ct": 4600, "ccm": - [ - 1.68486, -0.61085, -0.07402, -0.41927, 2.04016, -0.62089, -0.08633, -0.67672, 1.76305 - ] - }, - { - "ct": 5716, "ccm": - [ - 1.80439, -0.73699, -0.06739, -0.36073, 1.83327, -0.47255, -0.08378, -0.56403, 1.64781 - ] - }, - { - "ct": 8575, "ccm": - [ - 1.89357, -0.76427, -0.12931, -0.27399, 2.15605, -0.88206, -0.12035, -0.68256, 1.80292 - ] - } - ] - }, - "rpi.sharpen": - { - - }, - "rpi.dpc": - { - - } -} diff --git a/src/ipa/raspberrypi/data/imx219_noir.json b/src/ipa/raspberrypi/data/imx219_noir.json deleted file mode 100644 index 9a3f03ec..00000000 --- a/src/ipa/raspberrypi/data/imx219_noir.json +++ /dev/null @@ -1,344 +0,0 @@ -{ - "rpi.black_level": - { - "black_level": 4096 - }, - "rpi.dpc": - { - - }, - "rpi.lux": - { - "reference_shutter_speed": 27685, - "reference_gain": 1.0, - "reference_aperture": 1.0, - "reference_lux": 998, - "reference_Y": 12744 - }, - "rpi.noise": - { - "reference_constant": 0, - "reference_slope": 3.67 - }, - "rpi.geq": - { - "offset": 204, - "slope": 0.01633 - }, - "rpi.sdn": - { - - }, - "rpi.awb": - { - "bayes": 0 - }, - "rpi.agc": - { - "metering_modes": - { - "centre-weighted": - { - "weights": - [ - 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 - ] - }, - "spot": - { - "weights": - [ - 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - }, - "matrix": - { - "weights": - [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - ] - } - }, - "exposure_modes": - { - "normal": - { - "shutter": - [ - 100, 10000, 30000, 60000, 66666 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "short": - { - "shutter": - [ - 100, 5000, 10000, 20000, 33333 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "long": - { - "shutter": - [ - 100, 10000, 30000, 60000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 12.0 - ] - } - }, - "constraint_modes": - { - "normal": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - } - ], - "highlight": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - }, - { - "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.8, 1000, 0.8 - ] - } - ], - "shadows": - [ - { - "bound": "LOWER", "q_lo": 0.0, "q_hi": 0.5, "y_target": - [ - 0, 0.17, 1000, 0.17 - ] - } - ] - }, - "y_target": - [ - 0, 0.16, 1000, 0.165, 10000, 0.17 - ] - }, - "rpi.alsc": - { - "omega": 1.3, - "n_iter": 100, - "luminance_strength": 0.7, - "calibrations_Cr": - [ - { - "ct": 3000, "table": - [ - 1.487, 1.481, 1.481, 1.445, 1.389, 1.327, 1.307, 1.307, 1.307, 1.309, 1.341, 1.405, 1.458, 1.494, 1.494, 1.497, - 1.491, 1.481, 1.448, 1.397, 1.331, 1.275, 1.243, 1.229, 1.229, 1.249, 1.287, 1.349, 1.409, 1.463, 1.494, 1.497, - 1.491, 1.469, 1.405, 1.331, 1.275, 1.217, 1.183, 1.172, 1.172, 1.191, 1.231, 1.287, 1.349, 1.424, 1.484, 1.499, - 1.487, 1.444, 1.363, 1.283, 1.217, 1.183, 1.148, 1.138, 1.138, 1.159, 1.191, 1.231, 1.302, 1.385, 1.461, 1.492, - 1.481, 1.423, 1.334, 1.253, 1.189, 1.148, 1.135, 1.119, 1.123, 1.137, 1.159, 1.203, 1.272, 1.358, 1.442, 1.488, - 1.479, 1.413, 1.321, 1.236, 1.176, 1.139, 1.118, 1.114, 1.116, 1.123, 1.149, 1.192, 1.258, 1.344, 1.432, 1.487, - 1.479, 1.413, 1.321, 1.236, 1.176, 1.139, 1.116, 1.114, 1.115, 1.123, 1.149, 1.192, 1.258, 1.344, 1.432, 1.487, - 1.479, 1.425, 1.336, 1.251, 1.189, 1.149, 1.136, 1.118, 1.121, 1.138, 1.158, 1.206, 1.275, 1.358, 1.443, 1.488, - 1.488, 1.448, 1.368, 1.285, 1.219, 1.189, 1.149, 1.139, 1.139, 1.158, 1.195, 1.235, 1.307, 1.387, 1.462, 1.493, - 1.496, 1.475, 1.411, 1.337, 1.284, 1.219, 1.189, 1.176, 1.176, 1.195, 1.235, 1.296, 1.356, 1.429, 1.487, 1.501, - 1.495, 1.489, 1.458, 1.407, 1.337, 1.287, 1.253, 1.239, 1.239, 1.259, 1.296, 1.356, 1.419, 1.472, 1.499, 1.499, - 1.494, 1.489, 1.489, 1.453, 1.398, 1.336, 1.317, 1.317, 1.317, 1.321, 1.351, 1.416, 1.467, 1.501, 1.501, 1.499 - ] - }, - { - "ct": 3850, "table": - [ - 1.694, 1.688, 1.688, 1.649, 1.588, 1.518, 1.495, 1.495, 1.495, 1.497, 1.532, 1.602, 1.659, 1.698, 1.698, 1.703, - 1.698, 1.688, 1.653, 1.597, 1.525, 1.464, 1.429, 1.413, 1.413, 1.437, 1.476, 1.542, 1.606, 1.665, 1.698, 1.703, - 1.697, 1.673, 1.605, 1.525, 1.464, 1.401, 1.369, 1.354, 1.354, 1.377, 1.417, 1.476, 1.542, 1.623, 1.687, 1.705, - 1.692, 1.646, 1.561, 1.472, 1.401, 1.368, 1.337, 1.323, 1.324, 1.348, 1.377, 1.417, 1.492, 1.583, 1.661, 1.697, - 1.686, 1.625, 1.528, 1.439, 1.372, 1.337, 1.321, 1.311, 1.316, 1.324, 1.348, 1.389, 1.461, 1.553, 1.642, 1.694, - 1.684, 1.613, 1.514, 1.423, 1.359, 1.328, 1.311, 1.306, 1.306, 1.316, 1.339, 1.378, 1.446, 1.541, 1.633, 1.693, - 1.684, 1.613, 1.514, 1.423, 1.359, 1.328, 1.311, 1.305, 1.305, 1.316, 1.339, 1.378, 1.446, 1.541, 1.633, 1.693, - 1.685, 1.624, 1.529, 1.438, 1.372, 1.336, 1.324, 1.309, 1.314, 1.323, 1.348, 1.392, 1.462, 1.555, 1.646, 1.694, - 1.692, 1.648, 1.561, 1.473, 1.403, 1.372, 1.336, 1.324, 1.324, 1.348, 1.378, 1.423, 1.495, 1.585, 1.667, 1.701, - 1.701, 1.677, 1.608, 1.527, 1.471, 1.403, 1.375, 1.359, 1.359, 1.378, 1.423, 1.488, 1.549, 1.631, 1.694, 1.709, - 1.702, 1.694, 1.656, 1.601, 1.527, 1.473, 1.441, 1.424, 1.424, 1.443, 1.488, 1.549, 1.621, 1.678, 1.706, 1.707, - 1.699, 1.694, 1.694, 1.654, 1.593, 1.525, 1.508, 1.508, 1.508, 1.509, 1.546, 1.614, 1.674, 1.708, 1.708, 1.707 - ] - }, - { - "ct": 6000, "table": - [ - 2.179, 2.176, 2.176, 2.125, 2.048, 1.975, 1.955, 1.954, 1.954, 1.956, 1.993, 2.071, 2.141, 2.184, 2.185, 2.188, - 2.189, 2.176, 2.128, 2.063, 1.973, 1.908, 1.872, 1.856, 1.856, 1.876, 1.922, 1.999, 2.081, 2.144, 2.184, 2.192, - 2.187, 2.152, 2.068, 1.973, 1.907, 1.831, 1.797, 1.786, 1.786, 1.804, 1.853, 1.922, 1.999, 2.089, 2.166, 2.191, - 2.173, 2.117, 2.013, 1.908, 1.831, 1.791, 1.755, 1.749, 1.749, 1.767, 1.804, 1.853, 1.939, 2.041, 2.135, 2.181, - 2.166, 2.089, 1.975, 1.869, 1.792, 1.755, 1.741, 1.731, 1.734, 1.749, 1.767, 1.818, 1.903, 2.005, 2.111, 2.173, - 2.165, 2.074, 1.956, 1.849, 1.777, 1.742, 1.729, 1.725, 1.729, 1.734, 1.758, 1.804, 1.884, 1.991, 2.099, 2.172, - 2.165, 2.074, 1.956, 1.849, 1.777, 1.742, 1.727, 1.724, 1.725, 1.734, 1.758, 1.804, 1.884, 1.991, 2.099, 2.172, - 2.166, 2.085, 1.975, 1.869, 1.791, 1.755, 1.741, 1.729, 1.733, 1.749, 1.769, 1.819, 1.904, 2.009, 2.114, 2.174, - 2.174, 2.118, 2.015, 1.913, 1.831, 1.791, 1.755, 1.749, 1.749, 1.769, 1.811, 1.855, 1.943, 2.047, 2.139, 2.183, - 2.187, 2.151, 2.072, 1.979, 1.911, 1.831, 1.801, 1.791, 1.791, 1.811, 1.855, 1.933, 2.006, 2.101, 2.173, 2.197, - 2.189, 2.178, 2.132, 2.069, 1.979, 1.913, 1.879, 1.867, 1.867, 1.891, 1.933, 2.006, 2.091, 2.156, 2.195, 2.197, - 2.181, 2.179, 2.178, 2.131, 2.057, 1.981, 1.965, 1.965, 1.965, 1.969, 1.999, 2.083, 2.153, 2.197, 2.197, 2.196 - ] - } - ], - "calibrations_Cb": - [ - { - "ct": 3000, "table": - [ - 1.967, 1.961, 1.955, 1.953, 1.954, 1.957, 1.961, 1.963, 1.963, 1.961, 1.959, 1.957, 1.954, 1.951, 1.951, 1.955, - 1.961, 1.959, 1.957, 1.956, 1.962, 1.967, 1.975, 1.979, 1.979, 1.975, 1.971, 1.967, 1.957, 1.952, 1.951, 1.951, - 1.959, 1.959, 1.959, 1.966, 1.976, 1.989, 1.999, 2.004, 2.003, 1.997, 1.991, 1.981, 1.967, 1.956, 1.951, 1.951, - 1.959, 1.962, 1.967, 1.978, 1.993, 2.009, 2.021, 2.028, 2.026, 2.021, 2.011, 1.995, 1.981, 1.964, 1.953, 1.951, - 1.961, 1.965, 1.977, 1.993, 2.009, 2.023, 2.041, 2.047, 2.047, 2.037, 2.024, 2.011, 1.995, 1.975, 1.958, 1.953, - 1.963, 1.968, 1.981, 2.001, 2.019, 2.039, 2.046, 2.052, 2.052, 2.051, 2.035, 2.021, 2.001, 1.978, 1.959, 1.955, - 1.961, 1.966, 1.981, 2.001, 2.019, 2.038, 2.043, 2.051, 2.052, 2.042, 2.034, 2.019, 2.001, 1.978, 1.959, 1.954, - 1.957, 1.961, 1.972, 1.989, 2.003, 2.021, 2.038, 2.039, 2.039, 2.034, 2.019, 2.004, 1.988, 1.971, 1.954, 1.949, - 1.952, 1.953, 1.959, 1.972, 1.989, 2.003, 2.016, 2.019, 2.019, 2.014, 2.003, 1.988, 1.971, 1.955, 1.948, 1.947, - 1.949, 1.948, 1.949, 1.957, 1.971, 1.978, 1.991, 1.994, 1.994, 1.989, 1.979, 1.967, 1.954, 1.946, 1.947, 1.947, - 1.949, 1.946, 1.944, 1.946, 1.949, 1.954, 1.962, 1.967, 1.967, 1.963, 1.956, 1.948, 1.943, 1.943, 1.946, 1.949, - 1.951, 1.946, 1.944, 1.942, 1.943, 1.943, 1.947, 1.948, 1.949, 1.947, 1.945, 1.941, 1.938, 1.939, 1.948, 1.952 - ] - }, - { - "ct": 3850, "table": - [ - 1.726, 1.724, 1.722, 1.723, 1.731, 1.735, 1.743, 1.746, 1.746, 1.741, 1.735, 1.729, 1.725, 1.721, 1.721, 1.721, - 1.724, 1.723, 1.723, 1.727, 1.735, 1.744, 1.749, 1.756, 1.756, 1.749, 1.744, 1.735, 1.727, 1.719, 1.719, 1.719, - 1.723, 1.723, 1.724, 1.735, 1.746, 1.759, 1.767, 1.775, 1.775, 1.766, 1.758, 1.746, 1.735, 1.723, 1.718, 1.716, - 1.723, 1.725, 1.732, 1.746, 1.759, 1.775, 1.782, 1.792, 1.792, 1.782, 1.772, 1.759, 1.745, 1.729, 1.718, 1.716, - 1.725, 1.729, 1.738, 1.756, 1.775, 1.785, 1.796, 1.803, 1.804, 1.794, 1.783, 1.772, 1.757, 1.736, 1.722, 1.718, - 1.728, 1.731, 1.741, 1.759, 1.781, 1.795, 1.803, 1.806, 1.808, 1.805, 1.791, 1.779, 1.762, 1.739, 1.722, 1.721, - 1.727, 1.731, 1.741, 1.759, 1.781, 1.791, 1.799, 1.804, 1.806, 1.801, 1.791, 1.779, 1.762, 1.739, 1.722, 1.717, - 1.722, 1.724, 1.733, 1.751, 1.768, 1.781, 1.791, 1.796, 1.799, 1.791, 1.781, 1.766, 1.754, 1.731, 1.717, 1.714, - 1.718, 1.718, 1.724, 1.737, 1.752, 1.768, 1.776, 1.782, 1.784, 1.781, 1.766, 1.754, 1.737, 1.724, 1.713, 1.709, - 1.716, 1.715, 1.716, 1.725, 1.737, 1.749, 1.756, 1.763, 1.764, 1.762, 1.749, 1.737, 1.724, 1.717, 1.709, 1.708, - 1.715, 1.714, 1.712, 1.715, 1.722, 1.729, 1.736, 1.741, 1.742, 1.739, 1.731, 1.723, 1.717, 1.712, 1.711, 1.709, - 1.716, 1.714, 1.711, 1.712, 1.715, 1.719, 1.723, 1.728, 1.731, 1.729, 1.723, 1.718, 1.711, 1.711, 1.713, 1.713 - ] - }, - { - "ct": 6000, "table": - [ - 1.374, 1.372, 1.373, 1.374, 1.375, 1.378, 1.378, 1.381, 1.382, 1.382, 1.378, 1.373, 1.372, 1.369, 1.365, 1.365, - 1.371, 1.371, 1.372, 1.374, 1.378, 1.381, 1.384, 1.386, 1.388, 1.387, 1.384, 1.377, 1.372, 1.368, 1.364, 1.362, - 1.369, 1.371, 1.372, 1.377, 1.383, 1.391, 1.394, 1.396, 1.397, 1.395, 1.391, 1.382, 1.374, 1.369, 1.362, 1.361, - 1.369, 1.371, 1.375, 1.383, 1.391, 1.399, 1.402, 1.404, 1.405, 1.403, 1.398, 1.391, 1.379, 1.371, 1.363, 1.361, - 1.371, 1.373, 1.378, 1.388, 1.399, 1.407, 1.411, 1.413, 1.413, 1.411, 1.405, 1.397, 1.385, 1.374, 1.366, 1.362, - 1.371, 1.374, 1.379, 1.389, 1.405, 1.411, 1.414, 1.414, 1.415, 1.415, 1.411, 1.401, 1.388, 1.376, 1.367, 1.363, - 1.371, 1.373, 1.379, 1.389, 1.405, 1.408, 1.413, 1.414, 1.414, 1.413, 1.409, 1.401, 1.388, 1.376, 1.367, 1.362, - 1.366, 1.369, 1.374, 1.384, 1.396, 1.404, 1.407, 1.408, 1.408, 1.408, 1.401, 1.395, 1.382, 1.371, 1.363, 1.359, - 1.364, 1.365, 1.368, 1.375, 1.386, 1.396, 1.399, 1.401, 1.399, 1.399, 1.395, 1.385, 1.374, 1.365, 1.359, 1.357, - 1.361, 1.363, 1.365, 1.368, 1.377, 1.384, 1.388, 1.391, 1.391, 1.388, 1.385, 1.375, 1.366, 1.361, 1.358, 1.356, - 1.361, 1.362, 1.362, 1.364, 1.367, 1.373, 1.376, 1.377, 1.377, 1.375, 1.373, 1.366, 1.362, 1.358, 1.358, 1.358, - 1.361, 1.362, 1.362, 1.362, 1.363, 1.367, 1.369, 1.368, 1.367, 1.367, 1.367, 1.364, 1.358, 1.357, 1.358, 1.359 - ] - } - ], - "luminance_lut": - [ - 2.716, 2.568, 2.299, 2.065, 1.845, 1.693, 1.605, 1.597, 1.596, 1.634, 1.738, 1.914, 2.145, 2.394, 2.719, 2.901, - 2.593, 2.357, 2.093, 1.876, 1.672, 1.528, 1.438, 1.393, 1.394, 1.459, 1.569, 1.731, 1.948, 2.169, 2.481, 2.756, - 2.439, 2.197, 1.922, 1.691, 1.521, 1.365, 1.266, 1.222, 1.224, 1.286, 1.395, 1.573, 1.747, 1.988, 2.299, 2.563, - 2.363, 2.081, 1.797, 1.563, 1.376, 1.244, 1.152, 1.099, 1.101, 1.158, 1.276, 1.421, 1.607, 1.851, 2.163, 2.455, - 2.342, 2.003, 1.715, 1.477, 1.282, 1.152, 1.074, 1.033, 1.035, 1.083, 1.163, 1.319, 1.516, 1.759, 2.064, 2.398, - 2.342, 1.985, 1.691, 1.446, 1.249, 1.111, 1.034, 1.004, 1.004, 1.028, 1.114, 1.274, 1.472, 1.716, 2.019, 2.389, - 2.342, 1.991, 1.691, 1.446, 1.249, 1.112, 1.034, 1.011, 1.005, 1.035, 1.114, 1.274, 1.472, 1.716, 2.019, 2.389, - 2.365, 2.052, 1.751, 1.499, 1.299, 1.171, 1.089, 1.039, 1.042, 1.084, 1.162, 1.312, 1.516, 1.761, 2.059, 2.393, - 2.434, 2.159, 1.856, 1.601, 1.403, 1.278, 1.166, 1.114, 1.114, 1.162, 1.266, 1.402, 1.608, 1.847, 2.146, 2.435, - 2.554, 2.306, 2.002, 1.748, 1.563, 1.396, 1.299, 1.247, 1.243, 1.279, 1.386, 1.551, 1.746, 1.977, 2.272, 2.518, - 2.756, 2.493, 2.195, 1.947, 1.739, 1.574, 1.481, 1.429, 1.421, 1.457, 1.559, 1.704, 1.929, 2.159, 2.442, 2.681, - 2.935, 2.739, 2.411, 2.151, 1.922, 1.749, 1.663, 1.628, 1.625, 1.635, 1.716, 1.872, 2.113, 2.368, 2.663, 2.824 - ], - "sigma": 0.00381, - "sigma_Cb": 0.00216 - }, - "rpi.contrast": - { - "ce_enable": 1, - "gamma_curve": - [ - 0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120, 18051, 6144, 20790, 7168, 23193, - 8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168, - 16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753, 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796, - 32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954, 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476, - 65535, 65535 - ] - }, - "rpi.ccm": - { - "ccms": - [ - { - "ct": 2498, "ccm": - [ - 1.58731, -0.18011, -0.40721, -0.60639, 2.03422, -0.42782, -0.19612, -1.69203, 2.88815 - ] - }, - { - "ct": 2811, "ccm": - [ - 1.61593, -0.33164, -0.28429, -0.55048, 1.97779, -0.42731, -0.12042, -1.42847, 2.54889 - ] - }, - { - "ct": 2911, "ccm": - [ - 1.62771, -0.41282, -0.21489, -0.57991, 2.04176, -0.46186, -0.07613, -1.13359, 2.20972 - ] - }, - { - "ct": 2919, "ccm": - [ - 1.62661, -0.37736, -0.24925, -0.52519, 1.95233, -0.42714, -0.10842, -1.34929, 2.45771 - ] - }, - { - "ct": 3627, "ccm": - [ - 1.70385, -0.57231, -0.13154, -0.47763, 1.85998, -0.38235, -0.07467, -0.82678, 1.90145 - ] - }, - { - "ct": 4600, "ccm": - [ - 1.68486, -0.61085, -0.07402, -0.41927, 2.04016, -0.62089, -0.08633, -0.67672, 1.76305 - ] - }, - { - "ct": 5716, "ccm": - [ - 1.80439, -0.73699, -0.06739, -0.36073, 1.83327, -0.47255, -0.08378, -0.56403, 1.64781 - ] - }, - { - "ct": 8575, "ccm": - [ - 1.89357, -0.76427, -0.12931, -0.27399, 2.15605, -0.88206, -0.12035, -0.68256, 1.80292 - ] - } - ] - }, - "rpi.sharpen": - { - - }, - "rpi.dpc": - { - - } -} diff --git a/src/ipa/raspberrypi/data/imx290.json b/src/ipa/raspberrypi/data/imx290.json deleted file mode 100644 index 20b45c16..00000000 --- a/src/ipa/raspberrypi/data/imx290.json +++ /dev/null @@ -1,165 +0,0 @@ -{ - "rpi.black_level": - { - "black_level": 3840 - }, - "rpi.dpc": - { - }, - "rpi.lux": - { - "reference_shutter_speed": 6813, - "reference_gain": 1.0, - "reference_aperture": 1.0, - "reference_lux": 890, - "reference_Y": 12900 - }, - "rpi.noise": - { - "reference_constant": 0, - "reference_slope": 2.67 - }, - "rpi.geq": - { - "offset": 187, - "slope": 0.00842 - }, - "rpi.sdn": - { - }, - "rpi.awb": - { - "bayes": 0 - }, - "rpi.agc": - { - "speed": 0.2, - "metering_modes": - { - "matrix": - { - "weights": - [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - ] - }, - "centre-weighted": - { - "weights": - [ - 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 - ] - }, - "spot": - { - "weights": - [ - 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - } - }, - "exposure_modes": - { - "normal": - { - "shutter": - [ - 10, 30000, 60000 - ], - "gain": - [ - 1.0, 2.0, 8.0 - ] - }, - "sport": - { - "shutter": - [ - 10, 5000, 10000, 20000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - } - }, - "constraint_modes": - { - "normal": - [ - ], - "highlight": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - }, - { - "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.8, 1000, 0.8 - ] - } - ] - }, - "y_target": - [ - 0, 0.16, 1000, 0.16, 10000, 0.16 - ] - }, - "rpi.alsc": - { - "omega": 1.3, - "n_iter": 100, - "luminance_strength": 0.7, - "luminance_lut": - [ - 2.844, 2.349, 2.018, 1.775, 1.599, 1.466, 1.371, 1.321, 1.306, 1.316, 1.357, 1.439, 1.552, 1.705, 1.915, 2.221, - 2.576, 2.151, 1.851, 1.639, 1.478, 1.358, 1.272, 1.231, 1.218, 1.226, 1.262, 1.335, 1.438, 1.571, 1.766, 2.067, - 2.381, 2.005, 1.739, 1.545, 1.389, 1.278, 1.204, 1.166, 1.153, 1.161, 1.194, 1.263, 1.356, 1.489, 1.671, 1.943, - 2.242, 1.899, 1.658, 1.481, 1.329, 1.225, 1.156, 1.113, 1.096, 1.107, 1.143, 1.201, 1.289, 1.423, 1.607, 1.861, - 2.152, 1.831, 1.602, 1.436, 1.291, 1.193, 1.121, 1.069, 1.047, 1.062, 1.107, 1.166, 1.249, 1.384, 1.562, 1.801, - 2.104, 1.795, 1.572, 1.407, 1.269, 1.174, 1.099, 1.041, 1.008, 1.029, 1.083, 1.146, 1.232, 1.364, 1.547, 1.766, - 2.104, 1.796, 1.572, 1.403, 1.264, 1.171, 1.097, 1.036, 1.001, 1.025, 1.077, 1.142, 1.231, 1.363, 1.549, 1.766, - 2.148, 1.827, 1.594, 1.413, 1.276, 1.184, 1.114, 1.062, 1.033, 1.049, 1.092, 1.153, 1.242, 1.383, 1.577, 1.795, - 2.211, 1.881, 1.636, 1.455, 1.309, 1.214, 1.149, 1.104, 1.081, 1.089, 1.125, 1.184, 1.273, 1.423, 1.622, 1.846, - 2.319, 1.958, 1.698, 1.516, 1.362, 1.262, 1.203, 1.156, 1.137, 1.142, 1.171, 1.229, 1.331, 1.484, 1.682, 1.933, - 2.459, 2.072, 1.789, 1.594, 1.441, 1.331, 1.261, 1.219, 1.199, 1.205, 1.232, 1.301, 1.414, 1.571, 1.773, 2.052, - 2.645, 2.206, 1.928, 1.728, 1.559, 1.451, 1.352, 1.301, 1.282, 1.289, 1.319, 1.395, 1.519, 1.685, 1.904, 2.227 - ], - "sigma": 0.005, - "sigma_Cb": 0.005 - }, - "rpi.contrast": - { - "ce_enable": 1, - "gamma_curve": - [ - 0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120, 18051, 6144, 20790, 7168, 23193, - 8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168, - 16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753, 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796, - 32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954, 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476, - 65535, 65535 - ] - }, - "rpi.sharpen": - { - }, - "rpi.ccm": - { - "ccms": - [ - { - "ct": 3900, "ccm": - [ - 1.54659, -0.17707, -0.36953, -0.51471, 1.72733, -0.21262, 0.06667, -0.92279, 1.85612 - ] - } - ] - }, - "rpi.focus": - { - } -} diff --git a/src/ipa/raspberrypi/data/imx296.json b/src/ipa/raspberrypi/data/imx296.json deleted file mode 100644 index 837feff5..00000000 --- a/src/ipa/raspberrypi/data/imx296.json +++ /dev/null @@ -1,191 +0,0 @@ -{ - "rpi.black_level": - { - "black_level": 4096 - }, - "rpi.dpc": - { - }, - "rpi.lux": - { - "reference_shutter_speed": 19184, - "reference_gain": 1.0, - "reference_aperture": 1.0, - "reference_lux": 432, - "reference_Y": 13773 - }, - "rpi.noise": - { - "reference_constant": 0, - "reference_slope": 2.957 - }, - "rpi.geq": - { - "offset": 185, - "slope": 0.0105 - }, - "rpi.sdn": - { - }, - "rpi.agc": - { - "metering_modes": - { - "centre-weighted": - { - "weights": - [ - 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 - ] - }, - "spot": - { - "weights": - [ - 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - }, - "matrix": - { - "weights": - [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - ] - } - }, - "exposure_modes": - { - "normal": - { - "shutter": - [ - 100, 10000, 30000, 60000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 6.0 - ] - }, - "short": - { - "shutter": - [ - 100, 5000, 10000, 20000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 6.0 - ] - } - }, - "constraint_modes": - { - "normal": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - } - ], - "highlight": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - }, - { - "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.8, 1000, 0.8 - ] - } - ] - }, - "y_target": - [ - 0, 0.16, 1000, 0.165, 10000, 0.17 - ] - }, - "rpi.alsc": - { - "omega": 1.3, - "n_iter": 0, - "luminance_strength": 0.5, - "calibrations_Cr": - [ - { - "ct": 4000, "table": - [ - 2.554, 2.554, 2.541, 2.534, 2.495, 2.506, 2.516, 2.517, 2.518, 2.515, 2.513, 2.495, 2.481, 2.533, 2.533, 2.521, - 2.522, 2.534, 2.539, 2.531, 2.531, 2.506, 2.506, 2.513, 2.513, 2.509, 2.498, 2.496, 2.508, 2.517, 2.521, 2.521, - 2.509, 2.517, 2.534, 2.529, 2.531, 2.521, 2.517, 2.517, 2.515, 2.514, 2.506, 2.499, 2.508, 2.508, 2.521, 2.537, - 2.507, 2.508, 2.517, 2.516, 2.495, 2.487, 2.519, 2.534, 2.535, 2.531, 2.499, 2.494, 2.501, 2.511, 2.526, 2.526, - 2.509, 2.517, 2.507, 2.501, 2.494, 2.519, 2.539, 2.539, 2.537, 2.537, 2.533, 2.499, 2.503, 2.511, 2.529, 2.525, - 2.521, 2.522, 2.476, 2.501, 2.501, 2.539, 2.546, 2.538, 2.531, 2.538, 2.541, 2.531, 2.529, 2.526, 2.529, 2.525, - 2.516, 2.519, 2.469, 2.499, 2.499, 2.543, 2.543, 2.531, 2.528, 2.534, 2.541, 2.535, 2.531, 2.526, 2.531, 2.528, - 2.509, 2.515, 2.465, 2.487, 2.487, 2.539, 2.543, 2.539, 2.533, 2.549, 2.542, 2.531, 2.529, 2.524, 2.532, 2.533, - 2.499, 2.499, 2.475, 2.482, 2.471, 2.509, 2.539, 2.544, 2.543, 2.545, 2.533, 2.498, 2.521, 2.521, 2.537, 2.536, - 2.499, 2.488, 2.488, 2.488, 2.471, 2.462, 2.509, 2.539, 2.539, 2.532, 2.498, 2.498, 2.518, 2.518, 2.539, 2.539, - 2.483, 2.484, 2.488, 2.488, 2.502, 2.496, 2.508, 2.514, 2.518, 2.517, 2.521, 2.518, 2.518, 2.518, 2.525, 2.539, - 2.483, 2.487, 2.478, 2.478, 2.507, 2.509, 2.514, 2.513, 2.514, 2.517, 2.536, 2.559, 2.501, 2.501, 2.503, 2.525 - ] - } - ], - "calibrations_Cb": - [ - { - "ct": 4000, "table": - [ - 2.619, 2.603, 2.599, 2.597, 2.595, 2.594, 2.589, 2.587, 2.586, 2.589, 2.592, 2.597, 2.601, 2.608, 2.621, 2.621, - 2.619, 2.615, 2.603, 2.601, 2.596, 2.595, 2.591, 2.589, 2.589, 2.592, 2.599, 2.593, 2.601, 2.613, 2.622, 2.631, - 2.617, 2.617, 2.612, 2.611, 2.604, 2.598, 2.593, 2.591, 2.592, 2.591, 2.593, 2.595, 2.599, 2.614, 2.623, 2.631, - 2.624, 2.619, 2.615, 2.612, 2.605, 2.602, 2.597, 2.596, 2.592, 2.592, 2.595, 2.599, 2.602, 2.606, 2.619, 2.624, - 2.629, 2.627, 2.627, 2.617, 2.609, 2.598, 2.612, 2.623, 2.615, 2.604, 2.589, 2.595, 2.599, 2.608, 2.611, 2.614, - 2.629, 2.632, 2.637, 2.627, 2.612, 2.612, 2.629, 2.631, 2.628, 2.621, 2.604, 2.597, 2.598, 2.604, 2.609, 2.609, - 2.635, 2.636, 2.642, 2.628, 2.623, 2.623, 2.636, 2.636, 2.634, 2.628, 2.616, 2.599, 2.597, 2.601, 2.603, 2.601, - 2.641, 2.639, 2.646, 2.632, 2.627, 2.625, 2.632, 2.635, 2.634, 2.627, 2.614, 2.596, 2.595, 2.599, 2.599, 2.598, - 2.643, 2.644, 2.651, 2.649, 2.629, 2.617, 2.624, 2.629, 2.625, 2.614, 2.586, 2.599, 2.595, 2.597, 2.592, 2.595, - 2.645, 2.646, 2.649, 2.649, 2.638, 2.624, 2.616, 2.617, 2.609, 2.604, 2.603, 2.603, 2.595, 2.589, 2.587, 2.592, - 2.641, 2.643, 2.649, 2.647, 2.638, 2.618, 2.615, 2.608, 2.602, 2.595, 2.596, 2.595, 2.593, 2.584, 2.581, 2.583, - 2.638, 2.637, 2.647, 2.634, 2.634, 2.618, 2.621, 2.621, 2.611, 2.602, 2.596, 2.583, 2.581, 2.581, 2.576, 2.574 - ] - } - ], - "luminance_lut": - [ - 1.308, 1.293, 1.228, 1.175, 1.139, 1.108, 1.092, 1.082, 1.082, 1.086, 1.097, 1.114, 1.149, 1.199, 1.279, 1.303, - 1.293, 1.249, 1.199, 1.162, 1.136, 1.109, 1.087, 1.077, 1.072, 1.081, 1.095, 1.103, 1.133, 1.172, 1.225, 1.282, - 1.251, 1.212, 1.186, 1.159, 1.129, 1.114, 1.102, 1.088, 1.088, 1.088, 1.095, 1.117, 1.123, 1.158, 1.198, 1.249, - 1.223, 1.192, 1.177, 1.163, 1.147, 1.139, 1.132, 1.112, 1.111, 1.107, 1.113, 1.118, 1.139, 1.155, 1.186, 1.232, - 1.207, 1.186, 1.171, 1.162, 1.168, 1.163, 1.153, 1.138, 1.129, 1.128, 1.132, 1.136, 1.149, 1.167, 1.189, 1.216, - 1.198, 1.186, 1.176, 1.176, 1.177, 1.185, 1.171, 1.157, 1.146, 1.144, 1.146, 1.149, 1.161, 1.181, 1.201, 1.221, - 1.203, 1.181, 1.176, 1.178, 1.191, 1.189, 1.188, 1.174, 1.159, 1.153, 1.158, 1.161, 1.169, 1.185, 1.211, 1.227, - 1.211, 1.179, 1.177, 1.187, 1.194, 1.196, 1.194, 1.187, 1.176, 1.169, 1.171, 1.171, 1.175, 1.189, 1.214, 1.226, - 1.219, 1.182, 1.184, 1.191, 1.195, 1.199, 1.197, 1.194, 1.188, 1.185, 1.179, 1.179, 1.182, 1.194, 1.212, 1.227, - 1.237, 1.192, 1.194, 1.194, 1.198, 1.199, 1.198, 1.197, 1.196, 1.193, 1.189, 1.189, 1.192, 1.203, 1.214, 1.231, - 1.282, 1.199, 1.199, 1.197, 1.199, 1.199, 1.192, 1.193, 1.193, 1.194, 1.196, 1.197, 1.206, 1.216, 1.228, 1.244, - 1.309, 1.236, 1.204, 1.203, 1.202, 1.194, 1.194, 1.188, 1.192, 1.192, 1.199, 1.201, 1.212, 1.221, 1.235, 1.247 - ], - "sigma": 0.005, - "sigma_Cb": 0.005 - }, - "rpi.contrast": - { - "ce_enable": 1, - "gamma_curve": - [ - 0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120, 18051, 6144, 20790, 7168, 23193, - 8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168, - 16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753, 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796, - 32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954, 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476, - 65535, 65535 - ] - }, - "rpi.sharpen": - { - } -} diff --git a/src/ipa/raspberrypi/data/imx378.json b/src/ipa/raspberrypi/data/imx378.json deleted file mode 100644 index 66200345..00000000 --- a/src/ipa/raspberrypi/data/imx378.json +++ /dev/null @@ -1,338 +0,0 @@ -{ - "rpi.black_level": - { - "black_level": 4096 - }, - "rpi.dpc": - { - }, - "rpi.lux": - { - "reference_shutter_speed": 9999, - "reference_gain": 1.95, - "reference_aperture": 1.0, - "reference_lux": 1000, - "reference_Y": 12996 - }, - "rpi.noise": - { - "reference_constant": 0, - "reference_slope": 2.641 - }, - "rpi.geq": - { - "offset": 235, - "slope": 0.00902 - }, - "rpi.sdn": - { - }, - "rpi.awb": - { - "priors": - [ - { - "lux": 0, "prior": - [ - 2000, 1.0, 3000, 0.0, 13000, 0.0 - ] - }, - { - "lux": 800, "prior": - [ - 2000, 0.0, 6000, 2.0, 13000, 2.0 - ] - }, - { - "lux": 1500, "prior": - [ - 2000, 0.0, 4000, 1.0, 6000, 6.0, 6500, 7.0, 7000, 1.0, 13000, 1.0 - ] - } - ], - "modes": - { - "auto": - { - "lo": 2500, - "hi": 8000 - }, - "incandescent": - { - "lo": 2500, - "hi": 3000 - }, - "tungsten": - { - "lo": 3000, - "hi": 3500 - }, - "fluorescent": - { - "lo": 4000, - "hi": 4700 - }, - "indoor": - { - "lo": 3000, - "hi": 5000 - }, - "daylight": - { - "lo": 5500, - "hi": 6500 - }, - "cloudy": - { - "lo": 7000, - "hi": 8100 - } - }, - "bayes": 1, - "ct_curve": - [ - 2850.0, 0.6361, 0.3911, 3550.0, 0.5386, 0.5077, 4500.0, 0.4472, 0.6171, 5600.0, 0.3906, 0.6848, 8000.0, 0.3412, 0.7441 - ], - "sensitivity_r": 1.0, - "sensitivity_b": 1.0, - "transverse_pos": 0.01667, - "transverse_neg": 0.01195 - }, - "rpi.agc": - { - "metering_modes": - { - "centre-weighted": - { - "weights": - [ - 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 - ] - }, - "spot": - { - "weights": - [ - 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - }, - "matrix": - { - "weights": - [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - ] - } - }, - "exposure_modes": - { - "normal": - { - "shutter": - [ - 100, 10000, 30000, 60000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "short": - { - "shutter": - [ - 100, 5000, 10000, 20000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - } - }, - "constraint_modes": - { - "normal": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - } - ], - "highlight": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - }, - { - "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.8, 1000, 0.8 - ] - } - ] - }, - "y_target": - [ - 0, 0.16, 1000, 0.165, 10000, 0.17 - ] - }, - "rpi.alsc": - { - "omega": 1.3, - "n_iter": 100, - "luminance_strength": 0.5, - "calibrations_Cr": - [ - { - "ct": 2800, "table": - [ - 1.604, 1.601, 1.593, 1.581, 1.568, 1.561, 1.561, 1.561, 1.561, 1.567, 1.582, 1.596, 1.609, 1.622, 1.632, 1.636, - 1.601, 1.594, 1.586, 1.571, 1.555, 1.546, 1.543, 1.543, 1.547, 1.555, 1.572, 1.584, 1.599, 1.614, 1.625, 1.632, - 1.599, 1.586, 1.571, 1.555, 1.542, 1.528, 1.518, 1.518, 1.523, 1.537, 1.555, 1.572, 1.589, 1.607, 1.622, 1.629, - 1.597, 1.579, 1.561, 1.542, 1.528, 1.512, 1.493, 1.493, 1.499, 1.523, 1.537, 1.563, 1.582, 1.601, 1.619, 1.629, - 1.597, 1.577, 1.557, 1.535, 1.512, 1.493, 1.481, 1.479, 1.492, 1.499, 1.524, 1.555, 1.578, 1.599, 1.619, 1.629, - 1.597, 1.577, 1.557, 1.534, 1.508, 1.483, 1.476, 1.476, 1.481, 1.496, 1.522, 1.554, 1.578, 1.599, 1.619, 1.629, - 1.597, 1.578, 1.557, 1.534, 1.508, 1.483, 1.481, 1.479, 1.481, 1.496, 1.522, 1.554, 1.579, 1.601, 1.619, 1.631, - 1.597, 1.581, 1.562, 1.539, 1.517, 1.504, 1.483, 1.481, 1.496, 1.511, 1.531, 1.561, 1.585, 1.607, 1.623, 1.632, - 1.601, 1.589, 1.569, 1.554, 1.539, 1.517, 1.504, 1.504, 1.511, 1.531, 1.553, 1.573, 1.596, 1.614, 1.629, 1.636, - 1.609, 1.601, 1.586, 1.569, 1.554, 1.542, 1.535, 1.535, 1.541, 1.553, 1.573, 1.592, 1.608, 1.625, 1.637, 1.645, - 1.617, 1.611, 1.601, 1.586, 1.574, 1.565, 1.564, 1.564, 1.571, 1.579, 1.592, 1.608, 1.622, 1.637, 1.646, 1.654, - 1.619, 1.617, 1.611, 1.601, 1.588, 1.585, 1.585, 1.585, 1.588, 1.592, 1.607, 1.622, 1.637, 1.645, 1.654, 1.655 - ] - }, - { - "ct": 5500, "table": - [ - 2.664, 2.658, 2.645, 2.629, 2.602, 2.602, 2.602, 2.606, 2.617, 2.628, 2.649, 2.677, 2.699, 2.722, 2.736, 2.747, - 2.658, 2.653, 2.629, 2.605, 2.576, 2.575, 2.577, 2.592, 2.606, 2.618, 2.629, 2.651, 2.678, 2.707, 2.727, 2.741, - 2.649, 2.631, 2.605, 2.576, 2.563, 2.552, 2.552, 2.557, 2.577, 2.604, 2.619, 2.641, 2.669, 2.698, 2.721, 2.741, - 2.643, 2.613, 2.583, 2.563, 2.552, 2.531, 2.527, 2.527, 2.551, 2.577, 2.604, 2.638, 2.665, 2.694, 2.721, 2.741, - 2.643, 2.606, 2.575, 2.558, 2.531, 2.516, 2.504, 2.516, 2.527, 2.551, 2.596, 2.635, 2.665, 2.694, 2.721, 2.741, - 2.643, 2.606, 2.575, 2.558, 2.531, 2.503, 2.501, 2.502, 2.522, 2.551, 2.592, 2.635, 2.669, 2.696, 2.727, 2.744, - 2.648, 2.611, 2.579, 2.558, 2.532, 2.511, 2.502, 2.511, 2.522, 2.552, 2.592, 2.642, 2.673, 2.702, 2.731, 2.752, - 2.648, 2.619, 2.589, 2.571, 2.556, 2.532, 2.519, 2.522, 2.552, 2.568, 2.605, 2.648, 2.683, 2.715, 2.743, 2.758, - 2.659, 2.637, 2.613, 2.589, 2.571, 2.556, 2.555, 2.555, 2.568, 2.605, 2.641, 2.671, 2.699, 2.729, 2.758, 2.776, - 2.679, 2.665, 2.637, 2.613, 2.602, 2.599, 2.599, 2.606, 2.619, 2.641, 2.671, 2.698, 2.723, 2.754, 2.776, 2.787, - 2.695, 2.684, 2.671, 2.646, 2.636, 2.636, 2.641, 2.648, 2.661, 2.681, 2.698, 2.723, 2.751, 2.776, 2.788, 2.803, - 2.702, 2.699, 2.684, 2.671, 2.664, 2.664, 2.664, 2.668, 2.681, 2.698, 2.723, 2.751, 2.773, 2.788, 2.803, 2.805 - ] - } - ], - "calibrations_Cb": - [ - { - "ct": 2800, "table": - [ - 2.876, 2.868, 2.863, 2.851, 2.846, 2.846, 2.847, 2.851, 2.851, 2.857, 2.867, 2.875, 2.889, 2.899, 2.913, 2.926, - 2.863, 2.861, 2.856, 2.846, 2.846, 2.847, 2.848, 2.851, 2.857, 2.859, 2.875, 2.882, 2.886, 2.896, 2.909, 2.917, - 2.861, 2.856, 2.846, 2.841, 2.841, 2.855, 2.867, 2.875, 2.888, 2.888, 2.885, 2.883, 2.886, 2.889, 2.901, 2.913, - 2.858, 2.851, 2.846, 2.846, 2.855, 2.867, 2.884, 2.895, 2.902, 2.902, 2.901, 2.891, 2.891, 2.894, 2.901, 2.909, - 2.858, 2.851, 2.846, 2.846, 2.867, 2.884, 2.895, 2.902, 2.909, 2.915, 2.911, 2.901, 2.895, 2.898, 2.904, 2.909, - 2.858, 2.851, 2.849, 2.853, 2.874, 2.888, 2.901, 2.909, 2.917, 2.922, 2.917, 2.911, 2.901, 2.899, 2.905, 2.908, - 2.861, 2.855, 2.853, 2.855, 2.874, 2.888, 2.901, 2.913, 2.918, 2.922, 2.921, 2.911, 2.901, 2.901, 2.907, 2.908, - 2.862, 2.859, 2.855, 2.856, 2.872, 2.885, 2.899, 2.906, 2.915, 2.917, 2.911, 2.907, 2.907, 2.907, 2.908, 2.909, - 2.863, 2.863, 2.859, 2.864, 2.871, 2.881, 2.885, 2.899, 2.905, 2.905, 2.904, 2.904, 2.907, 2.909, 2.913, 2.913, - 2.866, 2.865, 2.865, 2.867, 2.868, 2.872, 2.881, 2.885, 2.889, 2.894, 2.895, 2.902, 2.906, 2.913, 2.914, 2.917, - 2.875, 2.875, 2.871, 2.871, 2.871, 2.871, 2.869, 2.869, 2.878, 2.889, 2.894, 2.895, 2.906, 2.914, 2.917, 2.921, - 2.882, 2.879, 2.876, 2.874, 2.871, 2.871, 2.869, 2.869, 2.869, 2.878, 2.891, 2.894, 2.905, 2.914, 2.919, 2.921 - ] - }, - { - "ct": 5500, "table": - [ - 1.488, 1.488, 1.488, 1.488, 1.491, 1.492, 1.492, 1.491, 1.491, 1.491, 1.492, 1.495, 1.497, 1.499, 1.499, 1.503, - 1.482, 1.485, 1.485, 1.487, 1.489, 1.492, 1.492, 1.492, 1.492, 1.492, 1.494, 1.494, 1.492, 1.491, 1.493, 1.494, - 1.482, 1.482, 1.484, 1.485, 1.487, 1.492, 1.496, 1.498, 1.499, 1.498, 1.494, 1.492, 1.491, 1.491, 1.491, 1.491, - 1.481, 1.481, 1.482, 1.485, 1.491, 1.496, 1.498, 1.499, 1.501, 1.499, 1.498, 1.493, 1.491, 1.488, 1.488, 1.488, - 1.481, 1.481, 1.481, 1.483, 1.491, 1.497, 1.498, 1.499, 1.501, 1.499, 1.498, 1.492, 1.488, 1.485, 1.483, 1.483, - 1.479, 1.479, 1.481, 1.482, 1.489, 1.495, 1.497, 1.498, 1.499, 1.499, 1.495, 1.492, 1.485, 1.482, 1.482, 1.481, - 1.479, 1.479, 1.479, 1.481, 1.489, 1.494, 1.496, 1.497, 1.497, 1.496, 1.495, 1.489, 1.482, 1.481, 1.479, 1.477, - 1.478, 1.478, 1.479, 1.481, 1.487, 1.491, 1.494, 1.496, 1.496, 1.495, 1.492, 1.487, 1.482, 1.479, 1.478, 1.476, - 1.478, 1.478, 1.479, 1.482, 1.486, 1.488, 1.491, 1.493, 1.493, 1.492, 1.487, 1.484, 1.481, 1.479, 1.476, 1.476, - 1.477, 1.479, 1.481, 1.483, 1.485, 1.486, 1.488, 1.488, 1.487, 1.487, 1.484, 1.483, 1.481, 1.479, 1.476, 1.476, - 1.477, 1.479, 1.482, 1.483, 1.484, 1.485, 1.484, 1.482, 1.482, 1.484, 1.483, 1.482, 1.481, 1.479, 1.477, 1.476, - 1.477, 1.479, 1.482, 1.483, 1.484, 1.484, 1.482, 1.482, 1.482, 1.482, 1.482, 1.481, 1.479, 1.479, 1.479, 1.479 - ] - } - ], - "luminance_lut": - [ - 2.764, 2.654, 2.321, 2.043, 1.768, 1.594, 1.558, 1.558, 1.558, 1.568, 1.661, 1.904, 2.193, 2.497, 2.888, 3.043, - 2.654, 2.373, 2.049, 1.819, 1.569, 1.446, 1.381, 1.356, 1.356, 1.403, 1.501, 1.679, 1.939, 2.218, 2.586, 2.888, - 2.376, 2.154, 1.819, 1.569, 1.438, 1.301, 1.246, 1.224, 1.224, 1.263, 1.349, 1.501, 1.679, 1.985, 2.359, 2.609, - 2.267, 1.987, 1.662, 1.438, 1.301, 1.235, 1.132, 1.105, 1.105, 1.164, 1.263, 1.349, 1.528, 1.808, 2.184, 2.491, - 2.218, 1.876, 1.568, 1.367, 1.235, 1.132, 1.087, 1.022, 1.023, 1.104, 1.164, 1.278, 1.439, 1.695, 2.066, 2.429, - 2.218, 1.832, 1.533, 1.341, 1.206, 1.089, 1.013, 1.002, 1.013, 1.026, 1.122, 1.246, 1.399, 1.642, 2.004, 2.426, - 2.218, 1.832, 1.533, 1.341, 1.206, 1.089, 1.011, 1.001, 1.009, 1.026, 1.122, 1.246, 1.399, 1.642, 2.004, 2.426, - 2.224, 1.896, 1.584, 1.382, 1.248, 1.147, 1.088, 1.016, 1.026, 1.118, 1.168, 1.283, 1.444, 1.697, 2.066, 2.428, - 2.292, 2.019, 1.689, 1.462, 1.322, 1.247, 1.147, 1.118, 1.118, 1.168, 1.275, 1.358, 1.532, 1.809, 2.189, 2.491, - 2.444, 2.204, 1.856, 1.606, 1.462, 1.322, 1.257, 1.234, 1.234, 1.275, 1.358, 1.516, 1.686, 1.993, 2.371, 2.622, - 2.748, 2.444, 2.108, 1.856, 1.606, 1.476, 1.399, 1.376, 1.376, 1.422, 1.516, 1.686, 1.968, 2.238, 2.611, 2.935, - 2.862, 2.748, 2.395, 2.099, 1.811, 1.621, 1.582, 1.582, 1.582, 1.592, 1.677, 1.919, 2.223, 2.534, 2.935, 3.078 - ], - "sigma": 0.00428, - "sigma_Cb": 0.00363 - }, - "rpi.contrast": - { - "ce_enable": 1, - "gamma_curve": - [ - 0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120, 18051, 6144, 20790, 7168, 23193, - 8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168, - 16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753, 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796, - 32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954, 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476, - 65535, 65535 - ] - }, - "rpi.ccm": - { - "ccms": - [ - { - "ct": 2850, "ccm": - [ - 1.42601, -0.20537, -0.22063, -0.47682, 1.81987, -0.34305, 0.01854, -0.86036, 1.84181 - ] - }, - { - "ct": 2900, "ccm": - [ - 1.29755, 0.04602, -0.34356, -0.41491, 1.73477, -0.31987, -0.01345, -0.97115, 1.98459 - ] - }, - { - "ct": 3550, "ccm": - [ - 1.49811, -0.33412, -0.16398, -0.40869, 1.72995, -0.32127, -0.01924, -0.62181, 1.64105 - ] - }, - { - "ct": 4500, "ccm": - [ - 1.47015, -0.29229, -0.17786, -0.36561, 1.88919, -0.52358, -0.03552, -0.56717, 1.60269 - ] - }, - { - "ct": 5600, "ccm": - [ - 1.60962, -0.47434, -0.13528, -0.32701, 1.73797, -0.41096, -0.07626, -0.40171, 1.47796 - ] - }, - { - "ct": 8000, "ccm": - [ - 1.54642, -0.20396, -0.34246, -0.31748, 2.22559, -0.90811, -0.10035, -0.65877, 1.75912 - ] - } - ] - }, - "rpi.sharpen": - { - } -} diff --git a/src/ipa/raspberrypi/data/imx477.json b/src/ipa/raspberrypi/data/imx477.json deleted file mode 100644 index d07febd2..00000000 --- a/src/ipa/raspberrypi/data/imx477.json +++ /dev/null @@ -1,430 +0,0 @@ -{ - "rpi.black_level": - { - "black_level": 4096 - }, - "rpi.dpc": - { - - }, - "rpi.lux": - { - "reference_shutter_speed": 27242, - "reference_gain": 1.0, - "reference_aperture": 1.0, - "reference_lux": 830, - "reference_Y": 17755 - }, - "rpi.noise": - { - "reference_constant": 0, - "reference_slope": 2.767 - }, - "rpi.geq": - { - "offset": 204, - "slope": 0.01078 - }, - "rpi.sdn": - { - - }, - "rpi.awb": - { - "priors": - [ - { - "lux": 0, "prior": - [ - 2000, 1.0, 3000, 0.0, 13000, 0.0 - ] - }, - { - "lux": 800, "prior": - [ - 2000, 0.0, 6000, 2.0, 13000, 2.0 - ] - }, - { - "lux": 1500, "prior": - [ - 2000, 0.0, 4000, 1.0, 6000, 6.0, 6500, 7.0, 7000, 1.0, 13000, 1.0 - ] - } - ], - "modes": - { - "auto": - { - "lo": 2500, - "hi": 8000 - }, - "incandescent": - { - "lo": 2500, - "hi": 3000 - }, - "tungsten": - { - "lo": 3000, - "hi": 3500 - }, - "fluorescent": - { - "lo": 4000, - "hi": 4700 - }, - "indoor": - { - "lo": 3000, - "hi": 5000 - }, - "daylight": - { - "lo": 5500, - "hi": 6500 - }, - "cloudy": - { - "lo": 7000, - "hi": 8600 - } - }, - "bayes": 1, - "ct_curve": - [ - 2360.0, 0.6009, 0.3093, 2870.0, 0.5047, 0.3936, 2970.0, 0.4782, 0.4221, 3700.0, 0.4212, 0.4923, 3870.0, 0.4037, 0.5166, 4000.0, - 0.3965, 0.5271, 4400.0, 0.3703, 0.5666, 4715.0, 0.3411, 0.6147, 5920.0, 0.3108, 0.6687, 9050.0, 0.2524, 0.7856 - ], - "sensitivity_r": 1.05, - "sensitivity_b": 1.05, - "transverse_pos": 0.0238, - "transverse_neg": 0.04429 - }, - "rpi.agc": - { - "metering_modes": - { - "centre-weighted": - { - "weights": - [ - 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 - ] - }, - "spot": - { - "weights": - [ - 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - }, - "matrix": - { - "weights": - [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - ] - } - }, - "exposure_modes": - { - "normal": - { - "shutter": - [ - 100, 10000, 30000, 60000, 66666 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "short": - { - "shutter": - [ - 100, 5000, 10000, 20000, 33333 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "long": - { - "shutter": - [ - 100, 10000, 30000, 60000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 12.0 - ] - } - }, - "constraint_modes": - { - "normal": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.3, 1000, 0.3 - ] - } - ], - "highlight": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.3, 1000, 0.3 - ] - }, - { - "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.8, 1000, 0.8 - ] - } - ], - "shadows": - [ - { - "bound": "LOWER", "q_lo": 0.0, "q_hi": 0.5, "y_target": - [ - 0, 0.17, 1000, 0.17 - ] - } - ] - }, - "y_target": - [ - 0, 0.16, 1000, 0.165, 10000, 0.17 - ] - }, - "rpi.alsc": - { - "omega": 1.3, - "n_iter": 100, - "luminance_strength": 0.5, - "calibrations_Cr": - [ - { - "ct": 2960, "table": - [ - 2.088, 2.086, 2.082, 2.081, 2.077, 2.071, 2.068, 2.068, 2.072, 2.073, 2.075, 2.078, 2.084, 2.092, 2.095, 2.098, - 2.086, 2.084, 2.079, 2.078, 2.075, 2.068, 2.064, 2.063, 2.068, 2.071, 2.072, 2.075, 2.081, 2.089, 2.092, 2.094, - 2.083, 2.081, 2.077, 2.072, 2.069, 2.062, 2.059, 2.059, 2.063, 2.067, 2.069, 2.072, 2.079, 2.088, 2.089, 2.089, - 2.081, 2.077, 2.072, 2.068, 2.065, 2.058, 2.055, 2.054, 2.057, 2.062, 2.066, 2.069, 2.077, 2.084, 2.086, 2.086, - 2.078, 2.075, 2.069, 2.065, 2.061, 2.055, 2.052, 2.049, 2.051, 2.056, 2.062, 2.065, 2.072, 2.079, 2.081, 2.079, - 2.079, 2.075, 2.069, 2.064, 2.061, 2.053, 2.049, 2.046, 2.049, 2.051, 2.057, 2.062, 2.069, 2.075, 2.077, 2.075, - 2.082, 2.079, 2.072, 2.065, 2.061, 2.054, 2.049, 2.047, 2.049, 2.051, 2.056, 2.061, 2.066, 2.073, 2.073, 2.069, - 2.086, 2.082, 2.075, 2.068, 2.062, 2.054, 2.051, 2.049, 2.051, 2.052, 2.056, 2.061, 2.066, 2.073, 2.073, 2.072, - 2.088, 2.086, 2.079, 2.074, 2.066, 2.057, 2.051, 2.051, 2.054, 2.055, 2.056, 2.061, 2.067, 2.072, 2.073, 2.072, - 2.091, 2.087, 2.079, 2.075, 2.068, 2.057, 2.052, 2.052, 2.056, 2.055, 2.055, 2.059, 2.066, 2.072, 2.072, 2.072, - 2.093, 2.088, 2.081, 2.077, 2.069, 2.059, 2.054, 2.054, 2.057, 2.056, 2.056, 2.058, 2.066, 2.072, 2.073, 2.073, - 2.095, 2.091, 2.084, 2.078, 2.075, 2.067, 2.057, 2.057, 2.059, 2.059, 2.058, 2.059, 2.068, 2.073, 2.075, 2.078 - ] - }, - { - "ct": 4850, "table": - [ - 2.973, 2.968, 2.956, 2.943, 2.941, 2.932, 2.923, 2.921, 2.924, 2.929, 2.931, 2.939, 2.953, 2.965, 2.966, 2.976, - 2.969, 2.962, 2.951, 2.941, 2.934, 2.928, 2.919, 2.918, 2.919, 2.923, 2.927, 2.933, 2.945, 2.957, 2.962, 2.962, - 2.964, 2.956, 2.944, 2.932, 2.929, 2.924, 2.915, 2.914, 2.915, 2.919, 2.924, 2.928, 2.941, 2.952, 2.958, 2.959, - 2.957, 2.951, 2.939, 2.928, 2.924, 2.919, 2.913, 2.911, 2.911, 2.915, 2.919, 2.925, 2.936, 2.947, 2.952, 2.953, - 2.954, 2.947, 2.935, 2.924, 2.919, 2.915, 2.908, 2.906, 2.906, 2.907, 2.914, 2.921, 2.932, 2.941, 2.943, 2.942, - 2.953, 2.946, 2.932, 2.921, 2.916, 2.911, 2.904, 2.902, 2.901, 2.904, 2.909, 2.919, 2.926, 2.937, 2.939, 2.939, - 2.953, 2.947, 2.932, 2.918, 2.915, 2.909, 2.903, 2.901, 2.901, 2.906, 2.911, 2.918, 2.924, 2.936, 2.936, 2.932, - 2.956, 2.948, 2.934, 2.919, 2.916, 2.908, 2.903, 2.901, 2.902, 2.907, 2.909, 2.917, 2.926, 2.936, 2.939, 2.939, - 2.957, 2.951, 2.936, 2.923, 2.917, 2.907, 2.904, 2.901, 2.902, 2.908, 2.911, 2.919, 2.929, 2.939, 2.942, 2.942, - 2.961, 2.951, 2.936, 2.922, 2.918, 2.906, 2.904, 2.901, 2.901, 2.907, 2.911, 2.921, 2.931, 2.941, 2.942, 2.944, - 2.964, 2.954, 2.936, 2.924, 2.918, 2.909, 2.905, 2.905, 2.905, 2.907, 2.912, 2.923, 2.933, 2.942, 2.944, 2.944, - 2.964, 2.958, 2.943, 2.927, 2.921, 2.914, 2.909, 2.907, 2.907, 2.912, 2.916, 2.928, 2.936, 2.944, 2.947, 2.952 - ] - }, - { - "ct": 5930, "table": - [ - 3.312, 3.308, 3.301, 3.294, 3.288, 3.277, 3.268, 3.261, 3.259, 3.261, 3.267, 3.273, 3.285, 3.301, 3.303, 3.312, - 3.308, 3.304, 3.294, 3.291, 3.283, 3.271, 3.263, 3.259, 3.257, 3.258, 3.261, 3.268, 3.278, 3.293, 3.299, 3.299, - 3.302, 3.296, 3.288, 3.282, 3.276, 3.267, 3.259, 3.254, 3.252, 3.253, 3.256, 3.261, 3.273, 3.289, 3.292, 3.292, - 3.296, 3.289, 3.282, 3.276, 3.269, 3.263, 3.256, 3.251, 3.248, 3.249, 3.251, 3.257, 3.268, 3.279, 3.284, 3.284, - 3.292, 3.285, 3.279, 3.271, 3.264, 3.257, 3.249, 3.243, 3.241, 3.241, 3.246, 3.252, 3.261, 3.274, 3.275, 3.273, - 3.291, 3.285, 3.276, 3.268, 3.259, 3.251, 3.242, 3.239, 3.236, 3.238, 3.244, 3.248, 3.258, 3.268, 3.269, 3.265, - 3.294, 3.288, 3.275, 3.266, 3.257, 3.248, 3.239, 3.238, 3.237, 3.238, 3.243, 3.246, 3.255, 3.264, 3.264, 3.257, - 3.297, 3.293, 3.279, 3.268, 3.258, 3.249, 3.238, 3.237, 3.239, 3.239, 3.243, 3.245, 3.255, 3.264, 3.264, 3.263, - 3.301, 3.295, 3.281, 3.271, 3.259, 3.248, 3.237, 3.237, 3.239, 3.241, 3.243, 3.246, 3.257, 3.265, 3.266, 3.264, - 3.306, 3.295, 3.279, 3.271, 3.261, 3.247, 3.235, 3.234, 3.239, 3.239, 3.243, 3.247, 3.258, 3.265, 3.265, 3.264, - 3.308, 3.297, 3.279, 3.272, 3.261, 3.249, 3.239, 3.239, 3.241, 3.243, 3.245, 3.248, 3.261, 3.265, 3.266, 3.265, - 3.309, 3.301, 3.286, 3.276, 3.267, 3.256, 3.246, 3.242, 3.244, 3.244, 3.249, 3.253, 3.263, 3.267, 3.271, 3.274 - ] - } - ], - "calibrations_Cb": - [ - { - "ct": 2960, "table": - [ - 2.133, 2.134, 2.139, 2.143, 2.148, 2.155, 2.158, 2.158, 2.158, 2.161, 2.161, 2.162, 2.159, 2.156, 2.152, 2.151, - 2.132, 2.133, 2.135, 2.142, 2.147, 2.153, 2.158, 2.158, 2.158, 2.158, 2.159, 2.159, 2.157, 2.154, 2.151, 2.148, - 2.133, 2.133, 2.135, 2.142, 2.149, 2.154, 2.158, 2.158, 2.157, 2.156, 2.158, 2.157, 2.155, 2.153, 2.148, 2.146, - 2.133, 2.133, 2.138, 2.145, 2.149, 2.154, 2.158, 2.159, 2.158, 2.155, 2.157, 2.156, 2.153, 2.149, 2.146, 2.144, - 2.133, 2.134, 2.139, 2.146, 2.149, 2.154, 2.158, 2.159, 2.159, 2.156, 2.154, 2.154, 2.149, 2.145, 2.143, 2.139, - 2.135, 2.135, 2.139, 2.146, 2.151, 2.155, 2.158, 2.159, 2.158, 2.156, 2.153, 2.151, 2.146, 2.143, 2.139, 2.136, - 2.135, 2.135, 2.138, 2.145, 2.151, 2.154, 2.157, 2.158, 2.157, 2.156, 2.153, 2.151, 2.147, 2.143, 2.141, 2.137, - 2.135, 2.134, 2.135, 2.141, 2.149, 2.154, 2.157, 2.157, 2.157, 2.157, 2.157, 2.153, 2.149, 2.146, 2.142, 2.139, - 2.132, 2.133, 2.135, 2.139, 2.148, 2.153, 2.158, 2.159, 2.159, 2.161, 2.161, 2.157, 2.154, 2.149, 2.144, 2.141, - 2.132, 2.133, 2.135, 2.141, 2.149, 2.155, 2.161, 2.161, 2.162, 2.162, 2.163, 2.159, 2.154, 2.149, 2.144, 2.138, - 2.136, 2.136, 2.137, 2.143, 2.149, 2.156, 2.162, 2.163, 2.162, 2.163, 2.164, 2.161, 2.157, 2.152, 2.146, 2.138, - 2.137, 2.137, 2.141, 2.147, 2.152, 2.157, 2.162, 2.162, 2.159, 2.161, 2.162, 2.162, 2.157, 2.152, 2.148, 2.148 - ] - }, - { - "ct": 4850, "table": - [ - 1.463, 1.464, 1.471, 1.478, 1.479, 1.483, 1.484, 1.486, 1.486, 1.484, 1.483, 1.481, 1.478, 1.475, 1.471, 1.468, - 1.463, 1.463, 1.468, 1.476, 1.479, 1.482, 1.484, 1.487, 1.486, 1.484, 1.483, 1.482, 1.478, 1.473, 1.469, 1.468, - 1.463, 1.464, 1.468, 1.476, 1.479, 1.483, 1.484, 1.486, 1.486, 1.485, 1.484, 1.482, 1.477, 1.473, 1.469, 1.468, - 1.463, 1.464, 1.469, 1.477, 1.481, 1.483, 1.485, 1.487, 1.487, 1.485, 1.485, 1.482, 1.478, 1.474, 1.469, 1.468, - 1.465, 1.465, 1.471, 1.478, 1.481, 1.484, 1.486, 1.488, 1.488, 1.487, 1.485, 1.482, 1.477, 1.472, 1.468, 1.467, - 1.465, 1.466, 1.472, 1.479, 1.482, 1.485, 1.486, 1.488, 1.488, 1.486, 1.484, 1.479, 1.475, 1.472, 1.468, 1.466, - 1.466, 1.466, 1.472, 1.478, 1.482, 1.484, 1.485, 1.488, 1.487, 1.485, 1.483, 1.479, 1.475, 1.472, 1.469, 1.468, - 1.465, 1.466, 1.469, 1.476, 1.481, 1.485, 1.485, 1.486, 1.486, 1.485, 1.483, 1.479, 1.477, 1.474, 1.471, 1.469, - 1.464, 1.465, 1.469, 1.476, 1.481, 1.484, 1.485, 1.487, 1.487, 1.486, 1.485, 1.481, 1.478, 1.475, 1.471, 1.469, - 1.463, 1.464, 1.469, 1.477, 1.481, 1.485, 1.485, 1.488, 1.488, 1.487, 1.486, 1.481, 1.478, 1.475, 1.471, 1.468, - 1.464, 1.465, 1.471, 1.478, 1.482, 1.486, 1.486, 1.488, 1.488, 1.487, 1.486, 1.481, 1.478, 1.475, 1.472, 1.468, - 1.465, 1.466, 1.472, 1.481, 1.483, 1.487, 1.487, 1.488, 1.488, 1.486, 1.485, 1.481, 1.479, 1.476, 1.473, 1.472 - ] - }, - { - "ct": 5930, "table": - [ - 1.443, 1.444, 1.448, 1.453, 1.459, 1.463, 1.465, 1.467, 1.469, 1.469, 1.467, 1.466, 1.462, 1.457, 1.454, 1.451, - 1.443, 1.444, 1.445, 1.451, 1.459, 1.463, 1.465, 1.467, 1.469, 1.469, 1.467, 1.465, 1.461, 1.456, 1.452, 1.451, - 1.444, 1.444, 1.445, 1.451, 1.459, 1.463, 1.466, 1.468, 1.469, 1.469, 1.467, 1.465, 1.461, 1.456, 1.452, 1.449, - 1.444, 1.444, 1.447, 1.452, 1.459, 1.464, 1.467, 1.469, 1.471, 1.469, 1.467, 1.466, 1.461, 1.456, 1.452, 1.449, - 1.444, 1.445, 1.448, 1.452, 1.459, 1.465, 1.469, 1.471, 1.471, 1.471, 1.468, 1.465, 1.461, 1.455, 1.451, 1.449, - 1.445, 1.446, 1.449, 1.453, 1.461, 1.466, 1.469, 1.471, 1.472, 1.469, 1.467, 1.465, 1.459, 1.455, 1.451, 1.447, - 1.446, 1.446, 1.449, 1.453, 1.461, 1.466, 1.469, 1.469, 1.469, 1.469, 1.467, 1.465, 1.459, 1.455, 1.452, 1.449, - 1.446, 1.446, 1.447, 1.451, 1.459, 1.466, 1.469, 1.469, 1.469, 1.469, 1.467, 1.465, 1.461, 1.457, 1.454, 1.451, - 1.444, 1.444, 1.447, 1.451, 1.459, 1.466, 1.469, 1.469, 1.471, 1.471, 1.468, 1.466, 1.462, 1.458, 1.454, 1.452, - 1.444, 1.444, 1.448, 1.453, 1.459, 1.466, 1.469, 1.471, 1.472, 1.472, 1.468, 1.466, 1.462, 1.458, 1.454, 1.449, - 1.446, 1.447, 1.449, 1.454, 1.461, 1.466, 1.471, 1.471, 1.471, 1.471, 1.468, 1.466, 1.462, 1.459, 1.455, 1.449, - 1.447, 1.447, 1.452, 1.457, 1.462, 1.468, 1.472, 1.472, 1.471, 1.471, 1.468, 1.466, 1.462, 1.459, 1.456, 1.455 - ] - } - ], - "luminance_lut": - [ - 1.548, 1.499, 1.387, 1.289, 1.223, 1.183, 1.164, 1.154, 1.153, 1.169, 1.211, 1.265, 1.345, 1.448, 1.581, 1.619, - 1.513, 1.412, 1.307, 1.228, 1.169, 1.129, 1.105, 1.098, 1.103, 1.127, 1.157, 1.209, 1.272, 1.361, 1.481, 1.583, - 1.449, 1.365, 1.257, 1.175, 1.124, 1.085, 1.062, 1.054, 1.059, 1.079, 1.113, 1.151, 1.211, 1.293, 1.407, 1.488, - 1.424, 1.324, 1.222, 1.139, 1.089, 1.056, 1.034, 1.031, 1.034, 1.049, 1.075, 1.115, 1.164, 1.241, 1.351, 1.446, - 1.412, 1.297, 1.203, 1.119, 1.069, 1.039, 1.021, 1.016, 1.022, 1.032, 1.052, 1.086, 1.135, 1.212, 1.321, 1.439, - 1.406, 1.287, 1.195, 1.115, 1.059, 1.028, 1.014, 1.012, 1.015, 1.026, 1.041, 1.074, 1.125, 1.201, 1.302, 1.425, - 1.406, 1.294, 1.205, 1.126, 1.062, 1.031, 1.013, 1.009, 1.011, 1.019, 1.042, 1.079, 1.129, 1.203, 1.302, 1.435, - 1.415, 1.318, 1.229, 1.146, 1.076, 1.039, 1.019, 1.014, 1.017, 1.031, 1.053, 1.093, 1.144, 1.219, 1.314, 1.436, - 1.435, 1.348, 1.246, 1.164, 1.094, 1.059, 1.036, 1.032, 1.037, 1.049, 1.072, 1.114, 1.167, 1.257, 1.343, 1.462, - 1.471, 1.385, 1.278, 1.189, 1.124, 1.084, 1.064, 1.061, 1.069, 1.078, 1.101, 1.146, 1.207, 1.298, 1.415, 1.496, - 1.522, 1.436, 1.323, 1.228, 1.169, 1.118, 1.101, 1.094, 1.099, 1.113, 1.146, 1.194, 1.265, 1.353, 1.474, 1.571, - 1.578, 1.506, 1.378, 1.281, 1.211, 1.156, 1.135, 1.134, 1.139, 1.158, 1.194, 1.251, 1.327, 1.427, 1.559, 1.611 - ], - "sigma": 0.00121, - "sigma_Cb": 0.00115 - }, - "rpi.contrast": - { - "ce_enable": 1, - "gamma_curve": - [ - 0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120, 18051, 6144, 20790, 7168, 23193, - 8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168, - 16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753, 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796, - 32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954, 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476, - 65535, 65535 - ] - }, - "rpi.ccm": - { - "ccms": - [ - { - "ct": 2360, "ccm": - [ - 1.66078, -0.23588, -0.42491, -0.47456, 1.82763, -0.35307, -0.00545, -1.44729, 2.45273 - ] - }, - { - "ct": 2870, "ccm": - [ - 1.78373, -0.55344, -0.23029, -0.39951, 1.69701, -0.29751, 0.01986, -1.06525, 2.04539 - ] - }, - { - "ct": 2970, "ccm": - [ - 1.73511, -0.56973, -0.16537, -0.36338, 1.69878, -0.33539, -0.02354, -0.76813, 1.79168 - ] - }, - { - "ct": 3000, "ccm": - [ - 2.06374, -0.92218, -0.14156, -0.41721, 1.69289, -0.27568, -0.00554, -0.92741, 1.93295 - ] - }, - { - "ct": 3700, "ccm": - [ - 2.13792, -1.08136, -0.05655, -0.34739, 1.58989, -0.24249, -0.00349, -0.76789, 1.77138 - ] - }, - { - "ct": 3870, "ccm": - [ - 1.83834, -0.70528, -0.13307, -0.30499, 1.60523, -0.30024, -0.05701, -0.58313, 1.64014 - ] - }, - { - "ct": 4000, "ccm": - [ - 2.15741, -1.10295, -0.05447, -0.34631, 1.61158, -0.26528, -0.02723, -0.70288, 1.73011 - ] - }, - { - "ct": 4400, "ccm": - [ - 2.05729, -0.95007, -0.10723, -0.41712, 1.78606, -0.36894, -0.11899, -0.55727, 1.67626 - ] - }, - - { - "ct": 4715, "ccm": - [ - 1.90255, -0.77478, -0.12777, -0.31338, 1.88197, -0.56858, -0.06001, -0.61785, 1.67786 - ] - }, - { - "ct": 5920, "ccm": - [ - 1.98691, -0.84671, -0.14019, -0.26581, 1.70615, -0.44035, -0.09532, -0.47332, 1.56864 - ] - }, - { - "ct": 9050, "ccm": - [ - 2.09255, -0.76541, -0.32714, -0.28973, 2.27462, -0.98489, -0.17299, -0.61275, 1.78574 - ] - } - ] - }, - "rpi.sharpen": - { - - }, - "rpi.focus": - { - } -} diff --git a/src/ipa/raspberrypi/data/imx477_noir.json b/src/ipa/raspberrypi/data/imx477_noir.json deleted file mode 100644 index 7d4fc7da..00000000 --- a/src/ipa/raspberrypi/data/imx477_noir.json +++ /dev/null @@ -1,362 +0,0 @@ -{ - "rpi.black_level": - { - "black_level": 4096 - }, - "rpi.dpc": - { - - }, - "rpi.lux": - { - "reference_shutter_speed": 27242, - "reference_gain": 1.0, - "reference_aperture": 1.0, - "reference_lux": 830, - "reference_Y": 17755 - }, - "rpi.noise": - { - "reference_constant": 0, - "reference_slope": 2.767 - }, - "rpi.geq": - { - "offset": 204, - "slope": 0.01078 - }, - "rpi.sdn": - { - - }, - "rpi.awb": - { - "bayes": 0 - }, - "rpi.agc": - { - "metering_modes": - { - "centre-weighted": - { - "weights": - [ - 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 - ] - }, - "spot": - { - "weights": - [ - 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - }, - "matrix": - { - "weights": - [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - ] - } - }, - "exposure_modes": - { - "normal": - { - "shutter": - [ - 100, 10000, 30000, 60000, 66666 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "short": - { - "shutter": - [ - 100, 5000, 10000, 20000, 33333 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "long": - { - "shutter": - [ - 100, 10000, 30000, 60000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 12.0 - ] - } - }, - "constraint_modes": - { - "normal": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.3, 1000, 0.3 - ] - } - ], - "highlight": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.3, 1000, 0.3 - ] - }, - { - "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.8, 1000, 0.8 - ] - } - ], - "shadows": - [ - { - "bound": "LOWER", "q_lo": 0.0, "q_hi": 0.5, "y_target": - [ - 0, 0.17, 1000, 0.17 - ] - } - ] - }, - "y_target": - [ - 0, 0.16, 1000, 0.165, 10000, 0.17 - ] - }, - "rpi.alsc": - { - "omega": 1.3, - "n_iter": 100, - "luminance_strength": 0.5, - "calibrations_Cr": - [ - { - "ct": 2960, "table": - [ - 2.088, 2.086, 2.082, 2.081, 2.077, 2.071, 2.068, 2.068, 2.072, 2.073, 2.075, 2.078, 2.084, 2.092, 2.095, 2.098, - 2.086, 2.084, 2.079, 2.078, 2.075, 2.068, 2.064, 2.063, 2.068, 2.071, 2.072, 2.075, 2.081, 2.089, 2.092, 2.094, - 2.083, 2.081, 2.077, 2.072, 2.069, 2.062, 2.059, 2.059, 2.063, 2.067, 2.069, 2.072, 2.079, 2.088, 2.089, 2.089, - 2.081, 2.077, 2.072, 2.068, 2.065, 2.058, 2.055, 2.054, 2.057, 2.062, 2.066, 2.069, 2.077, 2.084, 2.086, 2.086, - 2.078, 2.075, 2.069, 2.065, 2.061, 2.055, 2.052, 2.049, 2.051, 2.056, 2.062, 2.065, 2.072, 2.079, 2.081, 2.079, - 2.079, 2.075, 2.069, 2.064, 2.061, 2.053, 2.049, 2.046, 2.049, 2.051, 2.057, 2.062, 2.069, 2.075, 2.077, 2.075, - 2.082, 2.079, 2.072, 2.065, 2.061, 2.054, 2.049, 2.047, 2.049, 2.051, 2.056, 2.061, 2.066, 2.073, 2.073, 2.069, - 2.086, 2.082, 2.075, 2.068, 2.062, 2.054, 2.051, 2.049, 2.051, 2.052, 2.056, 2.061, 2.066, 2.073, 2.073, 2.072, - 2.088, 2.086, 2.079, 2.074, 2.066, 2.057, 2.051, 2.051, 2.054, 2.055, 2.056, 2.061, 2.067, 2.072, 2.073, 2.072, - 2.091, 2.087, 2.079, 2.075, 2.068, 2.057, 2.052, 2.052, 2.056, 2.055, 2.055, 2.059, 2.066, 2.072, 2.072, 2.072, - 2.093, 2.088, 2.081, 2.077, 2.069, 2.059, 2.054, 2.054, 2.057, 2.056, 2.056, 2.058, 2.066, 2.072, 2.073, 2.073, - 2.095, 2.091, 2.084, 2.078, 2.075, 2.067, 2.057, 2.057, 2.059, 2.059, 2.058, 2.059, 2.068, 2.073, 2.075, 2.078 - ] - }, - { - "ct": 4850, "table": - [ - 2.973, 2.968, 2.956, 2.943, 2.941, 2.932, 2.923, 2.921, 2.924, 2.929, 2.931, 2.939, 2.953, 2.965, 2.966, 2.976, - 2.969, 2.962, 2.951, 2.941, 2.934, 2.928, 2.919, 2.918, 2.919, 2.923, 2.927, 2.933, 2.945, 2.957, 2.962, 2.962, - 2.964, 2.956, 2.944, 2.932, 2.929, 2.924, 2.915, 2.914, 2.915, 2.919, 2.924, 2.928, 2.941, 2.952, 2.958, 2.959, - 2.957, 2.951, 2.939, 2.928, 2.924, 2.919, 2.913, 2.911, 2.911, 2.915, 2.919, 2.925, 2.936, 2.947, 2.952, 2.953, - 2.954, 2.947, 2.935, 2.924, 2.919, 2.915, 2.908, 2.906, 2.906, 2.907, 2.914, 2.921, 2.932, 2.941, 2.943, 2.942, - 2.953, 2.946, 2.932, 2.921, 2.916, 2.911, 2.904, 2.902, 2.901, 2.904, 2.909, 2.919, 2.926, 2.937, 2.939, 2.939, - 2.953, 2.947, 2.932, 2.918, 2.915, 2.909, 2.903, 2.901, 2.901, 2.906, 2.911, 2.918, 2.924, 2.936, 2.936, 2.932, - 2.956, 2.948, 2.934, 2.919, 2.916, 2.908, 2.903, 2.901, 2.902, 2.907, 2.909, 2.917, 2.926, 2.936, 2.939, 2.939, - 2.957, 2.951, 2.936, 2.923, 2.917, 2.907, 2.904, 2.901, 2.902, 2.908, 2.911, 2.919, 2.929, 2.939, 2.942, 2.942, - 2.961, 2.951, 2.936, 2.922, 2.918, 2.906, 2.904, 2.901, 2.901, 2.907, 2.911, 2.921, 2.931, 2.941, 2.942, 2.944, - 2.964, 2.954, 2.936, 2.924, 2.918, 2.909, 2.905, 2.905, 2.905, 2.907, 2.912, 2.923, 2.933, 2.942, 2.944, 2.944, - 2.964, 2.958, 2.943, 2.927, 2.921, 2.914, 2.909, 2.907, 2.907, 2.912, 2.916, 2.928, 2.936, 2.944, 2.947, 2.952 - ] - }, - { - "ct": 5930, "table": - [ - 3.312, 3.308, 3.301, 3.294, 3.288, 3.277, 3.268, 3.261, 3.259, 3.261, 3.267, 3.273, 3.285, 3.301, 3.303, 3.312, - 3.308, 3.304, 3.294, 3.291, 3.283, 3.271, 3.263, 3.259, 3.257, 3.258, 3.261, 3.268, 3.278, 3.293, 3.299, 3.299, - 3.302, 3.296, 3.288, 3.282, 3.276, 3.267, 3.259, 3.254, 3.252, 3.253, 3.256, 3.261, 3.273, 3.289, 3.292, 3.292, - 3.296, 3.289, 3.282, 3.276, 3.269, 3.263, 3.256, 3.251, 3.248, 3.249, 3.251, 3.257, 3.268, 3.279, 3.284, 3.284, - 3.292, 3.285, 3.279, 3.271, 3.264, 3.257, 3.249, 3.243, 3.241, 3.241, 3.246, 3.252, 3.261, 3.274, 3.275, 3.273, - 3.291, 3.285, 3.276, 3.268, 3.259, 3.251, 3.242, 3.239, 3.236, 3.238, 3.244, 3.248, 3.258, 3.268, 3.269, 3.265, - 3.294, 3.288, 3.275, 3.266, 3.257, 3.248, 3.239, 3.238, 3.237, 3.238, 3.243, 3.246, 3.255, 3.264, 3.264, 3.257, - 3.297, 3.293, 3.279, 3.268, 3.258, 3.249, 3.238, 3.237, 3.239, 3.239, 3.243, 3.245, 3.255, 3.264, 3.264, 3.263, - 3.301, 3.295, 3.281, 3.271, 3.259, 3.248, 3.237, 3.237, 3.239, 3.241, 3.243, 3.246, 3.257, 3.265, 3.266, 3.264, - 3.306, 3.295, 3.279, 3.271, 3.261, 3.247, 3.235, 3.234, 3.239, 3.239, 3.243, 3.247, 3.258, 3.265, 3.265, 3.264, - 3.308, 3.297, 3.279, 3.272, 3.261, 3.249, 3.239, 3.239, 3.241, 3.243, 3.245, 3.248, 3.261, 3.265, 3.266, 3.265, - 3.309, 3.301, 3.286, 3.276, 3.267, 3.256, 3.246, 3.242, 3.244, 3.244, 3.249, 3.253, 3.263, 3.267, 3.271, 3.274 - ] - } - ], - "calibrations_Cb": - [ - { - "ct": 2960, "table": - [ - 2.133, 2.134, 2.139, 2.143, 2.148, 2.155, 2.158, 2.158, 2.158, 2.161, 2.161, 2.162, 2.159, 2.156, 2.152, 2.151, - 2.132, 2.133, 2.135, 2.142, 2.147, 2.153, 2.158, 2.158, 2.158, 2.158, 2.159, 2.159, 2.157, 2.154, 2.151, 2.148, - 2.133, 2.133, 2.135, 2.142, 2.149, 2.154, 2.158, 2.158, 2.157, 2.156, 2.158, 2.157, 2.155, 2.153, 2.148, 2.146, - 2.133, 2.133, 2.138, 2.145, 2.149, 2.154, 2.158, 2.159, 2.158, 2.155, 2.157, 2.156, 2.153, 2.149, 2.146, 2.144, - 2.133, 2.134, 2.139, 2.146, 2.149, 2.154, 2.158, 2.159, 2.159, 2.156, 2.154, 2.154, 2.149, 2.145, 2.143, 2.139, - 2.135, 2.135, 2.139, 2.146, 2.151, 2.155, 2.158, 2.159, 2.158, 2.156, 2.153, 2.151, 2.146, 2.143, 2.139, 2.136, - 2.135, 2.135, 2.138, 2.145, 2.151, 2.154, 2.157, 2.158, 2.157, 2.156, 2.153, 2.151, 2.147, 2.143, 2.141, 2.137, - 2.135, 2.134, 2.135, 2.141, 2.149, 2.154, 2.157, 2.157, 2.157, 2.157, 2.157, 2.153, 2.149, 2.146, 2.142, 2.139, - 2.132, 2.133, 2.135, 2.139, 2.148, 2.153, 2.158, 2.159, 2.159, 2.161, 2.161, 2.157, 2.154, 2.149, 2.144, 2.141, - 2.132, 2.133, 2.135, 2.141, 2.149, 2.155, 2.161, 2.161, 2.162, 2.162, 2.163, 2.159, 2.154, 2.149, 2.144, 2.138, - 2.136, 2.136, 2.137, 2.143, 2.149, 2.156, 2.162, 2.163, 2.162, 2.163, 2.164, 2.161, 2.157, 2.152, 2.146, 2.138, - 2.137, 2.137, 2.141, 2.147, 2.152, 2.157, 2.162, 2.162, 2.159, 2.161, 2.162, 2.162, 2.157, 2.152, 2.148, 2.148 - ] - }, - { - "ct": 4850, "table": - [ - 1.463, 1.464, 1.471, 1.478, 1.479, 1.483, 1.484, 1.486, 1.486, 1.484, 1.483, 1.481, 1.478, 1.475, 1.471, 1.468, - 1.463, 1.463, 1.468, 1.476, 1.479, 1.482, 1.484, 1.487, 1.486, 1.484, 1.483, 1.482, 1.478, 1.473, 1.469, 1.468, - 1.463, 1.464, 1.468, 1.476, 1.479, 1.483, 1.484, 1.486, 1.486, 1.485, 1.484, 1.482, 1.477, 1.473, 1.469, 1.468, - 1.463, 1.464, 1.469, 1.477, 1.481, 1.483, 1.485, 1.487, 1.487, 1.485, 1.485, 1.482, 1.478, 1.474, 1.469, 1.468, - 1.465, 1.465, 1.471, 1.478, 1.481, 1.484, 1.486, 1.488, 1.488, 1.487, 1.485, 1.482, 1.477, 1.472, 1.468, 1.467, - 1.465, 1.466, 1.472, 1.479, 1.482, 1.485, 1.486, 1.488, 1.488, 1.486, 1.484, 1.479, 1.475, 1.472, 1.468, 1.466, - 1.466, 1.466, 1.472, 1.478, 1.482, 1.484, 1.485, 1.488, 1.487, 1.485, 1.483, 1.479, 1.475, 1.472, 1.469, 1.468, - 1.465, 1.466, 1.469, 1.476, 1.481, 1.485, 1.485, 1.486, 1.486, 1.485, 1.483, 1.479, 1.477, 1.474, 1.471, 1.469, - 1.464, 1.465, 1.469, 1.476, 1.481, 1.484, 1.485, 1.487, 1.487, 1.486, 1.485, 1.481, 1.478, 1.475, 1.471, 1.469, - 1.463, 1.464, 1.469, 1.477, 1.481, 1.485, 1.485, 1.488, 1.488, 1.487, 1.486, 1.481, 1.478, 1.475, 1.471, 1.468, - 1.464, 1.465, 1.471, 1.478, 1.482, 1.486, 1.486, 1.488, 1.488, 1.487, 1.486, 1.481, 1.478, 1.475, 1.472, 1.468, - 1.465, 1.466, 1.472, 1.481, 1.483, 1.487, 1.487, 1.488, 1.488, 1.486, 1.485, 1.481, 1.479, 1.476, 1.473, 1.472 - ] - }, - { - "ct": 5930, "table": - [ - 1.443, 1.444, 1.448, 1.453, 1.459, 1.463, 1.465, 1.467, 1.469, 1.469, 1.467, 1.466, 1.462, 1.457, 1.454, 1.451, - 1.443, 1.444, 1.445, 1.451, 1.459, 1.463, 1.465, 1.467, 1.469, 1.469, 1.467, 1.465, 1.461, 1.456, 1.452, 1.451, - 1.444, 1.444, 1.445, 1.451, 1.459, 1.463, 1.466, 1.468, 1.469, 1.469, 1.467, 1.465, 1.461, 1.456, 1.452, 1.449, - 1.444, 1.444, 1.447, 1.452, 1.459, 1.464, 1.467, 1.469, 1.471, 1.469, 1.467, 1.466, 1.461, 1.456, 1.452, 1.449, - 1.444, 1.445, 1.448, 1.452, 1.459, 1.465, 1.469, 1.471, 1.471, 1.471, 1.468, 1.465, 1.461, 1.455, 1.451, 1.449, - 1.445, 1.446, 1.449, 1.453, 1.461, 1.466, 1.469, 1.471, 1.472, 1.469, 1.467, 1.465, 1.459, 1.455, 1.451, 1.447, - 1.446, 1.446, 1.449, 1.453, 1.461, 1.466, 1.469, 1.469, 1.469, 1.469, 1.467, 1.465, 1.459, 1.455, 1.452, 1.449, - 1.446, 1.446, 1.447, 1.451, 1.459, 1.466, 1.469, 1.469, 1.469, 1.469, 1.467, 1.465, 1.461, 1.457, 1.454, 1.451, - 1.444, 1.444, 1.447, 1.451, 1.459, 1.466, 1.469, 1.469, 1.471, 1.471, 1.468, 1.466, 1.462, 1.458, 1.454, 1.452, - 1.444, 1.444, 1.448, 1.453, 1.459, 1.466, 1.469, 1.471, 1.472, 1.472, 1.468, 1.466, 1.462, 1.458, 1.454, 1.449, - 1.446, 1.447, 1.449, 1.454, 1.461, 1.466, 1.471, 1.471, 1.471, 1.471, 1.468, 1.466, 1.462, 1.459, 1.455, 1.449, - 1.447, 1.447, 1.452, 1.457, 1.462, 1.468, 1.472, 1.472, 1.471, 1.471, 1.468, 1.466, 1.462, 1.459, 1.456, 1.455 - ] - } - ], - "luminance_lut": - [ - 1.548, 1.499, 1.387, 1.289, 1.223, 1.183, 1.164, 1.154, 1.153, 1.169, 1.211, 1.265, 1.345, 1.448, 1.581, 1.619, - 1.513, 1.412, 1.307, 1.228, 1.169, 1.129, 1.105, 1.098, 1.103, 1.127, 1.157, 1.209, 1.272, 1.361, 1.481, 1.583, - 1.449, 1.365, 1.257, 1.175, 1.124, 1.085, 1.062, 1.054, 1.059, 1.079, 1.113, 1.151, 1.211, 1.293, 1.407, 1.488, - 1.424, 1.324, 1.222, 1.139, 1.089, 1.056, 1.034, 1.031, 1.034, 1.049, 1.075, 1.115, 1.164, 1.241, 1.351, 1.446, - 1.412, 1.297, 1.203, 1.119, 1.069, 1.039, 1.021, 1.016, 1.022, 1.032, 1.052, 1.086, 1.135, 1.212, 1.321, 1.439, - 1.406, 1.287, 1.195, 1.115, 1.059, 1.028, 1.014, 1.012, 1.015, 1.026, 1.041, 1.074, 1.125, 1.201, 1.302, 1.425, - 1.406, 1.294, 1.205, 1.126, 1.062, 1.031, 1.013, 1.009, 1.011, 1.019, 1.042, 1.079, 1.129, 1.203, 1.302, 1.435, - 1.415, 1.318, 1.229, 1.146, 1.076, 1.039, 1.019, 1.014, 1.017, 1.031, 1.053, 1.093, 1.144, 1.219, 1.314, 1.436, - 1.435, 1.348, 1.246, 1.164, 1.094, 1.059, 1.036, 1.032, 1.037, 1.049, 1.072, 1.114, 1.167, 1.257, 1.343, 1.462, - 1.471, 1.385, 1.278, 1.189, 1.124, 1.084, 1.064, 1.061, 1.069, 1.078, 1.101, 1.146, 1.207, 1.298, 1.415, 1.496, - 1.522, 1.436, 1.323, 1.228, 1.169, 1.118, 1.101, 1.094, 1.099, 1.113, 1.146, 1.194, 1.265, 1.353, 1.474, 1.571, - 1.578, 1.506, 1.378, 1.281, 1.211, 1.156, 1.135, 1.134, 1.139, 1.158, 1.194, 1.251, 1.327, 1.427, 1.559, 1.611 - ], - "sigma": 0.00121, - "sigma_Cb": 0.00115 - }, - "rpi.contrast": - { - "ce_enable": 1, - "gamma_curve": - [ - 0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120, 18051, 6144, 20790, 7168, 23193, - 8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168, - 16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753, 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796, - 32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954, 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476, - 65535, 65535 - ] - }, - "rpi.ccm": - { - "ccms": - [ - { - "ct": 2360, "ccm": - [ - 1.66078, -0.23588, -0.42491, -0.47456, 1.82763, -0.35307, -0.00545, -1.44729, 2.45273 - ] - }, - { - "ct": 2870, "ccm": - [ - 1.78373, -0.55344, -0.23029, -0.39951, 1.69701, -0.29751, 0.01986, -1.06525, 2.04539 - ] - }, - { - "ct": 2970, "ccm": - [ - 1.73511, -0.56973, -0.16537, -0.36338, 1.69878, -0.33539, -0.02354, -0.76813, 1.79168 - ] - }, - { - "ct": 3000, "ccm": - [ - 2.06374, -0.92218, -0.14156, -0.41721, 1.69289, -0.27568, -0.00554, -0.92741, 1.93295 - ] - }, - { - "ct": 3700, "ccm": - [ - 2.13792, -1.08136, -0.05655, -0.34739, 1.58989, -0.24249, -0.00349, -0.76789, 1.77138 - ] - }, - { - "ct": 3870, "ccm": - [ - 1.83834, -0.70528, -0.13307, -0.30499, 1.60523, -0.30024, -0.05701, -0.58313, 1.64014 - ] - }, - { - "ct": 4000, "ccm": - [ - 2.15741, -1.10295, -0.05447, -0.34631, 1.61158, -0.26528, -0.02723, -0.70288, 1.73011 - ] - }, - { - "ct": 4400, "ccm": - [ - 2.05729, -0.95007, -0.10723, -0.41712, 1.78606, -0.36894, -0.11899, -0.55727, 1.67626 - ] - }, - - { - "ct": 4715, "ccm": - [ - 1.90255, -0.77478, -0.12777, -0.31338, 1.88197, -0.56858, -0.06001, -0.61785, 1.67786 - ] - }, - { - "ct": 5920, "ccm": - [ - 1.98691, -0.84671, -0.14019, -0.26581, 1.70615, -0.44035, -0.09532, -0.47332, 1.56864 - ] - }, - { - "ct": 9050, "ccm": - [ - 2.09255, -0.76541, -0.32714, -0.28973, 2.27462, -0.98489, -0.17299, -0.61275, 1.78574 - ] - } - ] - }, - "rpi.sharpen": - { - - }, - "rpi.focus": - { - } -} diff --git a/src/ipa/raspberrypi/data/imx519.json b/src/ipa/raspberrypi/data/imx519.json deleted file mode 100644 index 2ce6a08c..00000000 --- a/src/ipa/raspberrypi/data/imx519.json +++ /dev/null @@ -1,338 +0,0 @@ -{ - "rpi.black_level": - { - "black_level": 4096 - }, - "rpi.dpc": - { - }, - "rpi.lux": - { - "reference_shutter_speed": 13841, - "reference_gain": 2.0, - "reference_aperture": 1.0, - "reference_lux": 900, - "reference_Y": 12064 - }, - "rpi.noise": - { - "reference_constant": 0, - "reference_slope": 2.776 - }, - "rpi.geq": - { - "offset": 189, - "slope": 0.01495 - }, - "rpi.sdn": - { - }, - "rpi.awb": - { - "priors": - [ - { - "lux": 0, "prior": - [ - 2000, 1.0, 3000, 0.0, 13000, 0.0 - ] - }, - { - "lux": 800, "prior": - [ - 2000, 0.0, 6000, 2.0, 13000, 2.0 - ] - }, - { - "lux": 1500, "prior": - [ - 2000, 0.0, 4000, 1.0, 6000, 6.0, 6500, 7.0, 7000, 1.0, 13000, 1.0 - ] - } - ], - "modes": - { - "auto": - { - "lo": 2500, - "hi": 7900 - }, - "incandescent": - { - "lo": 2500, - "hi": 3000 - }, - "tungsten": - { - "lo": 3000, - "hi": 3500 - }, - "fluorescent": - { - "lo": 4000, - "hi": 4700 - }, - "indoor": - { - "lo": 3000, - "hi": 5000 - }, - "daylight": - { - "lo": 5500, - "hi": 6500 - }, - "cloudy": - { - "lo": 7000, - "hi": 8000 - } - }, - "bayes": 1, - "ct_curve": - [ - 2890.0, 0.7328, 0.3734, 3550.0, 0.6228, 0.4763, 4500.0, 0.5208, 0.5825, 5700.0, 0.4467, 0.6671, 7900.0, 0.3858, 0.7411 - ], - "sensitivity_r": 1.0, - "sensitivity_b": 1.0, - "transverse_pos": 0.02027, - "transverse_neg": 0.01935 - }, - "rpi.agc": - { - "metering_modes": - { - "centre-weighted": - { - "weights": - [ - 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 - ] - }, - "spot": - { - "weights": - [ - 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - }, - "matrix": - { - "weights": - [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - ] - } - }, - "exposure_modes": - { - "normal": - { - "shutter": - [ - 100, 10000, 30000, 60000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "short": - { - "shutter": - [ - 100, 5000, 10000, 20000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - } - }, - "constraint_modes": - { - "normal": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - } - ], - "highlight": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - }, - { - "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.8, 1000, 0.8 - ] - } - ] - }, - "y_target": - [ - 0, 0.16, 1000, 0.165, 10000, 0.17 - ] - }, - "rpi.alsc": - { - "omega": 1.3, - "n_iter": 100, - "luminance_strength": 0.5, - "calibrations_Cr": - [ - { - "ct": 3000, "table": - [ - 1.527, 1.521, 1.508, 1.493, 1.476, 1.455, 1.442, 1.441, 1.441, 1.441, 1.448, 1.467, 1.483, 1.494, 1.503, 1.504, - 1.525, 1.513, 1.496, 1.477, 1.461, 1.434, 1.418, 1.409, 1.409, 1.416, 1.429, 1.449, 1.469, 1.485, 1.495, 1.503, - 1.517, 1.506, 1.485, 1.461, 1.434, 1.412, 1.388, 1.376, 1.376, 1.386, 1.405, 1.429, 1.449, 1.471, 1.488, 1.495, - 1.512, 1.496, 1.471, 1.442, 1.412, 1.388, 1.361, 1.344, 1.344, 1.358, 1.384, 1.405, 1.431, 1.456, 1.479, 1.489, - 1.508, 1.488, 1.458, 1.425, 1.393, 1.361, 1.343, 1.322, 1.321, 1.342, 1.358, 1.385, 1.416, 1.445, 1.471, 1.484, - 1.507, 1.482, 1.453, 1.418, 1.382, 1.349, 1.322, 1.318, 1.318, 1.321, 1.345, 1.373, 1.405, 1.437, 1.465, 1.483, - 1.507, 1.482, 1.453, 1.418, 1.382, 1.349, 1.322, 1.313, 1.313, 1.321, 1.345, 1.373, 1.405, 1.437, 1.465, 1.483, - 1.507, 1.485, 1.455, 1.422, 1.387, 1.355, 1.333, 1.319, 1.321, 1.333, 1.351, 1.381, 1.411, 1.441, 1.467, 1.483, - 1.508, 1.489, 1.463, 1.432, 1.401, 1.372, 1.355, 1.333, 1.333, 1.351, 1.369, 1.393, 1.422, 1.448, 1.471, 1.484, - 1.511, 1.494, 1.472, 1.444, 1.416, 1.398, 1.372, 1.361, 1.361, 1.369, 1.393, 1.411, 1.436, 1.458, 1.477, 1.487, - 1.511, 1.496, 1.478, 1.455, 1.436, 1.416, 1.399, 1.391, 1.391, 1.397, 1.411, 1.429, 1.451, 1.466, 1.479, 1.487, - 1.511, 1.495, 1.478, 1.462, 1.448, 1.432, 1.419, 1.419, 1.419, 1.419, 1.429, 1.445, 1.459, 1.471, 1.482, 1.487 - ] - }, - { - "ct": 6000, "table": - [ - 2.581, 2.573, 2.558, 2.539, 2.514, 2.487, 2.473, 2.471, 2.471, 2.471, 2.479, 2.499, 2.517, 2.532, 2.543, 2.544, - 2.575, 2.559, 2.539, 2.521, 2.491, 2.458, 2.435, 2.421, 2.421, 2.429, 2.449, 2.477, 2.499, 2.519, 2.534, 2.543, - 2.561, 2.549, 2.521, 2.491, 2.457, 2.423, 2.393, 2.375, 2.375, 2.387, 2.412, 2.444, 2.475, 2.499, 2.519, 2.532, - 2.552, 2.531, 2.498, 2.459, 2.423, 2.391, 2.349, 2.325, 2.325, 2.344, 2.374, 2.412, 2.444, 2.476, 2.505, 2.519, - 2.543, 2.518, 2.479, 2.435, 2.392, 2.349, 2.324, 2.285, 2.283, 2.313, 2.344, 2.374, 2.417, 2.457, 2.489, 2.506, - 2.541, 2.511, 2.469, 2.421, 2.372, 2.326, 2.284, 2.277, 2.279, 2.283, 2.313, 2.357, 2.401, 2.443, 2.479, 2.504, - 2.541, 2.511, 2.469, 2.421, 2.372, 2.326, 2.284, 2.267, 2.267, 2.281, 2.313, 2.357, 2.401, 2.443, 2.479, 2.504, - 2.541, 2.512, 2.472, 2.425, 2.381, 2.338, 2.302, 2.278, 2.279, 2.301, 2.324, 2.364, 2.407, 2.447, 2.481, 2.504, - 2.544, 2.519, 2.483, 2.441, 2.401, 2.363, 2.338, 2.302, 2.302, 2.324, 2.355, 2.385, 2.423, 2.459, 2.488, 2.506, - 2.549, 2.527, 2.497, 2.463, 2.427, 2.401, 2.363, 2.345, 2.345, 2.355, 2.385, 2.412, 2.444, 2.473, 2.497, 2.509, - 2.552, 2.532, 2.507, 2.481, 2.459, 2.427, 2.402, 2.389, 2.389, 2.394, 2.412, 2.444, 2.465, 2.481, 2.499, 2.511, - 2.553, 2.533, 2.508, 2.489, 2.475, 2.454, 2.429, 2.429, 2.429, 2.429, 2.439, 2.463, 2.481, 2.492, 2.504, 2.511 - ] - } - ], - "calibrations_Cb": - [ - { - "ct": 3000, "table": - [ - 3.132, 3.126, 3.116, 3.103, 3.097, 3.091, 3.087, 3.086, 3.088, 3.091, 3.092, 3.102, 3.113, 3.121, 3.141, 3.144, - 3.149, 3.132, 3.123, 3.108, 3.101, 3.096, 3.091, 3.089, 3.091, 3.092, 3.101, 3.107, 3.116, 3.129, 3.144, 3.153, - 3.161, 3.149, 3.129, 3.121, 3.108, 3.103, 3.101, 3.101, 3.101, 3.103, 3.107, 3.116, 3.125, 3.134, 3.153, 3.159, - 3.176, 3.161, 3.144, 3.129, 3.124, 3.121, 3.117, 3.118, 3.118, 3.119, 3.122, 3.125, 3.134, 3.146, 3.159, 3.171, - 3.183, 3.176, 3.157, 3.144, 3.143, 3.143, 3.139, 3.141, 3.141, 3.141, 3.141, 3.141, 3.146, 3.161, 3.171, 3.179, - 3.189, 3.183, 3.165, 3.157, 3.156, 3.157, 3.159, 3.163, 3.163, 3.163, 3.163, 3.161, 3.163, 3.169, 3.179, 3.187, - 3.199, 3.189, 3.171, 3.165, 3.164, 3.167, 3.171, 3.173, 3.173, 3.172, 3.171, 3.169, 3.169, 3.175, 3.187, 3.189, - 3.206, 3.196, 3.177, 3.171, 3.165, 3.167, 3.171, 3.173, 3.173, 3.172, 3.171, 3.171, 3.173, 3.177, 3.192, 3.194, - 3.209, 3.197, 3.178, 3.171, 3.164, 3.161, 3.159, 3.161, 3.162, 3.164, 3.167, 3.171, 3.173, 3.181, 3.193, 3.198, - 3.204, 3.194, 3.176, 3.165, 3.161, 3.156, 3.154, 3.154, 3.159, 3.161, 3.164, 3.168, 3.173, 3.182, 3.198, 3.199, - 3.199, 3.191, 3.176, 3.169, 3.161, 3.157, 3.153, 3.153, 3.156, 3.161, 3.164, 3.168, 3.173, 3.186, 3.196, 3.199, - 3.199, 3.188, 3.179, 3.173, 3.165, 3.157, 3.153, 3.154, 3.156, 3.159, 3.167, 3.171, 3.176, 3.185, 3.193, 3.198 - ] - }, - { - "ct": 6000, "table": - [ - 1.579, 1.579, 1.577, 1.574, 1.573, 1.571, 1.571, 1.571, 1.571, 1.569, 1.569, 1.571, 1.572, 1.574, 1.577, 1.578, - 1.584, 1.579, 1.578, 1.575, 1.573, 1.572, 1.571, 1.572, 1.572, 1.571, 1.571, 1.572, 1.573, 1.576, 1.578, 1.579, - 1.587, 1.584, 1.579, 1.578, 1.575, 1.573, 1.573, 1.575, 1.575, 1.574, 1.573, 1.574, 1.576, 1.578, 1.581, 1.581, - 1.591, 1.587, 1.584, 1.579, 1.578, 1.579, 1.579, 1.581, 1.581, 1.581, 1.578, 1.577, 1.578, 1.581, 1.585, 1.586, - 1.595, 1.591, 1.587, 1.585, 1.585, 1.586, 1.587, 1.587, 1.588, 1.588, 1.585, 1.584, 1.584, 1.586, 1.589, 1.589, - 1.597, 1.595, 1.591, 1.589, 1.591, 1.593, 1.595, 1.596, 1.597, 1.597, 1.595, 1.594, 1.592, 1.592, 1.593, 1.593, - 1.601, 1.597, 1.593, 1.592, 1.593, 1.595, 1.598, 1.599, 1.602, 1.601, 1.598, 1.596, 1.595, 1.596, 1.595, 1.595, - 1.601, 1.599, 1.594, 1.593, 1.593, 1.595, 1.598, 1.599, 1.602, 1.601, 1.598, 1.597, 1.597, 1.597, 1.597, 1.597, - 1.602, 1.599, 1.594, 1.593, 1.592, 1.593, 1.595, 1.597, 1.597, 1.598, 1.598, 1.597, 1.597, 1.597, 1.598, 1.598, - 1.599, 1.598, 1.594, 1.592, 1.591, 1.591, 1.592, 1.595, 1.596, 1.597, 1.597, 1.597, 1.597, 1.599, 1.599, 1.599, - 1.598, 1.596, 1.594, 1.593, 1.592, 1.592, 1.592, 1.594, 1.595, 1.597, 1.597, 1.597, 1.598, 1.599, 1.599, 1.599, - 1.597, 1.595, 1.594, 1.594, 1.593, 1.592, 1.593, 1.595, 1.595, 1.597, 1.598, 1.598, 1.598, 1.599, 1.599, 1.599 - ] - } - ], - "luminance_lut": - [ - 2.887, 2.754, 2.381, 2.105, 1.859, 1.678, 1.625, 1.623, 1.623, 1.624, 1.669, 1.849, 2.092, 2.362, 2.723, 2.838, - 2.754, 2.443, 2.111, 1.905, 1.678, 1.542, 1.455, 1.412, 1.412, 1.452, 1.535, 1.665, 1.893, 2.096, 2.413, 2.723, - 2.443, 2.216, 1.911, 1.678, 1.537, 1.372, 1.288, 1.245, 1.245, 1.283, 1.363, 1.527, 1.665, 1.895, 2.193, 2.413, - 2.318, 2.057, 1.764, 1.541, 1.372, 1.282, 1.159, 1.113, 1.113, 1.151, 1.269, 1.363, 1.527, 1.749, 2.034, 2.278, - 2.259, 1.953, 1.671, 1.452, 1.283, 1.159, 1.107, 1.018, 1.017, 1.097, 1.151, 1.269, 1.437, 1.655, 1.931, 2.222, - 2.257, 1.902, 1.624, 1.408, 1.239, 1.111, 1.019, 1.011, 1.005, 1.014, 1.098, 1.227, 1.395, 1.608, 1.883, 2.222, - 2.257, 1.902, 1.624, 1.408, 1.239, 1.111, 1.016, 1.001, 1.001, 1.007, 1.098, 1.227, 1.395, 1.608, 1.883, 2.222, - 2.257, 1.946, 1.666, 1.448, 1.281, 1.153, 1.093, 1.013, 1.008, 1.089, 1.143, 1.269, 1.437, 1.654, 1.934, 2.226, - 2.309, 2.044, 1.756, 1.532, 1.363, 1.259, 1.153, 1.093, 1.093, 1.143, 1.264, 1.354, 1.524, 1.746, 2.035, 2.284, - 2.425, 2.201, 1.896, 1.662, 1.519, 1.363, 1.259, 1.214, 1.214, 1.264, 1.354, 1.519, 1.655, 1.888, 2.191, 2.413, - 2.724, 2.417, 2.091, 1.888, 1.662, 1.519, 1.419, 1.373, 1.373, 1.425, 1.521, 1.655, 1.885, 2.089, 2.409, 2.722, - 2.858, 2.724, 2.356, 2.085, 1.842, 1.658, 1.581, 1.577, 1.577, 1.579, 1.653, 1.838, 2.084, 2.359, 2.722, 2.842 - ], - "sigma": 0.00372, - "sigma_Cb": 0.00244 - }, - "rpi.contrast": - { - "ce_enable": 1, - "gamma_curve": - [ - 0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120, 18051, 6144, 20790, 7168, 23193, - 8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168, - 16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753, 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796, - 32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954, 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476, - 65535, 65535 - ] - }, - "rpi.ccm": - { - "ccms": - [ - { - "ct": 2890, "ccm": - [ - 1.36754, -0.18448, -0.18306, -0.32356, 1.44826, -0.12471, -0.00412, -0.69936, 1.70348 - ] - }, - { - "ct": 2920, "ccm": - [ - 1.26704, 0.01624, -0.28328, -0.28516, 1.38934, -0.10419, -0.04854, -0.82211, 1.87066 - ] - }, - { - "ct": 3550, "ccm": - [ - 1.42836, -0.27235, -0.15601, -0.28751, 1.41075, -0.12325, -0.01812, -0.54849, 1.56661 - ] - }, - { - "ct": 4500, "ccm": - [ - 1.36328, -0.19569, -0.16759, -0.25254, 1.52248, -0.26994, -0.01575, -0.53155, 1.54729 - ] - }, - { - "ct": 5700, "ccm": - [ - 1.49207, -0.37245, -0.11963, -0.21493, 1.40005, -0.18512, -0.03781, -0.38779, 1.42561 - ] - }, - { - "ct": 7900, "ccm": - [ - 1.34849, -0.05425, -0.29424, -0.22182, 1.77684, -0.55502, -0.07403, -0.55336, 1.62739 - ] - } - ] - }, - "rpi.sharpen": - { - } -} diff --git a/src/ipa/raspberrypi/data/meson.build b/src/ipa/raspberrypi/data/meson.build deleted file mode 100644 index 211811cf..00000000 --- a/src/ipa/raspberrypi/data/meson.build +++ /dev/null @@ -1,20 +0,0 @@ -# SPDX-License-Identifier: CC0-1.0 - -conf_files = files([ - 'imx219.json', - 'imx219_noir.json', - 'imx290.json', - 'imx296.json', - 'imx378.json', - 'imx477.json', - 'imx477_noir.json', - 'imx519.json', - 'ov5647.json', - 'ov5647_noir.json', - 'ov9281.json', - 'se327m12.json', - 'uncalibrated.json', -]) - -install_data(conf_files, - install_dir : ipa_data_dir / 'raspberrypi') diff --git a/src/ipa/raspberrypi/data/ov5647.json b/src/ipa/raspberrypi/data/ov5647.json deleted file mode 100644 index 24bc06fb..00000000 --- a/src/ipa/raspberrypi/data/ov5647.json +++ /dev/null @@ -1,409 +0,0 @@ -{ - "rpi.black_level": - { - "black_level": 1024 - }, - "rpi.dpc": - { - - }, - "rpi.lux": - { - "reference_shutter_speed": 21663, - "reference_gain": 1.0, - "reference_aperture": 1.0, - "reference_lux": 987, - "reference_Y": 8961 - }, - "rpi.noise": - { - "reference_constant": 0, - "reference_slope": 4.25 - }, - "rpi.geq": - { - "offset": 401, - "slope": 0.05619 - }, - "rpi.sdn": - { - - }, - "rpi.awb": - { - "priors": - [ - { - "lux": 0, "prior": - [ - 2000, 1.0, 3000, 0.0, 13000, 0.0 - ] - }, - { - "lux": 800, "prior": - [ - 2000, 0.0, 6000, 2.0, 13000, 2.0 - ] - }, - { - "lux": 1500, "prior": - [ - 2000, 0.0, 4000, 1.0, 6000, 6.0, 6500, 7.0, 7000, 1.0, 13000, 1.0 - ] - } - ], - "modes": - { - "auto": - { - "lo": 2500, - "hi": 8000 - }, - "incandescent": - { - "lo": 2500, - "hi": 3000 - }, - "tungsten": - { - "lo": 3000, - "hi": 3500 - }, - "fluorescent": - { - "lo": 4000, - "hi": 4700 - }, - "indoor": - { - "lo": 3000, - "hi": 5000 - }, - "daylight": - { - "lo": 5500, - "hi": 6500 - }, - "cloudy": - { - "lo": 7000, - "hi": 8600 - } - }, - "bayes": 1, - "ct_curve": - [ - 2500.0, 1.0289, 0.4503, 2803.0, 0.9428, 0.5108, 2914.0, 0.9406, 0.5127, 3605.0, 0.8261, 0.6249, 4540.0, 0.7331, 0.7533, 5699.0, - 0.6715, 0.8627, 8625.0, 0.6081, 1.0012 - ], - "sensitivity_r": 1.05, - "sensitivity_b": 1.05, - "transverse_pos": 0.0321, - "transverse_neg": 0.04313 - }, - "rpi.agc": - { - "metering_modes": - { - "centre-weighted": - { - "weights": - [ - 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 - ] - }, - "spot": - { - "weights": - [ - 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - }, - "matrix": - { - "weights": - [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - ] - } - }, - "exposure_modes": - { - "normal": - { - "shutter": - [ - 100, 10000, 30000, 60000, 66666 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "short": - { - "shutter": - [ - 100, 5000, 10000, 20000, 33333 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "long": - { - "shutter": - [ - 100, 10000, 30000, 60000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 12.0 - ] - } - }, - "constraint_modes": - { - "normal": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - } - ], - "highlight": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - }, - { - "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.8, 1000, 0.8 - ] - } - ], - "shadows": - [ - { - "bound": "LOWER", "q_lo": 0.0, "q_hi": 0.5, "y_target": - [ - 0, 0.17, 1000, 0.17 - ] - } - ] - }, - "y_target": - [ - 0, 0.16, 1000, 0.165, 10000, 0.17 - ], - "base_ev": 1.25 - }, - "rpi.alsc": - { - "omega": 1.3, - "n_iter": 100, - "luminance_strength": 0.5, - "calibrations_Cr": - [ - { - "ct": 3000, "table": - [ - 1.105, 1.103, 1.093, 1.083, 1.071, 1.065, 1.065, 1.065, 1.066, 1.069, 1.072, 1.077, 1.084, 1.089, 1.093, 1.093, - 1.103, 1.096, 1.084, 1.072, 1.059, 1.051, 1.047, 1.047, 1.051, 1.053, 1.059, 1.067, 1.075, 1.082, 1.085, 1.086, - 1.096, 1.084, 1.072, 1.059, 1.051, 1.045, 1.039, 1.038, 1.039, 1.045, 1.049, 1.057, 1.063, 1.072, 1.081, 1.082, - 1.092, 1.075, 1.061, 1.052, 1.045, 1.039, 1.036, 1.035, 1.035, 1.039, 1.044, 1.049, 1.056, 1.063, 1.072, 1.081, - 1.092, 1.073, 1.058, 1.048, 1.043, 1.038, 1.035, 1.033, 1.033, 1.035, 1.039, 1.044, 1.051, 1.057, 1.069, 1.078, - 1.091, 1.068, 1.054, 1.045, 1.041, 1.038, 1.035, 1.032, 1.032, 1.032, 1.036, 1.041, 1.045, 1.055, 1.069, 1.078, - 1.091, 1.068, 1.052, 1.043, 1.041, 1.038, 1.035, 1.032, 1.031, 1.032, 1.034, 1.036, 1.043, 1.055, 1.069, 1.078, - 1.092, 1.068, 1.052, 1.047, 1.042, 1.041, 1.038, 1.035, 1.032, 1.032, 1.035, 1.039, 1.043, 1.055, 1.071, 1.079, - 1.092, 1.073, 1.057, 1.051, 1.047, 1.047, 1.044, 1.041, 1.038, 1.038, 1.039, 1.043, 1.051, 1.059, 1.076, 1.083, - 1.092, 1.081, 1.068, 1.058, 1.056, 1.056, 1.053, 1.052, 1.049, 1.048, 1.048, 1.051, 1.059, 1.066, 1.083, 1.085, - 1.091, 1.087, 1.081, 1.068, 1.065, 1.064, 1.062, 1.062, 1.061, 1.056, 1.056, 1.056, 1.064, 1.069, 1.084, 1.089, - 1.091, 1.089, 1.085, 1.079, 1.069, 1.068, 1.067, 1.067, 1.067, 1.063, 1.061, 1.063, 1.068, 1.069, 1.081, 1.092 - ] - }, - { - "ct": 5000, "table": - [ - 1.486, 1.484, 1.468, 1.449, 1.427, 1.403, 1.399, 1.399, 1.399, 1.404, 1.413, 1.433, 1.454, 1.473, 1.482, 1.488, - 1.484, 1.472, 1.454, 1.431, 1.405, 1.381, 1.365, 1.365, 1.367, 1.373, 1.392, 1.411, 1.438, 1.458, 1.476, 1.481, - 1.476, 1.458, 1.433, 1.405, 1.381, 1.361, 1.339, 1.334, 1.334, 1.346, 1.362, 1.391, 1.411, 1.438, 1.462, 1.474, - 1.471, 1.443, 1.417, 1.388, 1.361, 1.339, 1.321, 1.313, 1.313, 1.327, 1.346, 1.362, 1.391, 1.422, 1.453, 1.473, - 1.469, 1.439, 1.408, 1.377, 1.349, 1.321, 1.312, 1.299, 1.299, 1.311, 1.327, 1.348, 1.378, 1.415, 1.446, 1.468, - 1.468, 1.434, 1.402, 1.371, 1.341, 1.316, 1.299, 1.296, 1.295, 1.299, 1.314, 1.338, 1.371, 1.408, 1.441, 1.466, - 1.468, 1.434, 1.401, 1.371, 1.341, 1.316, 1.301, 1.296, 1.295, 1.297, 1.314, 1.338, 1.369, 1.408, 1.441, 1.465, - 1.469, 1.436, 1.401, 1.374, 1.348, 1.332, 1.315, 1.301, 1.301, 1.313, 1.324, 1.342, 1.372, 1.409, 1.442, 1.465, - 1.471, 1.444, 1.413, 1.388, 1.371, 1.348, 1.332, 1.323, 1.323, 1.324, 1.342, 1.362, 1.386, 1.418, 1.449, 1.467, - 1.473, 1.454, 1.431, 1.407, 1.388, 1.371, 1.359, 1.352, 1.351, 1.351, 1.362, 1.383, 1.404, 1.433, 1.462, 1.472, - 1.474, 1.461, 1.447, 1.424, 1.407, 1.394, 1.385, 1.381, 1.379, 1.381, 1.383, 1.401, 1.419, 1.444, 1.466, 1.481, - 1.474, 1.464, 1.455, 1.442, 1.421, 1.408, 1.403, 1.403, 1.403, 1.399, 1.402, 1.415, 1.432, 1.446, 1.467, 1.483 - ] - }, - { - "ct": 6500, "table": - [ - 1.567, 1.565, 1.555, 1.541, 1.525, 1.518, 1.518, 1.518, 1.521, 1.527, 1.532, 1.541, 1.551, 1.559, 1.567, 1.569, - 1.565, 1.557, 1.542, 1.527, 1.519, 1.515, 1.511, 1.516, 1.519, 1.524, 1.528, 1.533, 1.542, 1.553, 1.559, 1.562, - 1.561, 1.546, 1.532, 1.521, 1.518, 1.515, 1.511, 1.516, 1.519, 1.524, 1.528, 1.529, 1.533, 1.542, 1.554, 1.559, - 1.561, 1.539, 1.526, 1.524, 1.521, 1.521, 1.522, 1.524, 1.525, 1.531, 1.529, 1.529, 1.531, 1.538, 1.549, 1.558, - 1.559, 1.538, 1.526, 1.525, 1.524, 1.528, 1.534, 1.536, 1.536, 1.536, 1.532, 1.529, 1.531, 1.537, 1.548, 1.556, - 1.561, 1.537, 1.525, 1.524, 1.526, 1.532, 1.537, 1.539, 1.538, 1.537, 1.532, 1.529, 1.529, 1.537, 1.546, 1.556, - 1.561, 1.536, 1.524, 1.522, 1.525, 1.532, 1.538, 1.538, 1.537, 1.533, 1.528, 1.526, 1.527, 1.536, 1.546, 1.555, - 1.561, 1.537, 1.522, 1.521, 1.524, 1.531, 1.536, 1.537, 1.534, 1.529, 1.526, 1.522, 1.523, 1.534, 1.547, 1.555, - 1.561, 1.538, 1.524, 1.522, 1.526, 1.531, 1.535, 1.535, 1.534, 1.527, 1.524, 1.522, 1.522, 1.535, 1.549, 1.556, - 1.558, 1.543, 1.532, 1.526, 1.526, 1.529, 1.534, 1.535, 1.533, 1.526, 1.523, 1.522, 1.524, 1.537, 1.552, 1.557, - 1.555, 1.546, 1.541, 1.528, 1.527, 1.528, 1.531, 1.533, 1.531, 1.527, 1.522, 1.522, 1.526, 1.536, 1.552, 1.561, - 1.555, 1.547, 1.542, 1.538, 1.526, 1.526, 1.529, 1.531, 1.529, 1.528, 1.519, 1.519, 1.527, 1.531, 1.543, 1.561 - ] - } - ], - "calibrations_Cb": - [ - { - "ct": 3000, "table": - [ - 1.684, 1.688, 1.691, 1.697, 1.709, 1.722, 1.735, 1.745, 1.747, 1.745, 1.731, 1.719, 1.709, 1.705, 1.699, 1.699, - 1.684, 1.689, 1.694, 1.708, 1.721, 1.735, 1.747, 1.762, 1.762, 1.758, 1.745, 1.727, 1.716, 1.707, 1.701, 1.699, - 1.684, 1.691, 1.704, 1.719, 1.734, 1.755, 1.772, 1.786, 1.789, 1.788, 1.762, 1.745, 1.724, 1.709, 1.702, 1.698, - 1.682, 1.694, 1.709, 1.729, 1.755, 1.773, 1.798, 1.815, 1.817, 1.808, 1.788, 1.762, 1.733, 1.714, 1.704, 1.699, - 1.682, 1.693, 1.713, 1.742, 1.772, 1.798, 1.815, 1.829, 1.831, 1.821, 1.807, 1.773, 1.742, 1.716, 1.703, 1.699, - 1.681, 1.693, 1.713, 1.742, 1.772, 1.799, 1.828, 1.839, 1.839, 1.828, 1.807, 1.774, 1.742, 1.715, 1.699, 1.695, - 1.679, 1.691, 1.712, 1.739, 1.771, 1.798, 1.825, 1.829, 1.831, 1.818, 1.801, 1.774, 1.738, 1.712, 1.695, 1.691, - 1.676, 1.685, 1.703, 1.727, 1.761, 1.784, 1.801, 1.817, 1.817, 1.801, 1.779, 1.761, 1.729, 1.706, 1.691, 1.684, - 1.669, 1.678, 1.692, 1.714, 1.741, 1.764, 1.784, 1.795, 1.795, 1.779, 1.761, 1.738, 1.713, 1.696, 1.683, 1.679, - 1.664, 1.671, 1.679, 1.693, 1.716, 1.741, 1.762, 1.769, 1.769, 1.753, 1.738, 1.713, 1.701, 1.687, 1.681, 1.676, - 1.661, 1.664, 1.671, 1.679, 1.693, 1.714, 1.732, 1.739, 1.739, 1.729, 1.708, 1.701, 1.685, 1.679, 1.676, 1.677, - 1.659, 1.661, 1.664, 1.671, 1.679, 1.693, 1.712, 1.714, 1.714, 1.708, 1.701, 1.687, 1.679, 1.672, 1.673, 1.677 - ] - }, - { - "ct": 5000, "table": - [ - 1.177, 1.183, 1.187, 1.191, 1.197, 1.206, 1.213, 1.215, 1.215, 1.215, 1.211, 1.204, 1.196, 1.191, 1.183, 1.182, - 1.179, 1.185, 1.191, 1.196, 1.206, 1.217, 1.224, 1.229, 1.229, 1.226, 1.221, 1.212, 1.202, 1.195, 1.188, 1.182, - 1.183, 1.191, 1.196, 1.206, 1.217, 1.229, 1.239, 1.245, 1.245, 1.245, 1.233, 1.221, 1.212, 1.199, 1.193, 1.187, - 1.183, 1.192, 1.201, 1.212, 1.229, 1.241, 1.252, 1.259, 1.259, 1.257, 1.245, 1.233, 1.217, 1.201, 1.194, 1.192, - 1.183, 1.192, 1.202, 1.219, 1.238, 1.252, 1.261, 1.269, 1.268, 1.261, 1.257, 1.241, 1.223, 1.204, 1.194, 1.191, - 1.182, 1.192, 1.202, 1.219, 1.239, 1.255, 1.266, 1.271, 1.271, 1.265, 1.258, 1.242, 1.223, 1.205, 1.192, 1.191, - 1.181, 1.189, 1.199, 1.218, 1.239, 1.254, 1.262, 1.268, 1.268, 1.258, 1.253, 1.241, 1.221, 1.204, 1.191, 1.187, - 1.179, 1.184, 1.193, 1.211, 1.232, 1.243, 1.254, 1.257, 1.256, 1.253, 1.242, 1.232, 1.216, 1.199, 1.187, 1.183, - 1.174, 1.179, 1.187, 1.202, 1.218, 1.232, 1.243, 1.246, 1.246, 1.239, 1.232, 1.218, 1.207, 1.191, 1.183, 1.179, - 1.169, 1.175, 1.181, 1.189, 1.202, 1.218, 1.229, 1.232, 1.232, 1.224, 1.218, 1.207, 1.199, 1.185, 1.181, 1.174, - 1.164, 1.168, 1.175, 1.179, 1.189, 1.201, 1.209, 1.213, 1.213, 1.209, 1.201, 1.198, 1.186, 1.181, 1.174, 1.173, - 1.161, 1.166, 1.171, 1.175, 1.179, 1.189, 1.197, 1.198, 1.198, 1.197, 1.196, 1.186, 1.182, 1.175, 1.173, 1.173 - ] - }, - { - "ct": 6500, "table": - [ - 1.166, 1.171, 1.173, 1.178, 1.187, 1.193, 1.201, 1.205, 1.205, 1.205, 1.199, 1.191, 1.184, 1.179, 1.174, 1.171, - 1.166, 1.172, 1.176, 1.184, 1.195, 1.202, 1.209, 1.216, 1.216, 1.213, 1.208, 1.201, 1.189, 1.182, 1.176, 1.171, - 1.166, 1.173, 1.183, 1.195, 1.202, 1.214, 1.221, 1.228, 1.229, 1.228, 1.221, 1.209, 1.201, 1.186, 1.179, 1.174, - 1.165, 1.174, 1.187, 1.201, 1.214, 1.223, 1.235, 1.241, 1.242, 1.241, 1.229, 1.221, 1.205, 1.188, 1.181, 1.177, - 1.165, 1.174, 1.189, 1.207, 1.223, 1.235, 1.242, 1.253, 1.252, 1.245, 1.241, 1.228, 1.211, 1.189, 1.181, 1.178, - 1.164, 1.173, 1.189, 1.207, 1.224, 1.238, 1.249, 1.255, 1.255, 1.249, 1.242, 1.228, 1.211, 1.191, 1.179, 1.176, - 1.163, 1.172, 1.187, 1.207, 1.223, 1.237, 1.245, 1.253, 1.252, 1.243, 1.237, 1.228, 1.207, 1.188, 1.176, 1.173, - 1.159, 1.167, 1.179, 1.199, 1.217, 1.227, 1.237, 1.241, 1.241, 1.237, 1.228, 1.217, 1.201, 1.184, 1.174, 1.169, - 1.156, 1.164, 1.172, 1.189, 1.205, 1.217, 1.226, 1.229, 1.229, 1.222, 1.217, 1.204, 1.192, 1.177, 1.171, 1.166, - 1.154, 1.159, 1.166, 1.177, 1.189, 1.205, 1.213, 1.216, 1.216, 1.209, 1.204, 1.192, 1.183, 1.172, 1.168, 1.162, - 1.152, 1.155, 1.161, 1.166, 1.177, 1.188, 1.195, 1.198, 1.199, 1.196, 1.187, 1.183, 1.173, 1.168, 1.163, 1.162, - 1.151, 1.154, 1.158, 1.162, 1.168, 1.177, 1.183, 1.184, 1.184, 1.184, 1.182, 1.172, 1.168, 1.165, 1.162, 1.161 - ] - } - ], - "luminance_lut": - [ - 2.236, 2.111, 1.912, 1.741, 1.579, 1.451, 1.379, 1.349, 1.349, 1.361, 1.411, 1.505, 1.644, 1.816, 2.034, 2.159, - 2.139, 1.994, 1.796, 1.625, 1.467, 1.361, 1.285, 1.248, 1.239, 1.265, 1.321, 1.408, 1.536, 1.703, 1.903, 2.087, - 2.047, 1.898, 1.694, 1.511, 1.373, 1.254, 1.186, 1.152, 1.142, 1.166, 1.226, 1.309, 1.441, 1.598, 1.799, 1.978, - 1.999, 1.824, 1.615, 1.429, 1.281, 1.179, 1.113, 1.077, 1.071, 1.096, 1.153, 1.239, 1.357, 1.525, 1.726, 1.915, - 1.976, 1.773, 1.563, 1.374, 1.222, 1.119, 1.064, 1.032, 1.031, 1.049, 1.099, 1.188, 1.309, 1.478, 1.681, 1.893, - 1.973, 1.756, 1.542, 1.351, 1.196, 1.088, 1.028, 1.011, 1.004, 1.029, 1.077, 1.169, 1.295, 1.459, 1.663, 1.891, - 1.973, 1.761, 1.541, 1.349, 1.193, 1.087, 1.031, 1.006, 1.006, 1.023, 1.075, 1.169, 1.298, 1.463, 1.667, 1.891, - 1.982, 1.789, 1.568, 1.373, 1.213, 1.111, 1.051, 1.029, 1.024, 1.053, 1.106, 1.199, 1.329, 1.495, 1.692, 1.903, - 2.015, 1.838, 1.621, 1.426, 1.268, 1.159, 1.101, 1.066, 1.068, 1.099, 1.166, 1.259, 1.387, 1.553, 1.751, 1.937, - 2.076, 1.911, 1.692, 1.507, 1.346, 1.236, 1.169, 1.136, 1.139, 1.174, 1.242, 1.349, 1.475, 1.641, 1.833, 2.004, - 2.193, 2.011, 1.798, 1.604, 1.444, 1.339, 1.265, 1.235, 1.237, 1.273, 1.351, 1.461, 1.598, 1.758, 1.956, 2.125, - 2.263, 2.154, 1.916, 1.711, 1.549, 1.432, 1.372, 1.356, 1.356, 1.383, 1.455, 1.578, 1.726, 1.914, 2.119, 2.211 - ], - "sigma": 0.006, - "sigma_Cb": 0.00208 - }, - "rpi.contrast": - { - "ce_enable": 1, - "gamma_curve": - [ - 0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120, 18051, 6144, 20790, 7168, 23193, - 8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168, - 16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753, 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796, - 32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954, 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476, - 65535, 65535 - ] - }, - "rpi.ccm": - { - "ccms": - [ - { - "ct": 2500, "ccm": - [ - 1.70741, -0.05307, -0.65433, -0.62822, 1.68836, -0.06014, -0.04452, -1.87628, 2.92079 - ] - }, - { - "ct": 2803, "ccm": - [ - 1.74383, -0.18731, -0.55652, -0.56491, 1.67772, -0.11281, -0.01522, -1.60635, 2.62157 - ] - }, - { - "ct": 2912, "ccm": - [ - 1.75215, -0.22221, -0.52995, -0.54568, 1.63522, -0.08954, 0.02633, -1.56997, 2.54364 - ] - }, - { - "ct": 2914, "ccm": - [ - 1.72423, -0.28939, -0.43484, -0.55188, 1.62925, -0.07737, 0.01959, -1.28661, 2.26702 - ] - }, - { - "ct": 3605, "ccm": - [ - 1.80381, -0.43646, -0.36735, -0.46505, 1.56814, -0.10309, 0.00929, -1.00424, 1.99495 - ] - }, - { - "ct": 4540, "ccm": - [ - 1.85263, -0.46545, -0.38719, -0.44136, 1.68443, -0.24307, 0.04108, -0.85599, 1.81491 - ] - }, - { - "ct": 5699, "ccm": - [ - 1.98595, -0.63542, -0.35054, -0.34623, 1.54146, -0.19522, 0.00411, -0.70936, 1.70525 - ] - }, - { - "ct": 8625, "ccm": - [ - 2.21637, -0.56663, -0.64974, -0.41133, 1.96625, -0.55492, -0.02307, -0.83529, 1.85837 - ] - } - ] - }, - "rpi.sharpen": - { - - } -} diff --git a/src/ipa/raspberrypi/data/ov5647_noir.json b/src/ipa/raspberrypi/data/ov5647_noir.json deleted file mode 100644 index 1c628ed1..00000000 --- a/src/ipa/raspberrypi/data/ov5647_noir.json +++ /dev/null @@ -1,341 +0,0 @@ -{ - "rpi.black_level": - { - "black_level": 1024 - }, - "rpi.dpc": - { - - }, - "rpi.lux": - { - "reference_shutter_speed": 21663, - "reference_gain": 1.0, - "reference_aperture": 1.0, - "reference_lux": 987, - "reference_Y": 8961 - }, - "rpi.noise": - { - "reference_constant": 0, - "reference_slope": 4.25 - }, - "rpi.geq": - { - "offset": 401, - "slope": 0.05619 - }, - "rpi.sdn": - { - - }, - "rpi.awb": - { - "bayes": 0 - }, - "rpi.agc": - { - "metering_modes": - { - "centre-weighted": - { - "weights": - [ - 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 - ] - }, - "spot": - { - "weights": - [ - 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - }, - "matrix": - { - "weights": - [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - ] - } - }, - "exposure_modes": - { - "normal": - { - "shutter": - [ - 100, 10000, 30000, 60000, 66666 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "short": - { - "shutter": - [ - 100, 5000, 10000, 20000, 33333 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "long": - { - "shutter": - [ - 100, 10000, 30000, 60000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 12.0 - ] - } - }, - "constraint_modes": - { - "normal": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - } - ], - "highlight": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - }, - { - "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.8, 1000, 0.8 - ] - } - ], - "shadows": - [ - { - "bound": "LOWER", "q_lo": 0.0, "q_hi": 0.5, "y_target": - [ - 0, 0.17, 1000, 0.17 - ] - } - ] - }, - "y_target": - [ - 0, 0.16, 1000, 0.165, 10000, 0.17 - ], - "base_ev": 1.25 - }, - "rpi.alsc": - { - "omega": 1.3, - "n_iter": 100, - "luminance_strength": 0.5, - "calibrations_Cr": - [ - { - "ct": 3000, "table": - [ - 1.105, 1.103, 1.093, 1.083, 1.071, 1.065, 1.065, 1.065, 1.066, 1.069, 1.072, 1.077, 1.084, 1.089, 1.093, 1.093, - 1.103, 1.096, 1.084, 1.072, 1.059, 1.051, 1.047, 1.047, 1.051, 1.053, 1.059, 1.067, 1.075, 1.082, 1.085, 1.086, - 1.096, 1.084, 1.072, 1.059, 1.051, 1.045, 1.039, 1.038, 1.039, 1.045, 1.049, 1.057, 1.063, 1.072, 1.081, 1.082, - 1.092, 1.075, 1.061, 1.052, 1.045, 1.039, 1.036, 1.035, 1.035, 1.039, 1.044, 1.049, 1.056, 1.063, 1.072, 1.081, - 1.092, 1.073, 1.058, 1.048, 1.043, 1.038, 1.035, 1.033, 1.033, 1.035, 1.039, 1.044, 1.051, 1.057, 1.069, 1.078, - 1.091, 1.068, 1.054, 1.045, 1.041, 1.038, 1.035, 1.032, 1.032, 1.032, 1.036, 1.041, 1.045, 1.055, 1.069, 1.078, - 1.091, 1.068, 1.052, 1.043, 1.041, 1.038, 1.035, 1.032, 1.031, 1.032, 1.034, 1.036, 1.043, 1.055, 1.069, 1.078, - 1.092, 1.068, 1.052, 1.047, 1.042, 1.041, 1.038, 1.035, 1.032, 1.032, 1.035, 1.039, 1.043, 1.055, 1.071, 1.079, - 1.092, 1.073, 1.057, 1.051, 1.047, 1.047, 1.044, 1.041, 1.038, 1.038, 1.039, 1.043, 1.051, 1.059, 1.076, 1.083, - 1.092, 1.081, 1.068, 1.058, 1.056, 1.056, 1.053, 1.052, 1.049, 1.048, 1.048, 1.051, 1.059, 1.066, 1.083, 1.085, - 1.091, 1.087, 1.081, 1.068, 1.065, 1.064, 1.062, 1.062, 1.061, 1.056, 1.056, 1.056, 1.064, 1.069, 1.084, 1.089, - 1.091, 1.089, 1.085, 1.079, 1.069, 1.068, 1.067, 1.067, 1.067, 1.063, 1.061, 1.063, 1.068, 1.069, 1.081, 1.092 - ] - }, - { - "ct": 5000, "table": - [ - 1.486, 1.484, 1.468, 1.449, 1.427, 1.403, 1.399, 1.399, 1.399, 1.404, 1.413, 1.433, 1.454, 1.473, 1.482, 1.488, - 1.484, 1.472, 1.454, 1.431, 1.405, 1.381, 1.365, 1.365, 1.367, 1.373, 1.392, 1.411, 1.438, 1.458, 1.476, 1.481, - 1.476, 1.458, 1.433, 1.405, 1.381, 1.361, 1.339, 1.334, 1.334, 1.346, 1.362, 1.391, 1.411, 1.438, 1.462, 1.474, - 1.471, 1.443, 1.417, 1.388, 1.361, 1.339, 1.321, 1.313, 1.313, 1.327, 1.346, 1.362, 1.391, 1.422, 1.453, 1.473, - 1.469, 1.439, 1.408, 1.377, 1.349, 1.321, 1.312, 1.299, 1.299, 1.311, 1.327, 1.348, 1.378, 1.415, 1.446, 1.468, - 1.468, 1.434, 1.402, 1.371, 1.341, 1.316, 1.299, 1.296, 1.295, 1.299, 1.314, 1.338, 1.371, 1.408, 1.441, 1.466, - 1.468, 1.434, 1.401, 1.371, 1.341, 1.316, 1.301, 1.296, 1.295, 1.297, 1.314, 1.338, 1.369, 1.408, 1.441, 1.465, - 1.469, 1.436, 1.401, 1.374, 1.348, 1.332, 1.315, 1.301, 1.301, 1.313, 1.324, 1.342, 1.372, 1.409, 1.442, 1.465, - 1.471, 1.444, 1.413, 1.388, 1.371, 1.348, 1.332, 1.323, 1.323, 1.324, 1.342, 1.362, 1.386, 1.418, 1.449, 1.467, - 1.473, 1.454, 1.431, 1.407, 1.388, 1.371, 1.359, 1.352, 1.351, 1.351, 1.362, 1.383, 1.404, 1.433, 1.462, 1.472, - 1.474, 1.461, 1.447, 1.424, 1.407, 1.394, 1.385, 1.381, 1.379, 1.381, 1.383, 1.401, 1.419, 1.444, 1.466, 1.481, - 1.474, 1.464, 1.455, 1.442, 1.421, 1.408, 1.403, 1.403, 1.403, 1.399, 1.402, 1.415, 1.432, 1.446, 1.467, 1.483 - ] - }, - { - "ct": 6500, "table": - [ - 1.567, 1.565, 1.555, 1.541, 1.525, 1.518, 1.518, 1.518, 1.521, 1.527, 1.532, 1.541, 1.551, 1.559, 1.567, 1.569, - 1.565, 1.557, 1.542, 1.527, 1.519, 1.515, 1.511, 1.516, 1.519, 1.524, 1.528, 1.533, 1.542, 1.553, 1.559, 1.562, - 1.561, 1.546, 1.532, 1.521, 1.518, 1.515, 1.511, 1.516, 1.519, 1.524, 1.528, 1.529, 1.533, 1.542, 1.554, 1.559, - 1.561, 1.539, 1.526, 1.524, 1.521, 1.521, 1.522, 1.524, 1.525, 1.531, 1.529, 1.529, 1.531, 1.538, 1.549, 1.558, - 1.559, 1.538, 1.526, 1.525, 1.524, 1.528, 1.534, 1.536, 1.536, 1.536, 1.532, 1.529, 1.531, 1.537, 1.548, 1.556, - 1.561, 1.537, 1.525, 1.524, 1.526, 1.532, 1.537, 1.539, 1.538, 1.537, 1.532, 1.529, 1.529, 1.537, 1.546, 1.556, - 1.561, 1.536, 1.524, 1.522, 1.525, 1.532, 1.538, 1.538, 1.537, 1.533, 1.528, 1.526, 1.527, 1.536, 1.546, 1.555, - 1.561, 1.537, 1.522, 1.521, 1.524, 1.531, 1.536, 1.537, 1.534, 1.529, 1.526, 1.522, 1.523, 1.534, 1.547, 1.555, - 1.561, 1.538, 1.524, 1.522, 1.526, 1.531, 1.535, 1.535, 1.534, 1.527, 1.524, 1.522, 1.522, 1.535, 1.549, 1.556, - 1.558, 1.543, 1.532, 1.526, 1.526, 1.529, 1.534, 1.535, 1.533, 1.526, 1.523, 1.522, 1.524, 1.537, 1.552, 1.557, - 1.555, 1.546, 1.541, 1.528, 1.527, 1.528, 1.531, 1.533, 1.531, 1.527, 1.522, 1.522, 1.526, 1.536, 1.552, 1.561, - 1.555, 1.547, 1.542, 1.538, 1.526, 1.526, 1.529, 1.531, 1.529, 1.528, 1.519, 1.519, 1.527, 1.531, 1.543, 1.561 - ] - } - ], - "calibrations_Cb": - [ - { - "ct": 3000, "table": - [ - 1.684, 1.688, 1.691, 1.697, 1.709, 1.722, 1.735, 1.745, 1.747, 1.745, 1.731, 1.719, 1.709, 1.705, 1.699, 1.699, - 1.684, 1.689, 1.694, 1.708, 1.721, 1.735, 1.747, 1.762, 1.762, 1.758, 1.745, 1.727, 1.716, 1.707, 1.701, 1.699, - 1.684, 1.691, 1.704, 1.719, 1.734, 1.755, 1.772, 1.786, 1.789, 1.788, 1.762, 1.745, 1.724, 1.709, 1.702, 1.698, - 1.682, 1.694, 1.709, 1.729, 1.755, 1.773, 1.798, 1.815, 1.817, 1.808, 1.788, 1.762, 1.733, 1.714, 1.704, 1.699, - 1.682, 1.693, 1.713, 1.742, 1.772, 1.798, 1.815, 1.829, 1.831, 1.821, 1.807, 1.773, 1.742, 1.716, 1.703, 1.699, - 1.681, 1.693, 1.713, 1.742, 1.772, 1.799, 1.828, 1.839, 1.839, 1.828, 1.807, 1.774, 1.742, 1.715, 1.699, 1.695, - 1.679, 1.691, 1.712, 1.739, 1.771, 1.798, 1.825, 1.829, 1.831, 1.818, 1.801, 1.774, 1.738, 1.712, 1.695, 1.691, - 1.676, 1.685, 1.703, 1.727, 1.761, 1.784, 1.801, 1.817, 1.817, 1.801, 1.779, 1.761, 1.729, 1.706, 1.691, 1.684, - 1.669, 1.678, 1.692, 1.714, 1.741, 1.764, 1.784, 1.795, 1.795, 1.779, 1.761, 1.738, 1.713, 1.696, 1.683, 1.679, - 1.664, 1.671, 1.679, 1.693, 1.716, 1.741, 1.762, 1.769, 1.769, 1.753, 1.738, 1.713, 1.701, 1.687, 1.681, 1.676, - 1.661, 1.664, 1.671, 1.679, 1.693, 1.714, 1.732, 1.739, 1.739, 1.729, 1.708, 1.701, 1.685, 1.679, 1.676, 1.677, - 1.659, 1.661, 1.664, 1.671, 1.679, 1.693, 1.712, 1.714, 1.714, 1.708, 1.701, 1.687, 1.679, 1.672, 1.673, 1.677 - ] - }, - { - "ct": 5000, "table": - [ - 1.177, 1.183, 1.187, 1.191, 1.197, 1.206, 1.213, 1.215, 1.215, 1.215, 1.211, 1.204, 1.196, 1.191, 1.183, 1.182, - 1.179, 1.185, 1.191, 1.196, 1.206, 1.217, 1.224, 1.229, 1.229, 1.226, 1.221, 1.212, 1.202, 1.195, 1.188, 1.182, - 1.183, 1.191, 1.196, 1.206, 1.217, 1.229, 1.239, 1.245, 1.245, 1.245, 1.233, 1.221, 1.212, 1.199, 1.193, 1.187, - 1.183, 1.192, 1.201, 1.212, 1.229, 1.241, 1.252, 1.259, 1.259, 1.257, 1.245, 1.233, 1.217, 1.201, 1.194, 1.192, - 1.183, 1.192, 1.202, 1.219, 1.238, 1.252, 1.261, 1.269, 1.268, 1.261, 1.257, 1.241, 1.223, 1.204, 1.194, 1.191, - 1.182, 1.192, 1.202, 1.219, 1.239, 1.255, 1.266, 1.271, 1.271, 1.265, 1.258, 1.242, 1.223, 1.205, 1.192, 1.191, - 1.181, 1.189, 1.199, 1.218, 1.239, 1.254, 1.262, 1.268, 1.268, 1.258, 1.253, 1.241, 1.221, 1.204, 1.191, 1.187, - 1.179, 1.184, 1.193, 1.211, 1.232, 1.243, 1.254, 1.257, 1.256, 1.253, 1.242, 1.232, 1.216, 1.199, 1.187, 1.183, - 1.174, 1.179, 1.187, 1.202, 1.218, 1.232, 1.243, 1.246, 1.246, 1.239, 1.232, 1.218, 1.207, 1.191, 1.183, 1.179, - 1.169, 1.175, 1.181, 1.189, 1.202, 1.218, 1.229, 1.232, 1.232, 1.224, 1.218, 1.207, 1.199, 1.185, 1.181, 1.174, - 1.164, 1.168, 1.175, 1.179, 1.189, 1.201, 1.209, 1.213, 1.213, 1.209, 1.201, 1.198, 1.186, 1.181, 1.174, 1.173, - 1.161, 1.166, 1.171, 1.175, 1.179, 1.189, 1.197, 1.198, 1.198, 1.197, 1.196, 1.186, 1.182, 1.175, 1.173, 1.173 - ] - }, - { - "ct": 6500, "table": - [ - 1.166, 1.171, 1.173, 1.178, 1.187, 1.193, 1.201, 1.205, 1.205, 1.205, 1.199, 1.191, 1.184, 1.179, 1.174, 1.171, - 1.166, 1.172, 1.176, 1.184, 1.195, 1.202, 1.209, 1.216, 1.216, 1.213, 1.208, 1.201, 1.189, 1.182, 1.176, 1.171, - 1.166, 1.173, 1.183, 1.195, 1.202, 1.214, 1.221, 1.228, 1.229, 1.228, 1.221, 1.209, 1.201, 1.186, 1.179, 1.174, - 1.165, 1.174, 1.187, 1.201, 1.214, 1.223, 1.235, 1.241, 1.242, 1.241, 1.229, 1.221, 1.205, 1.188, 1.181, 1.177, - 1.165, 1.174, 1.189, 1.207, 1.223, 1.235, 1.242, 1.253, 1.252, 1.245, 1.241, 1.228, 1.211, 1.189, 1.181, 1.178, - 1.164, 1.173, 1.189, 1.207, 1.224, 1.238, 1.249, 1.255, 1.255, 1.249, 1.242, 1.228, 1.211, 1.191, 1.179, 1.176, - 1.163, 1.172, 1.187, 1.207, 1.223, 1.237, 1.245, 1.253, 1.252, 1.243, 1.237, 1.228, 1.207, 1.188, 1.176, 1.173, - 1.159, 1.167, 1.179, 1.199, 1.217, 1.227, 1.237, 1.241, 1.241, 1.237, 1.228, 1.217, 1.201, 1.184, 1.174, 1.169, - 1.156, 1.164, 1.172, 1.189, 1.205, 1.217, 1.226, 1.229, 1.229, 1.222, 1.217, 1.204, 1.192, 1.177, 1.171, 1.166, - 1.154, 1.159, 1.166, 1.177, 1.189, 1.205, 1.213, 1.216, 1.216, 1.209, 1.204, 1.192, 1.183, 1.172, 1.168, 1.162, - 1.152, 1.155, 1.161, 1.166, 1.177, 1.188, 1.195, 1.198, 1.199, 1.196, 1.187, 1.183, 1.173, 1.168, 1.163, 1.162, - 1.151, 1.154, 1.158, 1.162, 1.168, 1.177, 1.183, 1.184, 1.184, 1.184, 1.182, 1.172, 1.168, 1.165, 1.162, 1.161 - ] - } - ], - "luminance_lut": - [ - 2.236, 2.111, 1.912, 1.741, 1.579, 1.451, 1.379, 1.349, 1.349, 1.361, 1.411, 1.505, 1.644, 1.816, 2.034, 2.159, - 2.139, 1.994, 1.796, 1.625, 1.467, 1.361, 1.285, 1.248, 1.239, 1.265, 1.321, 1.408, 1.536, 1.703, 1.903, 2.087, - 2.047, 1.898, 1.694, 1.511, 1.373, 1.254, 1.186, 1.152, 1.142, 1.166, 1.226, 1.309, 1.441, 1.598, 1.799, 1.978, - 1.999, 1.824, 1.615, 1.429, 1.281, 1.179, 1.113, 1.077, 1.071, 1.096, 1.153, 1.239, 1.357, 1.525, 1.726, 1.915, - 1.976, 1.773, 1.563, 1.374, 1.222, 1.119, 1.064, 1.032, 1.031, 1.049, 1.099, 1.188, 1.309, 1.478, 1.681, 1.893, - 1.973, 1.756, 1.542, 1.351, 1.196, 1.088, 1.028, 1.011, 1.004, 1.029, 1.077, 1.169, 1.295, 1.459, 1.663, 1.891, - 1.973, 1.761, 1.541, 1.349, 1.193, 1.087, 1.031, 1.006, 1.006, 1.023, 1.075, 1.169, 1.298, 1.463, 1.667, 1.891, - 1.982, 1.789, 1.568, 1.373, 1.213, 1.111, 1.051, 1.029, 1.024, 1.053, 1.106, 1.199, 1.329, 1.495, 1.692, 1.903, - 2.015, 1.838, 1.621, 1.426, 1.268, 1.159, 1.101, 1.066, 1.068, 1.099, 1.166, 1.259, 1.387, 1.553, 1.751, 1.937, - 2.076, 1.911, 1.692, 1.507, 1.346, 1.236, 1.169, 1.136, 1.139, 1.174, 1.242, 1.349, 1.475, 1.641, 1.833, 2.004, - 2.193, 2.011, 1.798, 1.604, 1.444, 1.339, 1.265, 1.235, 1.237, 1.273, 1.351, 1.461, 1.598, 1.758, 1.956, 2.125, - 2.263, 2.154, 1.916, 1.711, 1.549, 1.432, 1.372, 1.356, 1.356, 1.383, 1.455, 1.578, 1.726, 1.914, 2.119, 2.211 - ], - "sigma": 0.006, - "sigma_Cb": 0.00208 - }, - "rpi.contrast": - { - "ce_enable": 1, - "gamma_curve": - [ - 0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120, 18051, 6144, 20790, 7168, 23193, - 8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168, - 16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753, 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796, - 32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954, 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476, - 65535, 65535 - ] - }, - "rpi.ccm": - { - "ccms": - [ - { - "ct": 2500, "ccm": - [ - 1.70741, -0.05307, -0.65433, -0.62822, 1.68836, -0.06014, -0.04452, -1.87628, 2.92079 - ] - }, - { - "ct": 2803, "ccm": - [ - 1.74383, -0.18731, -0.55652, -0.56491, 1.67772, -0.11281, -0.01522, -1.60635, 2.62157 - ] - }, - { - "ct": 2912, "ccm": - [ - 1.75215, -0.22221, -0.52995, -0.54568, 1.63522, -0.08954, 0.02633, -1.56997, 2.54364 - ] - }, - { - "ct": 2914, "ccm": - [ - 1.72423, -0.28939, -0.43484, -0.55188, 1.62925, -0.07737, 0.01959, -1.28661, 2.26702 - ] - }, - { - "ct": 3605, "ccm": - [ - 1.80381, -0.43646, -0.36735, -0.46505, 1.56814, -0.10309, 0.00929, -1.00424, 1.99495 - ] - }, - { - "ct": 4540, "ccm": - [ - 1.85263, -0.46545, -0.38719, -0.44136, 1.68443, -0.24307, 0.04108, -0.85599, 1.81491 - ] - }, - { - "ct": 5699, "ccm": - [ - 1.98595, -0.63542, -0.35054, -0.34623, 1.54146, -0.19522, 0.00411, -0.70936, 1.70525 - ] - }, - { - "ct": 8625, "ccm": - [ - 2.21637, -0.56663, -0.64974, -0.41133, 1.96625, -0.55492, -0.02307, -0.83529, 1.85837 - ] - } - ] - }, - "rpi.sharpen": - { - - } -} diff --git a/src/ipa/raspberrypi/data/ov9281.json b/src/ipa/raspberrypi/data/ov9281.json deleted file mode 100644 index 2319448b..00000000 --- a/src/ipa/raspberrypi/data/ov9281.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "rpi.black_level": - { - "black_level": 4096 - }, - "rpi.lux": - { - "reference_shutter_speed": 2000, - "reference_gain": 1.0, - "reference_aperture": 1.0, - "reference_lux": 800, - "reference_Y": 20000 - }, - "rpi.noise": - { - "reference_constant": 0, - "reference_slope": 2.5 - }, - "rpi.sdn": - { - }, - "rpi.agc": - { - "metering_modes": - { - "centre-weighted": { - "weights": [4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0] - } - }, - "exposure_modes": - { - "normal": - { - "shutter": [ 100, 15000, 30000, 60000, 120000 ], - "gain": [ 1.0, 2.0, 3.0, 4.0, 8.0 ] - } - }, - "constraint_modes": - { - "normal": - [ - { "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": [ 0, 0.4, 1000, 0.4 ] } - ] - }, - "y_target": [ 0, 0.16, 1000, 0.165, 10000, 0.17 ] - }, - "rpi.alsc": - { - "n_iter": 0, - "luminance_strength": 1.0, - "corner_strength": 1.5 - }, - "rpi.contrast": - { - "ce_enable": 0, - "gamma_curve": [ - 0, 0, - 1024, 5040, - 2048, 9338, - 3072, 12356, - 4096, 15312, - 5120, 18051, - 6144, 20790, - 7168, 23193, - 8192, 25744, - 9216, 27942, - 10240, 30035, - 11264, 32005, - 12288, 33975, - 13312, 35815, - 14336, 37600, - 15360, 39168, - 16384, 40642, - 18432, 43379, - 20480, 45749, - 22528, 47753, - 24576, 49621, - 26624, 51253, - 28672, 52698, - 30720, 53796, - 32768, 54876, - 36864, 57012, - 40960, 58656, - 45056, 59954, - 49152, 61183, - 53248, 62355, - 57344, 63419, - 61440, 64476, - 65535, 65535 - ] - } -} diff --git a/src/ipa/raspberrypi/data/se327m12.json b/src/ipa/raspberrypi/data/se327m12.json deleted file mode 100644 index 94af2239..00000000 --- a/src/ipa/raspberrypi/data/se327m12.json +++ /dev/null @@ -1,341 +0,0 @@ -{ - "rpi.black_level": - { - "black_level": 3840 - }, - "rpi.dpc": - { - }, - "rpi.lux": - { - "reference_shutter_speed": 6873, - "reference_gain": 1.0, - "reference_aperture": 1.0, - "reference_lux": 800, - "reference_Y": 12293 - }, - "rpi.noise": - { - "reference_constant": 0, - "reference_slope": 1.986 - }, - "rpi.geq": - { - "offset": 207, - "slope": 0.00539 - }, - "rpi.sdn": - { - }, - "rpi.awb": - { - "priors": - [ - { - "lux": 0, "prior": - [ - 2000, 1.0, 3000, 0.0, 13000, 0.0 - ] - }, - { - "lux": 800, "prior": - [ - 2000, 0.0, 6000, 2.0, 13000, 2.0 - ] - }, - { - "lux": 1500, "prior": - [ - 2000, 0.0, 4000, 1.0, 6000, 6.0, 6500, 7.0, 7000, 1.0, 13000, 1.0 - ] - } - ], - "modes": - { - "auto": - { - "lo": 2500, - "hi": 8000 - }, - "incandescent": - { - "lo": 2500, - "hi": 3000 - }, - "tungsten": - { - "lo": 3000, - "hi": 3500 - }, - "fluorescent": - { - "lo": 4000, - "hi": 4700 - }, - "indoor": - { - "lo": 3000, - "hi": 5000 - }, - "daylight": - { - "lo": 5500, - "hi": 6500 - }, - "cloudy": - { - "lo": 7000, - "hi": 8600 - } - }, - "bayes": 1, - "ct_curve": - [ - 2900.0, 0.9217, 0.3657, 3600.0, 0.7876, 0.4651, 4600.0, 0.6807, 0.5684, 5800.0, 0.5937, 0.6724, 8100.0, 0.5447, 0.7403 - ], - "sensitivity_r": 1.0, - "sensitivity_b": 1.0, - "transverse_pos": 0.0162, - "transverse_neg": 0.0204 - }, - "rpi.agc": - { - "metering_modes": - { - "centre-weighted": - { - "weights": - [ - 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 - ] - }, - "spot": - { - "weights": - [ - 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - }, - "matrix": - { - "weights": - [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - ] - } - }, - "exposure_modes": - { - "normal": - { - "shutter": - [ - 100, 10000, 30000, 60000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - }, - "short": - { - "shutter": - [ - 100, 5000, 10000, 20000, 120000 - ], - "gain": - [ - 1.0, 2.0, 4.0, 6.0, 8.0 - ] - } - }, - "constraint_modes": - { - "normal": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - } - ], - "highlight": - [ - { - "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.5, 1000, 0.5 - ] - }, - { - "bound": "UPPER", "q_lo": 0.98, "q_hi": 1.0, "y_target": - [ - 0, 0.8, 1000, 0.8 - ] - } - ] - }, - "y_target": - [ - 0, 0.16, 1000, 0.165, 10000, 0.17 - ] - }, - "rpi.alsc": - { - "omega": 1.3, - "n_iter": 100, - "luminance_strength": 0.5, - "calibrations_Cr": - [ - { - "ct": 4000, "table": - [ - 1.481, 1.471, 1.449, 1.429, 1.416, 1.404, 1.394, 1.389, 1.389, 1.389, 1.392, 1.397, 1.404, 1.416, 1.429, 1.437, - 1.472, 1.456, 1.436, 1.418, 1.405, 1.394, 1.389, 1.384, 1.382, 1.382, 1.386, 1.388, 1.398, 1.407, 1.422, 1.429, - 1.465, 1.443, 1.426, 1.411, 1.397, 1.389, 1.383, 1.377, 1.377, 1.377, 1.379, 1.384, 1.388, 1.398, 1.411, 1.422, - 1.462, 1.441, 1.423, 1.409, 1.395, 1.385, 1.379, 1.376, 1.374, 1.374, 1.375, 1.379, 1.384, 1.394, 1.407, 1.418, - 1.461, 1.439, 1.421, 1.407, 1.394, 1.385, 1.381, 1.376, 1.373, 1.373, 1.373, 1.376, 1.381, 1.389, 1.403, 1.415, - 1.461, 1.439, 1.419, 1.404, 1.392, 1.384, 1.379, 1.376, 1.373, 1.372, 1.374, 1.375, 1.379, 1.389, 1.401, 1.413, - 1.461, 1.438, 1.419, 1.402, 1.389, 1.383, 1.377, 1.375, 1.373, 1.372, 1.372, 1.375, 1.381, 1.388, 1.401, 1.414, - 1.462, 1.438, 1.419, 1.403, 1.391, 1.381, 1.377, 1.374, 1.373, 1.373, 1.374, 1.376, 1.381, 1.389, 1.401, 1.414, - 1.462, 1.441, 1.423, 1.405, 1.392, 1.383, 1.377, 1.374, 1.373, 1.372, 1.373, 1.376, 1.382, 1.391, 1.402, 1.414, - 1.465, 1.444, 1.424, 1.407, 1.393, 1.382, 1.378, 1.373, 1.369, 1.369, 1.372, 1.375, 1.381, 1.389, 1.402, 1.417, - 1.469, 1.449, 1.427, 1.413, 1.396, 1.384, 1.381, 1.375, 1.371, 1.371, 1.373, 1.377, 1.385, 1.393, 1.407, 1.422, - 1.474, 1.456, 1.436, 1.419, 1.407, 1.391, 1.383, 1.379, 1.377, 1.377, 1.378, 1.381, 1.391, 1.404, 1.422, 1.426 - ] - }, - { - "ct": 5000, "table": - [ - 1.742, 1.721, 1.689, 1.661, 1.639, 1.623, 1.613, 1.609, 1.607, 1.606, 1.609, 1.617, 1.626, 1.641, 1.665, 1.681, - 1.728, 1.703, 1.672, 1.645, 1.631, 1.614, 1.602, 1.599, 1.596, 1.597, 1.601, 1.608, 1.618, 1.631, 1.653, 1.671, - 1.713, 1.691, 1.658, 1.635, 1.618, 1.606, 1.595, 1.591, 1.588, 1.588, 1.591, 1.601, 1.608, 1.624, 1.641, 1.658, - 1.707, 1.681, 1.651, 1.627, 1.613, 1.599, 1.591, 1.585, 1.583, 1.584, 1.587, 1.591, 1.601, 1.615, 1.633, 1.655, - 1.699, 1.672, 1.644, 1.622, 1.606, 1.593, 1.586, 1.581, 1.579, 1.581, 1.583, 1.587, 1.597, 1.611, 1.631, 1.652, - 1.697, 1.665, 1.637, 1.617, 1.601, 1.589, 1.584, 1.579, 1.577, 1.578, 1.581, 1.585, 1.597, 1.607, 1.627, 1.652, - 1.697, 1.662, 1.634, 1.613, 1.599, 1.591, 1.583, 1.578, 1.576, 1.576, 1.579, 1.586, 1.597, 1.607, 1.628, 1.653, - 1.697, 1.662, 1.633, 1.613, 1.598, 1.589, 1.582, 1.578, 1.576, 1.577, 1.582, 1.589, 1.598, 1.611, 1.635, 1.655, - 1.701, 1.666, 1.636, 1.616, 1.602, 1.589, 1.583, 1.578, 1.577, 1.581, 1.583, 1.591, 1.601, 1.617, 1.639, 1.659, - 1.708, 1.671, 1.641, 1.618, 1.603, 1.591, 1.584, 1.581, 1.578, 1.581, 1.585, 1.594, 1.604, 1.622, 1.646, 1.666, - 1.714, 1.681, 1.648, 1.622, 1.608, 1.599, 1.591, 1.584, 1.583, 1.584, 1.589, 1.599, 1.614, 1.629, 1.653, 1.673, - 1.719, 1.691, 1.659, 1.631, 1.618, 1.606, 1.596, 1.591, 1.591, 1.593, 1.599, 1.608, 1.623, 1.642, 1.665, 1.681 - ] - } - ], - "calibrations_Cb": - [ - { - "ct": 4000, "table": - [ - 2.253, 2.267, 2.289, 2.317, 2.342, 2.359, 2.373, 2.381, 2.381, 2.378, 2.368, 2.361, 2.344, 2.337, 2.314, 2.301, - 2.262, 2.284, 2.314, 2.335, 2.352, 2.371, 2.383, 2.391, 2.393, 2.391, 2.381, 2.368, 2.361, 2.342, 2.322, 2.308, - 2.277, 2.303, 2.321, 2.346, 2.364, 2.381, 2.391, 2.395, 2.397, 2.397, 2.395, 2.381, 2.367, 2.354, 2.332, 2.321, - 2.277, 2.304, 2.327, 2.349, 2.369, 2.388, 2.393, 2.396, 2.396, 2.398, 2.396, 2.391, 2.376, 2.359, 2.339, 2.328, - 2.279, 2.311, 2.327, 2.354, 2.377, 2.389, 2.393, 2.397, 2.397, 2.398, 2.395, 2.393, 2.382, 2.363, 2.344, 2.332, - 2.282, 2.311, 2.329, 2.354, 2.377, 2.386, 2.396, 2.396, 2.395, 2.396, 2.397, 2.394, 2.383, 2.367, 2.346, 2.333, - 2.283, 2.314, 2.333, 2.353, 2.375, 2.389, 2.394, 2.395, 2.395, 2.395, 2.396, 2.394, 2.386, 2.368, 2.354, 2.336, - 2.287, 2.309, 2.331, 2.352, 2.373, 2.386, 2.394, 2.395, 2.395, 2.396, 2.396, 2.394, 2.384, 2.371, 2.354, 2.339, - 2.289, 2.307, 2.326, 2.347, 2.369, 2.385, 2.392, 2.397, 2.398, 2.398, 2.397, 2.392, 2.383, 2.367, 2.352, 2.337, - 2.286, 2.303, 2.322, 2.342, 2.361, 2.379, 2.389, 2.394, 2.397, 2.398, 2.396, 2.389, 2.381, 2.366, 2.346, 2.332, - 2.284, 2.291, 2.312, 2.329, 2.351, 2.372, 2.381, 2.389, 2.393, 2.394, 2.389, 2.385, 2.374, 2.362, 2.338, 2.325, - 2.283, 2.288, 2.305, 2.319, 2.339, 2.365, 2.374, 2.381, 2.384, 2.386, 2.385, 2.379, 2.368, 2.342, 2.325, 2.318 - ] - }, - { - "ct": 5000, "table": - [ - 1.897, 1.919, 1.941, 1.969, 1.989, 2.003, 2.014, 2.019, 2.019, 2.017, 2.014, 2.008, 1.999, 1.988, 1.968, 1.944, - 1.914, 1.932, 1.957, 1.982, 1.998, 2.014, 2.023, 2.029, 2.031, 2.029, 2.022, 2.014, 2.006, 1.995, 1.976, 1.955, - 1.925, 1.951, 1.974, 1.996, 2.013, 2.027, 2.035, 2.039, 2.039, 2.038, 2.035, 2.026, 2.015, 2.002, 1.984, 1.963, - 1.932, 1.958, 1.986, 2.007, 2.024, 2.034, 2.041, 2.041, 2.045, 2.045, 2.042, 2.033, 2.023, 2.009, 1.995, 1.971, - 1.942, 1.964, 1.994, 2.012, 2.029, 2.038, 2.043, 2.046, 2.047, 2.046, 2.045, 2.039, 2.029, 2.014, 1.997, 1.977, - 1.946, 1.974, 1.999, 2.015, 2.031, 2.041, 2.046, 2.047, 2.048, 2.047, 2.044, 2.041, 2.031, 2.019, 1.999, 1.978, - 1.948, 1.975, 2.002, 2.018, 2.031, 2.041, 2.046, 2.047, 2.048, 2.048, 2.045, 2.041, 2.029, 2.019, 1.998, 1.978, - 1.948, 1.973, 2.002, 2.018, 2.029, 2.042, 2.045, 2.048, 2.048, 2.048, 2.044, 2.037, 2.027, 2.014, 1.993, 1.978, - 1.945, 1.969, 1.998, 2.015, 2.028, 2.037, 2.045, 2.046, 2.047, 2.044, 2.039, 2.033, 2.022, 2.008, 1.989, 1.971, - 1.939, 1.964, 1.991, 2.011, 2.024, 2.032, 2.036, 2.042, 2.042, 2.039, 2.035, 2.024, 2.012, 1.998, 1.977, 1.964, - 1.932, 1.953, 1.981, 2.006, 2.016, 2.024, 2.028, 2.031, 2.034, 2.031, 2.024, 2.015, 2.005, 1.989, 1.966, 1.955, - 1.928, 1.944, 1.973, 1.999, 2.007, 2.016, 2.019, 2.025, 2.026, 2.025, 2.017, 2.008, 1.997, 1.975, 1.958, 1.947 - ] - } - ], - "luminance_lut": - [ - 1.877, 1.597, 1.397, 1.269, 1.191, 1.131, 1.093, 1.078, 1.071, 1.069, 1.086, 1.135, 1.221, 1.331, 1.474, 1.704, - 1.749, 1.506, 1.334, 1.229, 1.149, 1.088, 1.058, 1.053, 1.051, 1.046, 1.053, 1.091, 1.163, 1.259, 1.387, 1.587, - 1.661, 1.451, 1.295, 1.195, 1.113, 1.061, 1.049, 1.048, 1.047, 1.049, 1.049, 1.066, 1.124, 1.211, 1.333, 1.511, - 1.615, 1.411, 1.267, 1.165, 1.086, 1.052, 1.047, 1.047, 1.047, 1.049, 1.052, 1.056, 1.099, 1.181, 1.303, 1.471, - 1.576, 1.385, 1.252, 1.144, 1.068, 1.049, 1.044, 1.044, 1.045, 1.049, 1.053, 1.054, 1.083, 1.163, 1.283, 1.447, - 1.561, 1.373, 1.245, 1.135, 1.064, 1.049, 1.044, 1.044, 1.044, 1.046, 1.048, 1.054, 1.073, 1.153, 1.271, 1.432, - 1.571, 1.377, 1.242, 1.137, 1.066, 1.055, 1.052, 1.051, 1.051, 1.049, 1.047, 1.048, 1.068, 1.148, 1.271, 1.427, - 1.582, 1.396, 1.259, 1.156, 1.085, 1.068, 1.059, 1.054, 1.049, 1.045, 1.041, 1.043, 1.074, 1.157, 1.284, 1.444, - 1.623, 1.428, 1.283, 1.178, 1.105, 1.074, 1.069, 1.063, 1.056, 1.048, 1.046, 1.051, 1.094, 1.182, 1.311, 1.473, - 1.691, 1.471, 1.321, 1.213, 1.135, 1.088, 1.073, 1.069, 1.063, 1.059, 1.053, 1.071, 1.129, 1.222, 1.351, 1.521, - 1.808, 1.543, 1.371, 1.253, 1.174, 1.118, 1.085, 1.072, 1.067, 1.064, 1.071, 1.106, 1.176, 1.274, 1.398, 1.582, - 1.969, 1.666, 1.447, 1.316, 1.223, 1.166, 1.123, 1.094, 1.089, 1.097, 1.118, 1.163, 1.239, 1.336, 1.471, 1.681 - ], - "sigma": 0.00218, - "sigma_Cb": 0.00194 - }, - "rpi.contrast": - { - "ce_enable": 1, - "gamma_curve": - [ - 0, 0, 1024, 5040, 2048, 9338, 3072, 12356, 4096, 15312, 5120, 18051, 6144, 20790, 7168, 23193, - 8192, 25744, 9216, 27942, 10240, 30035, 11264, 32005, 12288, 33975, 13312, 35815, 14336, 37600, 15360, 39168, - 16384, 40642, 18432, 43379, 20480, 45749, 22528, 47753, 24576, 49621, 26624, 51253, 28672, 52698, 30720, 53796, - 32768, 54876, 36864, 57012, 40960, 58656, 45056, 59954, 49152, 61183, 53248, 62355, 57344, 63419, 61440, 64476, - 65535, 65535 - ] - }, - "rpi.ccm": - { - "ccms": - [ - { - "ct": 2900, "ccm": - [ - 1.44924, -0.12935, -0.31989, -0.65839, 1.95441, -0.29602, 0.18344, -1.22282, 2.03938 - ] - }, - { - "ct": 3000, "ccm": - [ - 1.38736, 0.07714, -0.46451, -0.59691, 1.84335, -0.24644, 0.10092, -1.30441, 2.20349 - ] - }, - { - "ct": 3600, "ccm": - [ - 1.51261, -0.27921, -0.23339, -0.55129, 1.83241, -0.28111, 0.11649, -0.93195, 1.81546 - ] - }, - { - "ct": 4600, "ccm": - [ - 1.47082, -0.18523, -0.28559, -0.48923, 1.95126, -0.46203, 0.07951, -0.83987, 1.76036 - ] - }, - { - "ct": 5800, "ccm": - [ - 1.57294, -0.36229, -0.21065, -0.42272, 1.80305, -0.38032, 0.03671, -0.66862, 1.63191 - ] - }, - { - "ct": 8100, "ccm": - [ - 1.58803, -0.09912, -0.48891, -0.42594, 2.22303, -0.79709, -0.00621, -0.90516, 1.91137 - ] - } - ] - }, - "rpi.sharpen": - { - "threshold": 2.0, - "strength": 0.5, - "limit": 0.5 - } -} diff --git a/src/ipa/raspberrypi/data/uncalibrated.json b/src/ipa/raspberrypi/data/uncalibrated.json deleted file mode 100644 index 16a01e94..00000000 --- a/src/ipa/raspberrypi/data/uncalibrated.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "rpi.black_level": - { - "black_level": 4096 - }, - "rpi.awb": - { - "use_derivatives": 0, - "bayes": 0 - }, - "rpi.agc": - { - "metering_modes": - { - "centre-weighted": { - "weights": [4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0] - } - }, - "exposure_modes": - { - "normal": - { - "shutter": [ 100, 15000, 30000, 60000, 120000 ], - "gain": [ 1.0, 2.0, 3.0, 4.0, 6.0 ] - } - }, - "constraint_modes": - { - "normal": - [ - { "bound": "LOWER", "q_lo": 0.98, "q_hi": 1.0, "y_target": [ 0, 0.4, 1000, 0.4 ] } - ] - }, - "y_target": [ 0, 0.16, 1000, 0.165, 10000, 0.17 ] - }, - "rpi.ccm": - { - "ccms": - [ - { "ct": 4000, "ccm": [ 2.0, -1.0, 0.0, -0.5, 2.0, -0.5, 0, -1.0, 2.0 ] } - ] - }, - "rpi.contrast": - { - "ce_enable": 0, - "gamma_curve": [ - 0, 0, - 1024, 5040, - 2048, 9338, - 3072, 12356, - 4096, 15312, - 5120, 18051, - 6144, 20790, - 7168, 23193, - 8192, 25744, - 9216, 27942, - 10240, 30035, - 11264, 32005, - 12288, 33975, - 13312, 35815, - 14336, 37600, - 15360, 39168, - 16384, 40642, - 18432, 43379, - 20480, 45749, - 22528, 47753, - 24576, 49621, - 26624, 51253, - 28672, 52698, - 30720, 53796, - 32768, 54876, - 36864, 57012, - 40960, 58656, - 45056, 59954, - 49152, 61183, - 53248, 62355, - 57344, 63419, - 61440, 64476, - 65535, 65535 - ] - } -} diff --git a/src/ipa/raspberrypi/md_parser.hpp b/src/ipa/raspberrypi/md_parser.hpp deleted file mode 100644 index d32d0f54..00000000 --- a/src/ipa/raspberrypi/md_parser.hpp +++ /dev/null @@ -1,155 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019, Raspberry Pi (Trading) Limited - * - * md_parser.hpp - image sensor metadata parser interface - */ -#pragma once - -#include <initializer_list> -#include <map> -#include <optional> -#include <stdint.h> - -#include <libcamera/base/span.h> - -/* - * Camera metadata parser class. Usage as shown below. - * - * Setup: - * - * Usually the metadata parser will be made as part of the CamHelper class so - * application code doesn't have to worry which kind to instantiate. But for - * the sake of example let's suppose we're parsing imx219 metadata. - * - * MdParser *parser = new MdParserSmia({ expHiReg, expLoReg, gainReg }); - * parser->SetBitsPerPixel(bpp); - * parser->SetLineLengthBytes(pitch); - * parser->SetNumLines(2); - * - * Note 1: if you don't know how many lines there are, the size of the input - * buffer is used as a limit instead. - * - * Note 2: if you don't know the line length, you can leave the line length unset - * (or set to zero) and the parser will hunt for the line start instead. - * - * Then on every frame: - * - * RegisterMap registers; - * if (parser->Parse(buffer, registers) != MdParser::OK) - * much badness; - * Metadata metadata; - * CamHelper::PopulateMetadata(registers, metadata); - * - * (Note that the CamHelper class converts to/from exposure lines and time, - * and gain_code / actual gain.) - * - * If you suspect your embedded data may have changed its layout, change any line - * lengths, number of lines, bits per pixel etc. that are different, and - * then: - * - * parser->Reset(); - * - * before calling Parse again. - */ - -namespace RPiController { - -/* Abstract base class from which other metadata parsers are derived. */ - -class MdParser -{ -public: - using RegisterMap = std::map<uint32_t, uint32_t>; - - /* - * Parser status codes: - * OK - success - * NOTFOUND - value such as exposure or gain was not found - * ERROR - all other errors - */ - enum Status { - OK = 0, - NOTFOUND = 1, - ERROR = 2 - }; - - MdParser() - : reset_(true), bits_per_pixel_(0), num_lines_(0), line_length_bytes_(0) - { - } - - virtual ~MdParser() = default; - - void Reset() - { - reset_ = true; - } - - void SetBitsPerPixel(int bpp) - { - bits_per_pixel_ = bpp; - } - - void SetNumLines(unsigned int num_lines) - { - num_lines_ = num_lines; - } - - void SetLineLengthBytes(unsigned int num_bytes) - { - line_length_bytes_ = num_bytes; - } - - virtual Status Parse(libcamera::Span<const uint8_t> buffer, - RegisterMap ®isters) = 0; - -protected: - bool reset_; - int bits_per_pixel_; - unsigned int num_lines_; - unsigned int line_length_bytes_; -}; - -/* - * This isn't a full implementation of a metadata parser for SMIA sensors, - * however, it does provide the findRegs function which will prove useful and - * make it easier to implement parsers for other SMIA-like sensors (see - * md_parser_imx219.cpp for an example). - */ - -class MdParserSmia final : public MdParser -{ -public: - MdParserSmia(std::initializer_list<uint32_t> registerList); - - MdParser::Status Parse(libcamera::Span<const uint8_t> buffer, - RegisterMap ®isters) override; - -private: - /* Maps register address to offset in the buffer. */ - using OffsetMap = std::map<uint32_t, std::optional<uint32_t>>; - - /* - * Note that error codes > 0 are regarded as non-fatal; codes < 0 - * indicate a bad data buffer. Status codes are: - * PARSE_OK - found all registers, much happiness - * MISSING_REGS - some registers found; should this be a hard error? - * The remaining codes are all hard errors. - */ - enum ParseStatus { - PARSE_OK = 0, - MISSING_REGS = 1, - NO_LINE_START = -1, - ILLEGAL_TAG = -2, - BAD_DUMMY = -3, - BAD_LINE_END = -4, - BAD_PADDING = -5 - }; - - ParseStatus findRegs(libcamera::Span<const uint8_t> buffer); - - OffsetMap offsets_; -}; - -} // namespace RPi diff --git a/src/ipa/raspberrypi/md_parser_smia.cpp b/src/ipa/raspberrypi/md_parser_smia.cpp deleted file mode 100644 index ea5eac41..00000000 --- a/src/ipa/raspberrypi/md_parser_smia.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019-2021, Raspberry Pi (Trading) Limited - * - * md_parser_smia.cpp - SMIA specification based embedded data parser - */ - -#include <libcamera/base/log.h> -#include "md_parser.hpp" - -using namespace RPiController; -using namespace libcamera; - -/* - * This function goes through the embedded data to find the offsets (not - * values!), in the data block, where the values of the given registers can - * subsequently be found. - * - * Embedded data tag bytes, from Sony IMX219 datasheet but general to all SMIA - * sensors, I think. - */ - -constexpr unsigned int LINE_START = 0x0a; -constexpr unsigned int LINE_END_TAG = 0x07; -constexpr unsigned int REG_HI_BITS = 0xaa; -constexpr unsigned int REG_LOW_BITS = 0xa5; -constexpr unsigned int REG_VALUE = 0x5a; -constexpr unsigned int REG_SKIP = 0x55; - -MdParserSmia::MdParserSmia(std::initializer_list<uint32_t> registerList) -{ - for (auto r : registerList) - offsets_[r] = {}; -} - -MdParser::Status MdParserSmia::Parse(libcamera::Span<const uint8_t> buffer, - RegisterMap ®isters) -{ - if (reset_) { - /* - * Search again through the metadata for all the registers - * requested. - */ - ASSERT(bits_per_pixel_); - - for (const auto &kv : offsets_) - offsets_[kv.first] = {}; - - ParseStatus ret = findRegs(buffer); - /* - * > 0 means "worked partially but parse again next time", - * < 0 means "hard error". - * - * In either case, we retry parsing on the next frame. - */ - if (ret != PARSE_OK) - return ERROR; - - reset_ = false; - } - - /* Populate the register values requested. */ - registers.clear(); - for (const auto &[reg, offset] : offsets_) { - if (!offset) { - reset_ = true; - return NOTFOUND; - } - registers[reg] = buffer[offset.value()]; - } - - return OK; -} - -MdParserSmia::ParseStatus MdParserSmia::findRegs(libcamera::Span<const uint8_t> buffer) -{ - ASSERT(offsets_.size()); - - if (buffer[0] != LINE_START) - return NO_LINE_START; - - unsigned int current_offset = 1; /* after the LINE_START */ - unsigned int current_line_start = 0, current_line = 0; - unsigned int reg_num = 0, regs_done = 0; - - while (1) { - int tag = buffer[current_offset++]; - - if ((bits_per_pixel_ == 10 && - (current_offset + 1 - current_line_start) % 5 == 0) || - (bits_per_pixel_ == 12 && - (current_offset + 1 - current_line_start) % 3 == 0)) { - if (buffer[current_offset++] != REG_SKIP) - return BAD_DUMMY; - } - - int data_byte = buffer[current_offset++]; - - if (tag == LINE_END_TAG) { - if (data_byte != LINE_END_TAG) - return BAD_LINE_END; - - if (num_lines_ && ++current_line == num_lines_) - return MISSING_REGS; - - if (line_length_bytes_) { - current_offset = current_line_start + line_length_bytes_; - - /* Require whole line to be in the buffer (if buffer size set). */ - if (buffer.size() && - current_offset + line_length_bytes_ > buffer.size()) - return MISSING_REGS; - - if (buffer[current_offset] != LINE_START) - return NO_LINE_START; - } else { - /* allow a zero line length to mean "hunt for the next line" */ - while (current_offset < buffer.size() && - buffer[current_offset] != LINE_START) - current_offset++; - - if (current_offset == buffer.size()) - return NO_LINE_START; - } - - /* inc current_offset to after LINE_START */ - current_line_start = current_offset++; - } else { - if (tag == REG_HI_BITS) - reg_num = (reg_num & 0xff) | (data_byte << 8); - else if (tag == REG_LOW_BITS) - reg_num = (reg_num & 0xff00) | data_byte; - else if (tag == REG_SKIP) - reg_num++; - else if (tag == REG_VALUE) { - auto reg = offsets_.find(reg_num); - - if (reg != offsets_.end()) { - offsets_[reg_num] = current_offset - 1; - - if (++regs_done == offsets_.size()) - return PARSE_OK; - } - reg_num++; - } else - return ILLEGAL_TAG; - } - } -} diff --git a/src/ipa/raspberrypi/meson.build b/src/ipa/raspberrypi/meson.build deleted file mode 100644 index 32897e07..00000000 --- a/src/ipa/raspberrypi/meson.build +++ /dev/null @@ -1,66 +0,0 @@ -# SPDX-License-Identifier: CC0-1.0 - -ipa_name = 'ipa_rpi' - -rpi_ipa_deps = [ - libcamera_private, - dependency('boost'), - libatomic, -] - -rpi_ipa_includes = [ - ipa_includes, - libipa_includes, - include_directories('controller') -] - -rpi_ipa_sources = files([ - 'raspberrypi.cpp', - 'md_parser_smia.cpp', - 'cam_helper.cpp', - 'cam_helper_ov5647.cpp', - 'cam_helper_imx219.cpp', - 'cam_helper_imx290.cpp', - 'cam_helper_imx296.cpp', - 'cam_helper_imx477.cpp', - 'cam_helper_imx519.cpp', - 'cam_helper_ov9281.cpp', - 'controller/controller.cpp', - 'controller/histogram.cpp', - 'controller/algorithm.cpp', - 'controller/rpi/alsc.cpp', - 'controller/rpi/awb.cpp', - 'controller/rpi/sharpen.cpp', - 'controller/rpi/black_level.cpp', - 'controller/rpi/focus.cpp', - 'controller/rpi/geq.cpp', - 'controller/rpi/noise.cpp', - 'controller/rpi/lux.cpp', - 'controller/rpi/agc.cpp', - 'controller/rpi/dpc.cpp', - 'controller/rpi/ccm.cpp', - 'controller/rpi/contrast.cpp', - 'controller/rpi/sdn.cpp', - 'controller/pwl.cpp', - 'controller/device_status.cpp', -]) - -mod = shared_module(ipa_name, - [rpi_ipa_sources, libcamera_generated_ipa_headers], - name_prefix : '', - include_directories : rpi_ipa_includes, - dependencies : rpi_ipa_deps, - link_with : libipa, - install : true, - install_dir : ipa_install_dir) - -if ipa_sign_module - custom_target(ipa_name + '.so.sign', - input : mod, - output : ipa_name + '.so.sign', - command : [ipa_sign, ipa_priv_key, '@INPUT@', '@OUTPUT@'], - install : false, - build_by_default : true) -endif - -subdir('data') diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp deleted file mode 100644 index f8d37b87..00000000 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ /dev/null @@ -1,1460 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (C) 2019-2021, Raspberry Pi (Trading) Ltd. - * - * rpi.cpp - Raspberry Pi Image Processing Algorithms - */ - -#include <algorithm> -#include <array> -#include <fcntl.h> -#include <math.h> -#include <stdint.h> -#include <string.h> -#include <sys/mman.h> - -#include <linux/bcm2835-isp.h> - -#include <libcamera/base/log.h> -#include <libcamera/base/shared_fd.h> -#include <libcamera/base/span.h> - -#include <libcamera/control_ids.h> -#include <libcamera/controls.h> -#include <libcamera/framebuffer.h> -#include <libcamera/ipa/ipa_interface.h> -#include <libcamera/ipa/ipa_module_info.h> -#include <libcamera/ipa/raspberrypi_ipa_interface.h> -#include <libcamera/request.h> - -#include "libcamera/internal/mapped_framebuffer.h" - -#include "agc_algorithm.hpp" -#include "agc_status.h" -#include "alsc_status.h" -#include "awb_algorithm.hpp" -#include "awb_status.h" -#include "black_level_status.h" -#include "cam_helper.hpp" -#include "ccm_algorithm.hpp" -#include "ccm_status.h" -#include "contrast_algorithm.hpp" -#include "contrast_status.h" -#include "controller.hpp" -#include "denoise_algorithm.hpp" -#include "denoise_status.h" -#include "dpc_status.h" -#include "focus_status.h" -#include "geq_status.h" -#include "lux_status.h" -#include "metadata.hpp" -#include "noise_status.h" -#include "sharpen_algorithm.hpp" -#include "sharpen_status.h" - -namespace libcamera { - -using namespace std::literals::chrono_literals; -using utils::Duration; - -/* Configure the sensor with these values initially. */ -constexpr double defaultAnalogueGain = 1.0; -constexpr Duration defaultExposureTime = 20.0ms; -constexpr Duration defaultMinFrameDuration = 1.0s / 30.0; -constexpr Duration defaultMaxFrameDuration = 250.0s; - -/* - * Determine the minimum allowable inter-frame duration to run the controller - * algorithms. If the pipeline handler provider frames at a rate higher than this, - * we rate-limit the controller Prepare() and Process() calls to lower than or - * equal to this rate. - */ -constexpr Duration controllerMinFrameDuration = 1.0s / 30.0; - -/* List of controls handled by the Raspberry Pi IPA */ -static const ControlInfoMap::Map ipaControls{ - { &controls::AeEnable, ControlInfo(false, true) }, - { &controls::ExposureTime, ControlInfo(0, 66666) }, - { &controls::AnalogueGain, ControlInfo(1.0f, 16.0f) }, - { &controls::AeMeteringMode, ControlInfo(controls::AeMeteringModeValues) }, - { &controls::AeConstraintMode, ControlInfo(controls::AeConstraintModeValues) }, - { &controls::AeExposureMode, ControlInfo(controls::AeExposureModeValues) }, - { &controls::ExposureValue, ControlInfo(-8.0f, 8.0f, 0.0f) }, - { &controls::AwbEnable, ControlInfo(false, true) }, - { &controls::ColourGains, ControlInfo(0.0f, 32.0f) }, - { &controls::AwbMode, ControlInfo(controls::AwbModeValues) }, - { &controls::Brightness, ControlInfo(-1.0f, 1.0f, 0.0f) }, - { &controls::Contrast, ControlInfo(0.0f, 32.0f, 1.0f) }, - { &controls::Saturation, ControlInfo(0.0f, 32.0f, 1.0f) }, - { &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) }, - { &controls::ColourCorrectionMatrix, ControlInfo(-16.0f, 16.0f) }, - { &controls::ScalerCrop, ControlInfo(Rectangle{}, Rectangle(65535, 65535, 65535, 65535), Rectangle{}) }, - { &controls::FrameDurationLimits, ControlInfo(INT64_C(33333), INT64_C(120000)) }, - { &controls::draft::NoiseReductionMode, ControlInfo(controls::draft::NoiseReductionModeValues) } -}; - -LOG_DEFINE_CATEGORY(IPARPI) - -namespace ipa::RPi { - -class IPARPi : public IPARPiInterface -{ -public: - IPARPi() - : controller_(), frameCount_(0), checkCount_(0), mistrustCount_(0), - lastRunTimestamp_(0), lsTable_(nullptr), firstStart_(true) - { - } - - ~IPARPi() - { - if (lsTable_) - munmap(lsTable_, MaxLsGridSize); - } - - int init(const IPASettings &settings, IPAInitResult *result) override; - void start(const ControlList &controls, StartConfig *startConfig) override; - void stop() override {} - - int configure(const IPACameraSensorInfo &sensorInfo, - const std::map<unsigned int, IPAStream> &streamConfig, - const std::map<unsigned int, ControlInfoMap> &entityControls, - const IPAConfig &data, - ControlList *controls, IPAConfigResult *result) override; - void mapBuffers(const std::vector<IPABuffer> &buffers) override; - void unmapBuffers(const std::vector<unsigned int> &ids) override; - void signalStatReady(const uint32_t bufferId) override; - void signalQueueRequest(const ControlList &controls) override; - void signalIspPrepare(const ISPConfig &data) override; - -private: - void setMode(const IPACameraSensorInfo &sensorInfo); - bool validateSensorControls(); - bool validateIspControls(); - void queueRequest(const ControlList &controls); - void returnEmbeddedBuffer(unsigned int bufferId); - void prepareISP(const ISPConfig &data); - void reportMetadata(); - void fillDeviceStatus(const ControlList &sensorControls); - void processStats(unsigned int bufferId); - void applyFrameDurations(Duration minFrameDuration, Duration maxFrameDuration); - void applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls); - void applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls); - void applyDG(const struct AgcStatus *dgStatus, ControlList &ctrls); - void applyCCM(const struct CcmStatus *ccmStatus, ControlList &ctrls); - void applyBlackLevel(const struct BlackLevelStatus *blackLevelStatus, ControlList &ctrls); - void applyGamma(const struct ContrastStatus *contrastStatus, ControlList &ctrls); - void applyGEQ(const struct GeqStatus *geqStatus, ControlList &ctrls); - void applyDenoise(const struct DenoiseStatus *denoiseStatus, ControlList &ctrls); - void applySharpen(const struct SharpenStatus *sharpenStatus, ControlList &ctrls); - void applyDPC(const struct DpcStatus *dpcStatus, ControlList &ctrls); - void applyLS(const struct AlscStatus *lsStatus, ControlList &ctrls); - void resampleTable(uint16_t dest[], double const src[12][16], int destW, int destH); - - std::map<unsigned int, MappedFrameBuffer> buffers_; - - ControlInfoMap sensorCtrls_; - ControlInfoMap ispCtrls_; - ControlList libcameraMetadata_; - - /* Camera sensor params. */ - CameraMode mode_; - - /* Raspberry Pi controller specific defines. */ - std::unique_ptr<RPiController::CamHelper> helper_; - RPiController::Controller controller_; - RPiController::Metadata rpiMetadata_; - - /* - * We count frames to decide if the frame must be hidden (e.g. from - * display) or mistrusted (i.e. not given to the control algos). - */ - uint64_t frameCount_; - - /* For checking the sequencing of Prepare/Process calls. */ - uint64_t checkCount_; - - /* How many frames we should avoid running control algos on. */ - unsigned int mistrustCount_; - - /* Number of frames that need to be dropped on startup. */ - unsigned int dropFrameCount_; - - /* Frame timestamp for the last run of the controller. */ - uint64_t lastRunTimestamp_; - - /* Do we run a Controller::process() for this frame? */ - bool processPending_; - - /* LS table allocation passed in from the pipeline handler. */ - SharedFD lsTableHandle_; - void *lsTable_; - - /* Distinguish the first camera start from others. */ - bool firstStart_; - - /* Frame duration (1/fps) limits. */ - Duration minFrameDuration_; - Duration maxFrameDuration_; - - /* Maximum gain code for the sensor. */ - uint32_t maxSensorGainCode_; -}; - -int IPARPi::init(const IPASettings &settings, IPAInitResult *result) -{ - /* - * Load the "helper" for this sensor. This tells us all the device specific stuff - * that the kernel driver doesn't. We only do this the first time; we don't need - * to re-parse the metadata after a simple mode-switch for no reason. - */ - helper_ = std::unique_ptr<RPiController::CamHelper>(RPiController::CamHelper::Create(settings.sensorModel)); - if (!helper_) { - LOG(IPARPI, Error) << "Could not create camera helper for " - << settings.sensorModel; - return -EINVAL; - } - - /* - * Pass out the sensor config to the pipeline handler in order - * to setup the staggered writer class. - */ - int gainDelay, exposureDelay, vblankDelay, sensorMetadata; - helper_->GetDelays(exposureDelay, gainDelay, vblankDelay); - sensorMetadata = helper_->SensorEmbeddedDataPresent(); - - result->sensorConfig.gainDelay = gainDelay; - result->sensorConfig.exposureDelay = exposureDelay; - result->sensorConfig.vblankDelay = vblankDelay; - result->sensorConfig.sensorMetadata = sensorMetadata; - - /* Load the tuning file for this sensor. */ - controller_.Read(settings.configurationFile.c_str()); - controller_.Initialise(); - - /* Return the controls handled by the IPA */ - ControlInfoMap::Map ctrlMap = ipaControls; - result->controlInfo = ControlInfoMap(std::move(ctrlMap), controls::controls); - - return 0; -} - -void IPARPi::start(const ControlList &controls, StartConfig *startConfig) -{ - RPiController::Metadata metadata; - - ASSERT(startConfig); - if (!controls.empty()) { - /* We have been given some controls to action before start. */ - queueRequest(controls); - } - - controller_.SwitchMode(mode_, &metadata); - - /* SwitchMode may supply updated exposure/gain values to use. */ - AgcStatus agcStatus; - agcStatus.shutter_time = 0.0s; - agcStatus.analogue_gain = 0.0; - - metadata.Get("agc.status", agcStatus); - if (agcStatus.shutter_time && agcStatus.analogue_gain) { - ControlList ctrls(sensorCtrls_); - applyAGC(&agcStatus, ctrls); - startConfig->controls = std::move(ctrls); - } - - /* - * Initialise frame counts, and decide how many frames must be hidden or - * "mistrusted", which depends on whether this is a startup from cold, - * or merely a mode switch in a running system. - */ - frameCount_ = 0; - checkCount_ = 0; - if (firstStart_) { - dropFrameCount_ = helper_->HideFramesStartup(); - mistrustCount_ = helper_->MistrustFramesStartup(); - - /* - * Query the AGC/AWB for how many frames they may take to - * converge sufficiently. Where these numbers are non-zero - * we must allow for the frames with bad statistics - * (mistrustCount_) that they won't see. But if zero (i.e. - * no convergence necessary), no frames need to be dropped. - */ - unsigned int agcConvergenceFrames = 0; - RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( - controller_.GetAlgorithm("agc")); - if (agc) { - agcConvergenceFrames = agc->GetConvergenceFrames(); - if (agcConvergenceFrames) - agcConvergenceFrames += mistrustCount_; - } - - unsigned int awbConvergenceFrames = 0; - RPiController::AwbAlgorithm *awb = dynamic_cast<RPiController::AwbAlgorithm *>( - controller_.GetAlgorithm("awb")); - if (awb) { - awbConvergenceFrames = awb->GetConvergenceFrames(); - if (awbConvergenceFrames) - awbConvergenceFrames += mistrustCount_; - } - - dropFrameCount_ = std::max({ dropFrameCount_, agcConvergenceFrames, awbConvergenceFrames }); - LOG(IPARPI, Debug) << "Drop " << dropFrameCount_ << " frames on startup"; - } else { - dropFrameCount_ = helper_->HideFramesModeSwitch(); - mistrustCount_ = helper_->MistrustFramesModeSwitch(); - } - - startConfig->dropFrameCount = dropFrameCount_; - const Duration maxSensorFrameDuration = mode_.max_frame_length * mode_.line_length; - startConfig->maxSensorFrameLengthMs = maxSensorFrameDuration.get<std::milli>(); - - firstStart_ = false; - lastRunTimestamp_ = 0; -} - -void IPARPi::setMode(const IPACameraSensorInfo &sensorInfo) -{ - mode_.bitdepth = sensorInfo.bitsPerPixel; - mode_.width = sensorInfo.outputSize.width; - mode_.height = sensorInfo.outputSize.height; - mode_.sensor_width = sensorInfo.activeAreaSize.width; - mode_.sensor_height = sensorInfo.activeAreaSize.height; - mode_.crop_x = sensorInfo.analogCrop.x; - mode_.crop_y = sensorInfo.analogCrop.y; - - /* - * Calculate scaling parameters. The scale_[xy] factors are determined - * by the ratio between the crop rectangle size and the output size. - */ - mode_.scale_x = sensorInfo.analogCrop.width / sensorInfo.outputSize.width; - mode_.scale_y = sensorInfo.analogCrop.height / sensorInfo.outputSize.height; - - /* - * We're not told by the pipeline handler how scaling is split between - * binning and digital scaling. For now, as a heuristic, assume that - * downscaling up to 2 is achieved through binning, and that any - * additional scaling is achieved through digital scaling. - * - * \todo Get the pipeline handle to provide the full data - */ - mode_.bin_x = std::min(2, static_cast<int>(mode_.scale_x)); - mode_.bin_y = std::min(2, static_cast<int>(mode_.scale_y)); - - /* The noise factor is the square root of the total binning factor. */ - mode_.noise_factor = sqrt(mode_.bin_x * mode_.bin_y); - - /* - * Calculate the line length as the ratio between the line length in - * pixels and the pixel rate. - */ - mode_.line_length = sensorInfo.lineLength * (1.0s / sensorInfo.pixelRate); - - /* - * Set the frame length limits for the mode to ensure exposure and - * framerate calculations are clipped appropriately. - */ - mode_.min_frame_length = sensorInfo.minFrameLength; - mode_.max_frame_length = sensorInfo.maxFrameLength; - - /* - * Some sensors may have different sensitivities in different modes; - * the CamHelper will know the correct value. - */ - mode_.sensitivity = helper_->GetModeSensitivity(mode_); -} - -int IPARPi::configure(const IPACameraSensorInfo &sensorInfo, - [[maybe_unused]] const std::map<unsigned int, IPAStream> &streamConfig, - const std::map<unsigned int, ControlInfoMap> &entityControls, - const IPAConfig &ipaConfig, - ControlList *controls, IPAConfigResult *result) -{ - if (entityControls.size() != 2) { - LOG(IPARPI, Error) << "No ISP or sensor controls found."; - return -1; - } - - sensorCtrls_ = entityControls.at(0); - ispCtrls_ = entityControls.at(1); - - if (!validateSensorControls()) { - LOG(IPARPI, Error) << "Sensor control validation failed."; - return -1; - } - - if (!validateIspControls()) { - LOG(IPARPI, Error) << "ISP control validation failed."; - return -1; - } - - maxSensorGainCode_ = sensorCtrls_.at(V4L2_CID_ANALOGUE_GAIN).max().get<int32_t>(); - - /* Setup a metadata ControlList to output metadata. */ - libcameraMetadata_ = ControlList(controls::controls); - - /* Re-assemble camera mode using the sensor info. */ - setMode(sensorInfo); - - mode_.transform = static_cast<libcamera::Transform>(ipaConfig.transform); - - /* Store the lens shading table pointer and handle if available. */ - if (ipaConfig.lsTableHandle.isValid()) { - /* Remove any previous table, if there was one. */ - if (lsTable_) { - munmap(lsTable_, MaxLsGridSize); - lsTable_ = nullptr; - } - - /* Map the LS table buffer into user space. */ - lsTableHandle_ = std::move(ipaConfig.lsTableHandle); - if (lsTableHandle_.isValid()) { - lsTable_ = mmap(nullptr, MaxLsGridSize, PROT_READ | PROT_WRITE, - MAP_SHARED, lsTableHandle_.get(), 0); - - if (lsTable_ == MAP_FAILED) { - LOG(IPARPI, Error) << "dmaHeap mmap failure for LS table."; - lsTable_ = nullptr; - } - } - } - - /* Pass the camera mode to the CamHelper to setup algorithms. */ - helper_->SetCameraMode(mode_); - - /* - * Initialise this ControlList correctly, even if empty, in case the IPA is - * running is isolation mode (passing the ControlList through the IPC layer). - */ - ControlList ctrls(sensorCtrls_); - - /* The pipeline handler passes out the mode's sensitivity. */ - result->modeSensitivity = mode_.sensitivity; - - if (firstStart_) { - /* Supply initial values for frame durations. */ - applyFrameDurations(defaultMinFrameDuration, defaultMaxFrameDuration); - - /* Supply initial values for gain and exposure. */ - AgcStatus agcStatus; - agcStatus.shutter_time = defaultExposureTime; - agcStatus.analogue_gain = defaultAnalogueGain; - applyAGC(&agcStatus, ctrls); - } - - ASSERT(controls); - *controls = std::move(ctrls); - - /* - * Apply the correct limits to the exposure, gain and frame duration controls - * based on the current sensor mode. - */ - ControlInfoMap::Map ctrlMap = ipaControls; - const Duration minSensorFrameDuration = mode_.min_frame_length * mode_.line_length; - const Duration maxSensorFrameDuration = mode_.max_frame_length * mode_.line_length; - ctrlMap[&controls::FrameDurationLimits] = - ControlInfo(static_cast<int64_t>(minSensorFrameDuration.get<std::micro>()), - static_cast<int64_t>(maxSensorFrameDuration.get<std::micro>())); - - ctrlMap[&controls::AnalogueGain] = - ControlInfo(1.0f, static_cast<float>(helper_->Gain(maxSensorGainCode_))); - - /* - * Calculate the max exposure limit from the frame duration limit as V4L2 - * will limit the maximum control value based on the current VBLANK value. - */ - Duration maxShutter = Duration::max(); - helper_->GetVBlanking(maxShutter, minSensorFrameDuration, maxSensorFrameDuration); - const uint32_t exposureMin = sensorCtrls_.at(V4L2_CID_EXPOSURE).min().get<int32_t>(); - - ctrlMap[&controls::ExposureTime] = - ControlInfo(static_cast<int32_t>(helper_->Exposure(exposureMin).get<std::micro>()), - static_cast<int32_t>(maxShutter.get<std::micro>())); - - result->controlInfo = ControlInfoMap(std::move(ctrlMap), controls::controls); - return 0; -} - -void IPARPi::mapBuffers(const std::vector<IPABuffer> &buffers) -{ - for (const IPABuffer &buffer : buffers) { - const FrameBuffer fb(buffer.planes); - buffers_.emplace(buffer.id, - MappedFrameBuffer(&fb, MappedFrameBuffer::MapFlag::ReadWrite)); - } -} - -void IPARPi::unmapBuffers(const std::vector<unsigned int> &ids) -{ - for (unsigned int id : ids) { - auto it = buffers_.find(id); - if (it == buffers_.end()) - continue; - - buffers_.erase(id); - } -} - -void IPARPi::signalStatReady(uint32_t bufferId) -{ - if (++checkCount_ != frameCount_) /* assert here? */ - LOG(IPARPI, Error) << "WARNING: Prepare/Process mismatch!!!"; - if (processPending_ && frameCount_ > mistrustCount_) - processStats(bufferId); - - reportMetadata(); - - statsMetadataComplete.emit(bufferId & MaskID, libcameraMetadata_); -} - -void IPARPi::signalQueueRequest(const ControlList &controls) -{ - queueRequest(controls); -} - -void IPARPi::signalIspPrepare(const ISPConfig &data) -{ - /* - * At start-up, or after a mode-switch, we may want to - * avoid running the control algos for a few frames in case - * they are "unreliable". - */ - prepareISP(data); - frameCount_++; - - /* Ready to push the input buffer into the ISP. */ - runIsp.emit(data.bayerBufferId & MaskID); -} - -void IPARPi::reportMetadata() -{ - std::unique_lock<RPiController::Metadata> lock(rpiMetadata_); - - /* - * Certain information about the current frame and how it will be - * processed can be extracted and placed into the libcamera metadata - * buffer, where an application could query it. - */ - DeviceStatus *deviceStatus = rpiMetadata_.GetLocked<DeviceStatus>("device.status"); - if (deviceStatus) { - libcameraMetadata_.set(controls::ExposureTime, - deviceStatus->shutter_speed.get<std::micro>()); - libcameraMetadata_.set(controls::AnalogueGain, deviceStatus->analogue_gain); - libcameraMetadata_.set(controls::FrameDuration, - helper_->Exposure(deviceStatus->frame_length).get<std::micro>()); - if (deviceStatus->sensor_temperature) - libcameraMetadata_.set(controls::SensorTemperature, *deviceStatus->sensor_temperature); - } - - AgcStatus *agcStatus = rpiMetadata_.GetLocked<AgcStatus>("agc.status"); - if (agcStatus) { - libcameraMetadata_.set(controls::AeLocked, agcStatus->locked); - libcameraMetadata_.set(controls::DigitalGain, agcStatus->digital_gain); - } - - LuxStatus *luxStatus = rpiMetadata_.GetLocked<LuxStatus>("lux.status"); - if (luxStatus) - libcameraMetadata_.set(controls::Lux, luxStatus->lux); - - AwbStatus *awbStatus = rpiMetadata_.GetLocked<AwbStatus>("awb.status"); - if (awbStatus) { - libcameraMetadata_.set(controls::ColourGains, { static_cast<float>(awbStatus->gain_r), - static_cast<float>(awbStatus->gain_b) }); - libcameraMetadata_.set(controls::ColourTemperature, awbStatus->temperature_K); - } - - BlackLevelStatus *blackLevelStatus = rpiMetadata_.GetLocked<BlackLevelStatus>("black_level.status"); - if (blackLevelStatus) - libcameraMetadata_.set(controls::SensorBlackLevels, - { static_cast<int32_t>(blackLevelStatus->black_level_r), - static_cast<int32_t>(blackLevelStatus->black_level_g), - static_cast<int32_t>(blackLevelStatus->black_level_g), - static_cast<int32_t>(blackLevelStatus->black_level_b) }); - - FocusStatus *focusStatus = rpiMetadata_.GetLocked<FocusStatus>("focus.status"); - if (focusStatus && focusStatus->num == 12) { - /* - * We get a 4x3 grid of regions by default. Calculate the average - * FoM over the central two positions to give an overall scene FoM. - * This can change later if it is not deemed suitable. - */ - int32_t focusFoM = (focusStatus->focus_measures[5] + focusStatus->focus_measures[6]) / 2; - libcameraMetadata_.set(controls::FocusFoM, focusFoM); - } - - CcmStatus *ccmStatus = rpiMetadata_.GetLocked<CcmStatus>("ccm.status"); - if (ccmStatus) { - float m[9]; - for (unsigned int i = 0; i < 9; i++) - m[i] = ccmStatus->matrix[i]; - libcameraMetadata_.set(controls::ColourCorrectionMatrix, m); - } -} - -bool IPARPi::validateSensorControls() -{ - static const uint32_t ctrls[] = { - V4L2_CID_ANALOGUE_GAIN, - V4L2_CID_EXPOSURE, - V4L2_CID_VBLANK, - }; - - for (auto c : ctrls) { - if (sensorCtrls_.find(c) == sensorCtrls_.end()) { - LOG(IPARPI, Error) << "Unable to find sensor control " - << utils::hex(c); - return false; - } - } - - return true; -} - -bool IPARPi::validateIspControls() -{ - static const uint32_t ctrls[] = { - V4L2_CID_RED_BALANCE, - V4L2_CID_BLUE_BALANCE, - V4L2_CID_DIGITAL_GAIN, - V4L2_CID_USER_BCM2835_ISP_CC_MATRIX, - V4L2_CID_USER_BCM2835_ISP_GAMMA, - V4L2_CID_USER_BCM2835_ISP_BLACK_LEVEL, - V4L2_CID_USER_BCM2835_ISP_GEQ, - V4L2_CID_USER_BCM2835_ISP_DENOISE, - V4L2_CID_USER_BCM2835_ISP_SHARPEN, - V4L2_CID_USER_BCM2835_ISP_DPC, - V4L2_CID_USER_BCM2835_ISP_LENS_SHADING, - V4L2_CID_USER_BCM2835_ISP_CDN, - }; - - for (auto c : ctrls) { - if (ispCtrls_.find(c) == ispCtrls_.end()) { - LOG(IPARPI, Error) << "Unable to find ISP control " - << utils::hex(c); - return false; - } - } - - return true; -} - -/* - * Converting between enums (used in the libcamera API) and the names that - * we use to identify different modes. Unfortunately, the conversion tables - * must be kept up-to-date by hand. - */ -static const std::map<int32_t, std::string> MeteringModeTable = { - { controls::MeteringCentreWeighted, "centre-weighted" }, - { controls::MeteringSpot, "spot" }, - { controls::MeteringMatrix, "matrix" }, - { controls::MeteringCustom, "custom" }, -}; - -static const std::map<int32_t, std::string> ConstraintModeTable = { - { controls::ConstraintNormal, "normal" }, - { controls::ConstraintHighlight, "highlight" }, - { controls::ConstraintCustom, "custom" }, -}; - -static const std::map<int32_t, std::string> ExposureModeTable = { - { controls::ExposureNormal, "normal" }, - { controls::ExposureShort, "short" }, - { controls::ExposureLong, "long" }, - { controls::ExposureCustom, "custom" }, -}; - -static const std::map<int32_t, std::string> AwbModeTable = { - { controls::AwbAuto, "auto" }, - { controls::AwbIncandescent, "incandescent" }, - { controls::AwbTungsten, "tungsten" }, - { controls::AwbFluorescent, "fluorescent" }, - { controls::AwbIndoor, "indoor" }, - { controls::AwbDaylight, "daylight" }, - { controls::AwbCloudy, "cloudy" }, - { controls::AwbCustom, "custom" }, -}; - -static const std::map<int32_t, RPiController::DenoiseMode> DenoiseModeTable = { - { controls::draft::NoiseReductionModeOff, RPiController::DenoiseMode::Off }, - { controls::draft::NoiseReductionModeFast, RPiController::DenoiseMode::ColourFast }, - { controls::draft::NoiseReductionModeHighQuality, RPiController::DenoiseMode::ColourHighQuality }, - { controls::draft::NoiseReductionModeMinimal, RPiController::DenoiseMode::ColourOff }, - { controls::draft::NoiseReductionModeZSL, RPiController::DenoiseMode::ColourHighQuality }, -}; - -void IPARPi::queueRequest(const ControlList &controls) -{ - /* Clear the return metadata buffer. */ - libcameraMetadata_.clear(); - - for (auto const &ctrl : controls) { - LOG(IPARPI, Debug) << "Request ctrl: " - << controls::controls.at(ctrl.first)->name() - << " = " << ctrl.second.toString(); - - switch (ctrl.first) { - case controls::AE_ENABLE: { - RPiController::Algorithm *agc = controller_.GetAlgorithm("agc"); - if (!agc) { - LOG(IPARPI, Warning) - << "Could not set AE_ENABLE - no AGC algorithm"; - break; - } - - if (ctrl.second.get<bool>() == false) - agc->Pause(); - else - agc->Resume(); - - libcameraMetadata_.set(controls::AeEnable, ctrl.second.get<bool>()); - break; - } - - case controls::EXPOSURE_TIME: { - RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( - controller_.GetAlgorithm("agc")); - if (!agc) { - LOG(IPARPI, Warning) - << "Could not set EXPOSURE_TIME - no AGC algorithm"; - break; - } - - /* The control provides units of microseconds. */ - agc->SetFixedShutter(ctrl.second.get<int32_t>() * 1.0us); - - libcameraMetadata_.set(controls::ExposureTime, ctrl.second.get<int32_t>()); - break; - } - - case controls::ANALOGUE_GAIN: { - RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( - controller_.GetAlgorithm("agc")); - if (!agc) { - LOG(IPARPI, Warning) - << "Could not set ANALOGUE_GAIN - no AGC algorithm"; - break; - } - - agc->SetFixedAnalogueGain(ctrl.second.get<float>()); - - libcameraMetadata_.set(controls::AnalogueGain, - ctrl.second.get<float>()); - break; - } - - case controls::AE_METERING_MODE: { - RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( - controller_.GetAlgorithm("agc")); - if (!agc) { - LOG(IPARPI, Warning) - << "Could not set AE_METERING_MODE - no AGC algorithm"; - break; - } - - int32_t idx = ctrl.second.get<int32_t>(); - if (MeteringModeTable.count(idx)) { - agc->SetMeteringMode(MeteringModeTable.at(idx)); - libcameraMetadata_.set(controls::AeMeteringMode, idx); - } else { - LOG(IPARPI, Error) << "Metering mode " << idx - << " not recognised"; - } - break; - } - - case controls::AE_CONSTRAINT_MODE: { - RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( - controller_.GetAlgorithm("agc")); - if (!agc) { - LOG(IPARPI, Warning) - << "Could not set AE_CONSTRAINT_MODE - no AGC algorithm"; - break; - } - - int32_t idx = ctrl.second.get<int32_t>(); - if (ConstraintModeTable.count(idx)) { - agc->SetConstraintMode(ConstraintModeTable.at(idx)); - libcameraMetadata_.set(controls::AeConstraintMode, idx); - } else { - LOG(IPARPI, Error) << "Constraint mode " << idx - << " not recognised"; - } - break; - } - - case controls::AE_EXPOSURE_MODE: { - RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( - controller_.GetAlgorithm("agc")); - if (!agc) { - LOG(IPARPI, Warning) - << "Could not set AE_EXPOSURE_MODE - no AGC algorithm"; - break; - } - - int32_t idx = ctrl.second.get<int32_t>(); - if (ExposureModeTable.count(idx)) { - agc->SetExposureMode(ExposureModeTable.at(idx)); - libcameraMetadata_.set(controls::AeExposureMode, idx); - } else { - LOG(IPARPI, Error) << "Exposure mode " << idx - << " not recognised"; - } - break; - } - - case controls::EXPOSURE_VALUE: { - RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( - controller_.GetAlgorithm("agc")); - if (!agc) { - LOG(IPARPI, Warning) - << "Could not set EXPOSURE_VALUE - no AGC algorithm"; - break; - } - - /* - * The SetEv() function takes in a direct exposure multiplier. - * So convert to 2^EV - */ - double ev = pow(2.0, ctrl.second.get<float>()); - agc->SetEv(ev); - libcameraMetadata_.set(controls::ExposureValue, - ctrl.second.get<float>()); - break; - } - - case controls::AWB_ENABLE: { - RPiController::Algorithm *awb = controller_.GetAlgorithm("awb"); - if (!awb) { - LOG(IPARPI, Warning) - << "Could not set AWB_ENABLE - no AWB algorithm"; - break; - } - - if (ctrl.second.get<bool>() == false) - awb->Pause(); - else - awb->Resume(); - - libcameraMetadata_.set(controls::AwbEnable, - ctrl.second.get<bool>()); - break; - } - - case controls::AWB_MODE: { - RPiController::AwbAlgorithm *awb = dynamic_cast<RPiController::AwbAlgorithm *>( - controller_.GetAlgorithm("awb")); - if (!awb) { - LOG(IPARPI, Warning) - << "Could not set AWB_MODE - no AWB algorithm"; - break; - } - - int32_t idx = ctrl.second.get<int32_t>(); - if (AwbModeTable.count(idx)) { - awb->SetMode(AwbModeTable.at(idx)); - libcameraMetadata_.set(controls::AwbMode, idx); - } else { - LOG(IPARPI, Error) << "AWB mode " << idx - << " not recognised"; - } - break; - } - - case controls::COLOUR_GAINS: { - auto gains = ctrl.second.get<Span<const float>>(); - RPiController::AwbAlgorithm *awb = dynamic_cast<RPiController::AwbAlgorithm *>( - controller_.GetAlgorithm("awb")); - if (!awb) { - LOG(IPARPI, Warning) - << "Could not set COLOUR_GAINS - no AWB algorithm"; - break; - } - - awb->SetManualGains(gains[0], gains[1]); - if (gains[0] != 0.0f && gains[1] != 0.0f) - /* A gain of 0.0f will switch back to auto mode. */ - libcameraMetadata_.set(controls::ColourGains, - { gains[0], gains[1] }); - break; - } - - case controls::BRIGHTNESS: { - RPiController::ContrastAlgorithm *contrast = dynamic_cast<RPiController::ContrastAlgorithm *>( - controller_.GetAlgorithm("contrast")); - if (!contrast) { - LOG(IPARPI, Warning) - << "Could not set BRIGHTNESS - no contrast algorithm"; - break; - } - - contrast->SetBrightness(ctrl.second.get<float>() * 65536); - libcameraMetadata_.set(controls::Brightness, - ctrl.second.get<float>()); - break; - } - - case controls::CONTRAST: { - RPiController::ContrastAlgorithm *contrast = dynamic_cast<RPiController::ContrastAlgorithm *>( - controller_.GetAlgorithm("contrast")); - if (!contrast) { - LOG(IPARPI, Warning) - << "Could not set CONTRAST - no contrast algorithm"; - break; - } - - contrast->SetContrast(ctrl.second.get<float>()); - libcameraMetadata_.set(controls::Contrast, - ctrl.second.get<float>()); - break; - } - - case controls::SATURATION: { - RPiController::CcmAlgorithm *ccm = dynamic_cast<RPiController::CcmAlgorithm *>( - controller_.GetAlgorithm("ccm")); - if (!ccm) { - LOG(IPARPI, Warning) - << "Could not set SATURATION - no ccm algorithm"; - break; - } - - ccm->SetSaturation(ctrl.second.get<float>()); - libcameraMetadata_.set(controls::Saturation, - ctrl.second.get<float>()); - break; - } - - case controls::SHARPNESS: { - RPiController::SharpenAlgorithm *sharpen = dynamic_cast<RPiController::SharpenAlgorithm *>( - controller_.GetAlgorithm("sharpen")); - if (!sharpen) { - LOG(IPARPI, Warning) - << "Could not set SHARPNESS - no sharpen algorithm"; - break; - } - - sharpen->SetStrength(ctrl.second.get<float>()); - libcameraMetadata_.set(controls::Sharpness, - ctrl.second.get<float>()); - break; - } - - case controls::SCALER_CROP: { - /* We do nothing with this, but should avoid the warning below. */ - break; - } - - case controls::FRAME_DURATION_LIMITS: { - auto frameDurations = ctrl.second.get<Span<const int64_t>>(); - applyFrameDurations(frameDurations[0] * 1.0us, frameDurations[1] * 1.0us); - break; - } - - case controls::NOISE_REDUCTION_MODE: { - RPiController::DenoiseAlgorithm *sdn = dynamic_cast<RPiController::DenoiseAlgorithm *>( - controller_.GetAlgorithm("SDN")); - if (!sdn) { - LOG(IPARPI, Warning) - << "Could not set NOISE_REDUCTION_MODE - no SDN algorithm"; - break; - } - - int32_t idx = ctrl.second.get<int32_t>(); - auto mode = DenoiseModeTable.find(idx); - if (mode != DenoiseModeTable.end()) { - sdn->SetMode(mode->second); - - /* - * \todo If the colour denoise is not going to run due to an - * analysis image resolution or format mismatch, we should - * report the status correctly in the metadata. - */ - libcameraMetadata_.set(controls::draft::NoiseReductionMode, idx); - } else { - LOG(IPARPI, Error) << "Noise reduction mode " << idx - << " not recognised"; - } - break; - } - - default: - LOG(IPARPI, Warning) - << "Ctrl " << controls::controls.at(ctrl.first)->name() - << " is not handled."; - break; - } - } -} - -void IPARPi::returnEmbeddedBuffer(unsigned int bufferId) -{ - embeddedComplete.emit(bufferId & MaskID); -} - -void IPARPi::prepareISP(const ISPConfig &data) -{ - int64_t frameTimestamp = data.controls.get(controls::SensorTimestamp); - RPiController::Metadata lastMetadata; - Span<uint8_t> embeddedBuffer; - - lastMetadata = std::move(rpiMetadata_); - fillDeviceStatus(data.controls); - - if (data.embeddedBufferPresent) { - /* - * Pipeline handler has supplied us with an embedded data buffer, - * we must pass it to the CamHelper for parsing. - */ - auto it = buffers_.find(data.embeddedBufferId); - ASSERT(it != buffers_.end()); - embeddedBuffer = it->second.planes()[0]; - } - - /* - * This may overwrite the DeviceStatus using values from the sensor - * metadata, and may also do additional custom processing. - */ - helper_->Prepare(embeddedBuffer, rpiMetadata_); - - /* Done with embedded data now, return to pipeline handler asap. */ - if (data.embeddedBufferPresent) - returnEmbeddedBuffer(data.embeddedBufferId); - - /* Allow a 10% margin on the comparison below. */ - Duration delta = (frameTimestamp - lastRunTimestamp_) * 1.0ns; - if (lastRunTimestamp_ && frameCount_ > dropFrameCount_ && - delta < controllerMinFrameDuration * 0.9) { - /* - * Ensure we merge the previous frame's metadata with the current - * frame. This will not overwrite exposure/gain values for the - * current frame, or any other bits of metadata that were added - * in helper_->Prepare(). - */ - rpiMetadata_.Merge(lastMetadata); - processPending_ = false; - return; - } - - lastRunTimestamp_ = frameTimestamp; - processPending_ = true; - - ControlList ctrls(ispCtrls_); - - controller_.Prepare(&rpiMetadata_); - - /* Lock the metadata buffer to avoid constant locks/unlocks. */ - std::unique_lock<RPiController::Metadata> lock(rpiMetadata_); - - AwbStatus *awbStatus = rpiMetadata_.GetLocked<AwbStatus>("awb.status"); - if (awbStatus) - applyAWB(awbStatus, ctrls); - - CcmStatus *ccmStatus = rpiMetadata_.GetLocked<CcmStatus>("ccm.status"); - if (ccmStatus) - applyCCM(ccmStatus, ctrls); - - AgcStatus *dgStatus = rpiMetadata_.GetLocked<AgcStatus>("agc.status"); - if (dgStatus) - applyDG(dgStatus, ctrls); - - AlscStatus *lsStatus = rpiMetadata_.GetLocked<AlscStatus>("alsc.status"); - if (lsStatus) - applyLS(lsStatus, ctrls); - - ContrastStatus *contrastStatus = rpiMetadata_.GetLocked<ContrastStatus>("contrast.status"); - if (contrastStatus) - applyGamma(contrastStatus, ctrls); - - BlackLevelStatus *blackLevelStatus = rpiMetadata_.GetLocked<BlackLevelStatus>("black_level.status"); - if (blackLevelStatus) - applyBlackLevel(blackLevelStatus, ctrls); - - GeqStatus *geqStatus = rpiMetadata_.GetLocked<GeqStatus>("geq.status"); - if (geqStatus) - applyGEQ(geqStatus, ctrls); - - DenoiseStatus *denoiseStatus = rpiMetadata_.GetLocked<DenoiseStatus>("denoise.status"); - if (denoiseStatus) - applyDenoise(denoiseStatus, ctrls); - - SharpenStatus *sharpenStatus = rpiMetadata_.GetLocked<SharpenStatus>("sharpen.status"); - if (sharpenStatus) - applySharpen(sharpenStatus, ctrls); - - DpcStatus *dpcStatus = rpiMetadata_.GetLocked<DpcStatus>("dpc.status"); - if (dpcStatus) - applyDPC(dpcStatus, ctrls); - - if (!ctrls.empty()) - setIspControls.emit(ctrls); -} - -void IPARPi::fillDeviceStatus(const ControlList &sensorControls) -{ - DeviceStatus deviceStatus = {}; - - int32_t exposureLines = sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>(); - int32_t gainCode = sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>(); - int32_t vblank = sensorControls.get(V4L2_CID_VBLANK).get<int32_t>(); - - deviceStatus.shutter_speed = helper_->Exposure(exposureLines); - deviceStatus.analogue_gain = helper_->Gain(gainCode); - deviceStatus.frame_length = mode_.height + vblank; - - LOG(IPARPI, Debug) << "Metadata - " << deviceStatus; - - rpiMetadata_.Set("device.status", deviceStatus); -} - -void IPARPi::processStats(unsigned int bufferId) -{ - auto it = buffers_.find(bufferId); - if (it == buffers_.end()) { - LOG(IPARPI, Error) << "Could not find stats buffer!"; - return; - } - - Span<uint8_t> mem = it->second.planes()[0]; - bcm2835_isp_stats *stats = reinterpret_cast<bcm2835_isp_stats *>(mem.data()); - RPiController::StatisticsPtr statistics = std::make_shared<bcm2835_isp_stats>(*stats); - helper_->Process(statistics, rpiMetadata_); - controller_.Process(statistics, &rpiMetadata_); - - struct AgcStatus agcStatus; - if (rpiMetadata_.Get("agc.status", agcStatus) == 0) { - ControlList ctrls(sensorCtrls_); - applyAGC(&agcStatus, ctrls); - - setDelayedControls.emit(ctrls); - } -} - -void IPARPi::applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls) -{ - LOG(IPARPI, Debug) << "Applying WB R: " << awbStatus->gain_r << " B: " - << awbStatus->gain_b; - - ctrls.set(V4L2_CID_RED_BALANCE, - static_cast<int32_t>(awbStatus->gain_r * 1000)); - ctrls.set(V4L2_CID_BLUE_BALANCE, - static_cast<int32_t>(awbStatus->gain_b * 1000)); -} - -void IPARPi::applyFrameDurations(Duration minFrameDuration, Duration maxFrameDuration) -{ - const Duration minSensorFrameDuration = mode_.min_frame_length * mode_.line_length; - const Duration maxSensorFrameDuration = mode_.max_frame_length * mode_.line_length; - - /* - * This will only be applied once AGC recalculations occur. - * The values may be clamped based on the sensor mode capabilities as well. - */ - minFrameDuration_ = minFrameDuration ? minFrameDuration : defaultMaxFrameDuration; - maxFrameDuration_ = maxFrameDuration ? maxFrameDuration : defaultMinFrameDuration; - minFrameDuration_ = std::clamp(minFrameDuration_, - minSensorFrameDuration, maxSensorFrameDuration); - maxFrameDuration_ = std::clamp(maxFrameDuration_, - minSensorFrameDuration, maxSensorFrameDuration); - maxFrameDuration_ = std::max(maxFrameDuration_, minFrameDuration_); - - /* Return the validated limits via metadata. */ - libcameraMetadata_.set(controls::FrameDurationLimits, - { static_cast<int64_t>(minFrameDuration_.get<std::micro>()), - static_cast<int64_t>(maxFrameDuration_.get<std::micro>()) }); - - /* - * Calculate the maximum exposure time possible for the AGC to use. - * GetVBlanking() will update maxShutter with the largest exposure - * value possible. - */ - Duration maxShutter = Duration::max(); - helper_->GetVBlanking(maxShutter, minFrameDuration_, maxFrameDuration_); - - RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( - controller_.GetAlgorithm("agc")); - agc->SetMaxShutter(maxShutter); -} - -void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls) -{ - int32_t gainCode = helper_->GainCode(agcStatus->analogue_gain); - - /* - * Ensure anything larger than the max gain code will not be passed to - * DelayedControls. The AGC will correctly handle a lower gain returned - * by the sensor, provided it knows the actual gain used. - */ - gainCode = std::min<int32_t>(gainCode, maxSensorGainCode_); - - /* GetVBlanking might clip exposure time to the fps limits. */ - Duration exposure = agcStatus->shutter_time; - int32_t vblanking = helper_->GetVBlanking(exposure, minFrameDuration_, maxFrameDuration_); - int32_t exposureLines = helper_->ExposureLines(exposure); - - LOG(IPARPI, Debug) << "Applying AGC Exposure: " << exposure - << " (Shutter lines: " << exposureLines << ", AGC requested " - << agcStatus->shutter_time << ") Gain: " - << agcStatus->analogue_gain << " (Gain Code: " - << gainCode << ")"; - - /* - * Due to the behavior of V4L2, the current value of VBLANK could clip the - * exposure time without us knowing. The next time though this function should - * clip exposure correctly. - */ - ctrls.set(V4L2_CID_VBLANK, vblanking); - ctrls.set(V4L2_CID_EXPOSURE, exposureLines); - ctrls.set(V4L2_CID_ANALOGUE_GAIN, gainCode); -} - -void IPARPi::applyDG(const struct AgcStatus *dgStatus, ControlList &ctrls) -{ - ctrls.set(V4L2_CID_DIGITAL_GAIN, - static_cast<int32_t>(dgStatus->digital_gain * 1000)); -} - -void IPARPi::applyCCM(const struct CcmStatus *ccmStatus, ControlList &ctrls) -{ - bcm2835_isp_custom_ccm ccm; - - for (int i = 0; i < 9; i++) { - ccm.ccm.ccm[i / 3][i % 3].den = 1000; - ccm.ccm.ccm[i / 3][i % 3].num = 1000 * ccmStatus->matrix[i]; - } - - ccm.enabled = 1; - ccm.ccm.offsets[0] = ccm.ccm.offsets[1] = ccm.ccm.offsets[2] = 0; - - ControlValue c(Span<const uint8_t>{ reinterpret_cast<uint8_t *>(&ccm), - sizeof(ccm) }); - ctrls.set(V4L2_CID_USER_BCM2835_ISP_CC_MATRIX, c); -} - -void IPARPi::applyGamma(const struct ContrastStatus *contrastStatus, ControlList &ctrls) -{ - struct bcm2835_isp_gamma gamma; - - gamma.enabled = 1; - for (int i = 0; i < CONTRAST_NUM_POINTS; i++) { - gamma.x[i] = contrastStatus->points[i].x; - gamma.y[i] = contrastStatus->points[i].y; - } - - ControlValue c(Span<const uint8_t>{ reinterpret_cast<uint8_t *>(&gamma), - sizeof(gamma) }); - ctrls.set(V4L2_CID_USER_BCM2835_ISP_GAMMA, c); -} - -void IPARPi::applyBlackLevel(const struct BlackLevelStatus *blackLevelStatus, ControlList &ctrls) -{ - bcm2835_isp_black_level blackLevel; - - blackLevel.enabled = 1; - blackLevel.black_level_r = blackLevelStatus->black_level_r; - blackLevel.black_level_g = blackLevelStatus->black_level_g; - blackLevel.black_level_b = blackLevelStatus->black_level_b; - - ControlValue c(Span<const uint8_t>{ reinterpret_cast<uint8_t *>(&blackLevel), - sizeof(blackLevel) }); - ctrls.set(V4L2_CID_USER_BCM2835_ISP_BLACK_LEVEL, c); -} - -void IPARPi::applyGEQ(const struct GeqStatus *geqStatus, ControlList &ctrls) -{ - bcm2835_isp_geq geq; - - geq.enabled = 1; - geq.offset = geqStatus->offset; - geq.slope.den = 1000; - geq.slope.num = 1000 * geqStatus->slope; - - ControlValue c(Span<const uint8_t>{ reinterpret_cast<uint8_t *>(&geq), - sizeof(geq) }); - ctrls.set(V4L2_CID_USER_BCM2835_ISP_GEQ, c); -} - -void IPARPi::applyDenoise(const struct DenoiseStatus *denoiseStatus, ControlList &ctrls) -{ - using RPiController::DenoiseMode; - - bcm2835_isp_denoise denoise; - DenoiseMode mode = static_cast<DenoiseMode>(denoiseStatus->mode); - - denoise.enabled = mode != DenoiseMode::Off; - denoise.constant = denoiseStatus->noise_constant; - denoise.slope.num = 1000 * denoiseStatus->noise_slope; - denoise.slope.den = 1000; - denoise.strength.num = 1000 * denoiseStatus->strength; - denoise.strength.den = 1000; - - /* Set the CDN mode to match the SDN operating mode. */ - bcm2835_isp_cdn cdn; - switch (mode) { - case DenoiseMode::ColourFast: - cdn.enabled = 1; - cdn.mode = CDN_MODE_FAST; - break; - case DenoiseMode::ColourHighQuality: - cdn.enabled = 1; - cdn.mode = CDN_MODE_HIGH_QUALITY; - break; - default: - cdn.enabled = 0; - } - - ControlValue c(Span<const uint8_t>{ reinterpret_cast<uint8_t *>(&denoise), - sizeof(denoise) }); - ctrls.set(V4L2_CID_USER_BCM2835_ISP_DENOISE, c); - - c = ControlValue(Span<const uint8_t>{ reinterpret_cast<uint8_t *>(&cdn), - sizeof(cdn) }); - ctrls.set(V4L2_CID_USER_BCM2835_ISP_CDN, c); -} - -void IPARPi::applySharpen(const struct SharpenStatus *sharpenStatus, ControlList &ctrls) -{ - bcm2835_isp_sharpen sharpen; - - sharpen.enabled = 1; - sharpen.threshold.num = 1000 * sharpenStatus->threshold; - sharpen.threshold.den = 1000; - sharpen.strength.num = 1000 * sharpenStatus->strength; - sharpen.strength.den = 1000; - sharpen.limit.num = 1000 * sharpenStatus->limit; - sharpen.limit.den = 1000; - - ControlValue c(Span<const uint8_t>{ reinterpret_cast<uint8_t *>(&sharpen), - sizeof(sharpen) }); - ctrls.set(V4L2_CID_USER_BCM2835_ISP_SHARPEN, c); -} - -void IPARPi::applyDPC(const struct DpcStatus *dpcStatus, ControlList &ctrls) -{ - bcm2835_isp_dpc dpc; - - dpc.enabled = 1; - dpc.strength = dpcStatus->strength; - - ControlValue c(Span<const uint8_t>{ reinterpret_cast<uint8_t *>(&dpc), - sizeof(dpc) }); - ctrls.set(V4L2_CID_USER_BCM2835_ISP_DPC, c); -} - -void IPARPi::applyLS(const struct AlscStatus *lsStatus, ControlList &ctrls) -{ - /* - * Program lens shading tables into pipeline. - * Choose smallest cell size that won't exceed 63x48 cells. - */ - const int cellSizes[] = { 16, 32, 64, 128, 256 }; - unsigned int numCells = std::size(cellSizes); - unsigned int i, w, h, cellSize; - for (i = 0; i < numCells; i++) { - cellSize = cellSizes[i]; - w = (mode_.width + cellSize - 1) / cellSize; - h = (mode_.height + cellSize - 1) / cellSize; - if (w < 64 && h <= 48) - break; - } - - if (i == numCells) { - LOG(IPARPI, Error) << "Cannot find cell size"; - return; - } - - /* We're going to supply corner sampled tables, 16 bit samples. */ - w++, h++; - bcm2835_isp_lens_shading ls = { - .enabled = 1, - .grid_cell_size = cellSize, - .grid_width = w, - .grid_stride = w, - .grid_height = h, - /* .dmabuf will be filled in by pipeline handler. */ - .dmabuf = 0, - .ref_transform = 0, - .corner_sampled = 1, - .gain_format = GAIN_FORMAT_U4P10 - }; - - if (!lsTable_ || w * h * 4 * sizeof(uint16_t) > MaxLsGridSize) { - LOG(IPARPI, Error) << "Do not have a correctly allocate lens shading table!"; - return; - } - - if (lsStatus) { - /* Format will be u4.10 */ - uint16_t *grid = static_cast<uint16_t *>(lsTable_); - - resampleTable(grid, lsStatus->r, w, h); - resampleTable(grid + w * h, lsStatus->g, w, h); - std::memcpy(grid + 2 * w * h, grid + w * h, w * h * sizeof(uint16_t)); - resampleTable(grid + 3 * w * h, lsStatus->b, w, h); - } - - ControlValue c(Span<const uint8_t>{ reinterpret_cast<uint8_t *>(&ls), - sizeof(ls) }); - ctrls.set(V4L2_CID_USER_BCM2835_ISP_LENS_SHADING, c); -} - -/* - * Resamples a 16x12 table with central sampling to destW x destH with corner - * sampling. - */ -void IPARPi::resampleTable(uint16_t dest[], double const src[12][16], - int destW, int destH) -{ - /* - * Precalculate and cache the x sampling locations and phases to - * save recomputing them on every row. - */ - assert(destW > 1 && destH > 1 && destW <= 64); - int xLo[64], xHi[64]; - double xf[64]; - double x = -0.5, xInc = 16.0 / (destW - 1); - for (int i = 0; i < destW; i++, x += xInc) { - xLo[i] = floor(x); - xf[i] = x - xLo[i]; - xHi[i] = xLo[i] < 15 ? xLo[i] + 1 : 15; - xLo[i] = xLo[i] > 0 ? xLo[i] : 0; - } - - /* Now march over the output table generating the new values. */ - double y = -0.5, yInc = 12.0 / (destH - 1); - for (int j = 0; j < destH; j++, y += yInc) { - int yLo = floor(y); - double yf = y - yLo; - int yHi = yLo < 11 ? yLo + 1 : 11; - yLo = yLo > 0 ? yLo : 0; - double const *rowAbove = src[yLo]; - double const *rowBelow = src[yHi]; - for (int i = 0; i < destW; i++) { - double above = rowAbove[xLo[i]] * (1 - xf[i]) + rowAbove[xHi[i]] * xf[i]; - double below = rowBelow[xLo[i]] * (1 - xf[i]) + rowBelow[xHi[i]] * xf[i]; - int result = floor(1024 * (above * (1 - yf) + below * yf) + .5); - *(dest++) = result > 16383 ? 16383 : result; /* want u4.10 */ - } - } -} - -} /* namespace ipa::RPi */ - -/* - * External IPA module interface - */ -extern "C" { -const struct IPAModuleInfo ipaModuleInfo = { - IPA_MODULE_API_VERSION, - 1, - "PipelineHandlerRPi", - "raspberrypi", -}; - -IPAInterface *ipaCreate() -{ - return new ipa::RPi::IPARPi(); -} - -} /* extern "C" */ - -} /* namespace libcamera */ |