mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-12 23:09:45 +03:00
libcamera: software_isp: Add CCM algorithm
This patch adds color correction matrix (CCM) algorithm to software ISP. It is based on the corresponding algorithm in rkisp1. The primary difference against hardware pipelines is that applying the CCM is optional. Applying CCM causes a significant slowdown, time needed to process a frame raises by 40-90% on tested platforms. If CCM is really needed, it can be applied, if not, it's better to stick without it. This can be configured by presence or omission of Ccm algorithm in the tuning file. CCM is changed only if the determined temperature changes by at least 100 K (an arbitrarily selected value), to avoid recomputing the matrices and lookup tables all the time. Since the CCM is float, rather than double, to use the same type as in the rkisp1 pipeline, the type of color gains is changed from double to float. The outputs of the algorithm are not used yet, they will be enabled in followup patches. Signed-off-by: Milan Zamazal <mzamazal@redhat.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Milan Zamazal <mzamazal@redhat.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
parent
23dfd69081
commit
38ec74fb40
6 changed files with 133 additions and 4 deletions
|
@ -59,9 +59,9 @@ void Awb::process(IPAContext &context,
|
|||
*/
|
||||
auto &gains = context.activeState.awb.gains;
|
||||
gains = { {
|
||||
sumR <= sumG / 4 ? 4.0 : static_cast<double>(sumG) / sumR,
|
||||
sumR <= sumG / 4 ? 4.0f : static_cast<float>(sumG) / sumR,
|
||||
1.0,
|
||||
sumB <= sumG / 4 ? 4.0 : static_cast<double>(sumG) / sumB,
|
||||
sumB <= sumG / 4 ? 4.0f : static_cast<float>(sumG) / sumB,
|
||||
} };
|
||||
|
||||
RGB<double> rgbGains{ { 1 / gains.r(), 1 / gains.g(), 1 / gains.b() } };
|
||||
|
|
74
src/ipa/simple/algorithms/ccm.cpp
Normal file
74
src/ipa/simple/algorithms/ccm.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Copyright (C) 2024, Ideas On Board
|
||||
* Copyright (C) 2024-2025, Red Hat Inc.
|
||||
*
|
||||
* Color correction matrix
|
||||
*/
|
||||
|
||||
#include "ccm.h"
|
||||
|
||||
#include <libcamera/base/log.h>
|
||||
#include <libcamera/base/utils.h>
|
||||
|
||||
#include <libcamera/control_ids.h>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr unsigned int kTemperatureThreshold = 100;
|
||||
|
||||
}
|
||||
|
||||
namespace libcamera {
|
||||
|
||||
namespace ipa::soft::algorithms {
|
||||
|
||||
LOG_DEFINE_CATEGORY(IPASoftCcm)
|
||||
|
||||
int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData)
|
||||
{
|
||||
int ret = ccm_.readYaml(tuningData["ccms"], "ct", "ccm");
|
||||
if (ret < 0) {
|
||||
LOG(IPASoftCcm, Error)
|
||||
<< "Failed to parse 'ccm' parameter from tuning file.";
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Ccm::prepare(IPAContext &context, const uint32_t frame,
|
||||
IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params)
|
||||
{
|
||||
const unsigned int ct = context.activeState.awb.temperatureK;
|
||||
|
||||
/* Change CCM only on bigger temperature changes. */
|
||||
if (frame > 0 &&
|
||||
utils::abs_diff(ct, lastCt_) < kTemperatureThreshold) {
|
||||
frameContext.ccm.ccm = context.activeState.ccm.ccm;
|
||||
context.activeState.ccm.changed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
lastCt_ = ct;
|
||||
Matrix<float, 3, 3> ccm = ccm_.getInterpolated(ct);
|
||||
|
||||
context.activeState.ccm.ccm = ccm;
|
||||
frameContext.ccm.ccm = ccm;
|
||||
context.activeState.ccm.changed = true;
|
||||
}
|
||||
|
||||
void Ccm::process([[maybe_unused]] IPAContext &context,
|
||||
[[maybe_unused]] const uint32_t frame,
|
||||
IPAFrameContext &frameContext,
|
||||
[[maybe_unused]] const SwIspStats *stats,
|
||||
ControlList &metadata)
|
||||
{
|
||||
metadata.set(controls::ColourCorrectionMatrix, frameContext.ccm.ccm.data());
|
||||
}
|
||||
|
||||
REGISTER_IPA_ALGORITHM(Ccm, "Ccm")
|
||||
|
||||
} /* namespace ipa::soft::algorithms */
|
||||
|
||||
} /* namespace libcamera */
|
43
src/ipa/simple/algorithms/ccm.h
Normal file
43
src/ipa/simple/algorithms/ccm.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Copyright (C) 2024-2025, Red Hat Inc.
|
||||
*
|
||||
* Color correction matrix
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "libcamera/internal/matrix.h"
|
||||
|
||||
#include <libipa/interpolator.h>
|
||||
|
||||
#include "algorithm.h"
|
||||
|
||||
namespace libcamera {
|
||||
|
||||
namespace ipa::soft::algorithms {
|
||||
|
||||
class Ccm : public Algorithm
|
||||
{
|
||||
public:
|
||||
Ccm() = default;
|
||||
~Ccm() = default;
|
||||
|
||||
int init(IPAContext &context, const YamlObject &tuningData) override;
|
||||
void prepare(IPAContext &context,
|
||||
const uint32_t frame,
|
||||
IPAFrameContext &frameContext,
|
||||
DebayerParams *params) override;
|
||||
void process(IPAContext &context, const uint32_t frame,
|
||||
IPAFrameContext &frameContext,
|
||||
const SwIspStats *stats,
|
||||
ControlList &metadata) override;
|
||||
|
||||
private:
|
||||
unsigned int lastCt_;
|
||||
Interpolator<Matrix<float, 3, 3>> ccm_;
|
||||
};
|
||||
|
||||
} /* namespace ipa::soft::algorithms */
|
||||
|
||||
} /* namespace libcamera */
|
|
@ -103,7 +103,7 @@ void Lut::prepare(IPAContext &context,
|
|||
const double div = static_cast<double>(DebayerParams::kRGBLookupSize) /
|
||||
gammaTableSize;
|
||||
/* Apply gamma after gain! */
|
||||
const RGB<double> lutGains = (gains * i / div).min(gammaTableSize - 1);
|
||||
const RGB<float> lutGains = (gains * i / div).min(gammaTableSize - 1);
|
||||
params->red[i] = gammaTable[static_cast<unsigned int>(lutGains.r())];
|
||||
params->green[i] = gammaTable[static_cast<unsigned int>(lutGains.g())];
|
||||
params->blue[i] = gammaTable[static_cast<unsigned int>(lutGains.b())];
|
||||
|
|
|
@ -4,5 +4,6 @@ soft_simple_ipa_algorithms = files([
|
|||
'awb.cpp',
|
||||
'agc.cpp',
|
||||
'blc.cpp',
|
||||
'ccm.cpp',
|
||||
'lut.cpp',
|
||||
])
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <libcamera/controls.h>
|
||||
|
||||
#include "libcamera/internal/matrix.h"
|
||||
#include "libcamera/internal/vector.h"
|
||||
|
||||
#include <libipa/fc_queue.h>
|
||||
|
@ -38,7 +39,7 @@ struct IPAActiveState {
|
|||
} blc;
|
||||
|
||||
struct {
|
||||
RGB<double> gains;
|
||||
RGB<float> gains;
|
||||
unsigned int temperatureK;
|
||||
} awb;
|
||||
|
||||
|
@ -48,6 +49,12 @@ struct IPAActiveState {
|
|||
uint8_t blackLevel;
|
||||
double contrast;
|
||||
} gamma;
|
||||
|
||||
struct {
|
||||
Matrix<float, 3, 3> ccm;
|
||||
bool changed;
|
||||
} ccm;
|
||||
|
||||
struct {
|
||||
/* 0..2 range, 1.0 = normal */
|
||||
std::optional<double> contrast;
|
||||
|
@ -55,6 +62,10 @@ struct IPAActiveState {
|
|||
};
|
||||
|
||||
struct IPAFrameContext : public FrameContext {
|
||||
struct {
|
||||
Matrix<float, 3, 3> ccm;
|
||||
} ccm;
|
||||
|
||||
struct {
|
||||
int32_t exposure;
|
||||
double gain;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue