Skip to content

Commit e6db90d

Browse files
author
Michael Kunz
committed
libcamera: Adding LensShadingCorrection maps and ToneCurve to controls metadata
Having the LensShadingCorrection maps and ToneCurves available in frame metadata allows creating a DNG file with all necessary information so that the DNG matches the JPEG image without colour casts. I opened a PR in raspberrypi/rpicam-apps (raspberrypi/rpicam-apps#928) improving the colour accuracy of said DNG files created by these apps. The information needed is currently not provided by libcamera in the frame metadata. This patch intends to add LensShadingCorrection maps and ToneCurve to the controls metadata in libcamera, so that DNG files can be written with correct colours. Signed-off-by: Michael Kunz <mkunz@articimaging.eu>
1 parent 6c1dd9d commit e6db90d

5 files changed

Lines changed: 91 additions & 4 deletions

File tree

src/ipa/rpi/common/ipa_base.cpp

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,25 @@
1212

1313
#include <libcamera/base/log.h>
1414
#include <libcamera/base/span.h>
15+
1516
#include <libcamera/control_ids.h>
1617
#include <libcamera/property_ids.h>
1718

1819
#include "controller/af_algorithm.h"
1920
#include "controller/af_status.h"
2021
#include "controller/agc_algorithm.h"
22+
#include "controller/alsc_status.h"
2123
#include "controller/awb_algorithm.h"
2224
#include "controller/awb_status.h"
2325
#include "controller/black_level_status.h"
2426
#include "controller/ccm_algorithm.h"
2527
#include "controller/ccm_status.h"
2628
#include "controller/contrast_algorithm.h"
29+
#include "controller/contrast_status.h"
2730
#include "controller/denoise_algorithm.h"
2831
#include "controller/hdr_algorithm.h"
2932
#include "controller/lux_status.h"
33+
#include "controller/noise_status.h"
3034
#include "controller/sharpen_algorithm.h"
3135
#include "controller/statistics.h"
3236
#include "controller/sync_algorithm.h"
@@ -82,6 +86,7 @@ const ControlInfoMap::Map ipaControls{
8286
static_cast<int64_t>(defaultMaxFrameDuration.get<std::micro>()),
8387
Span<const int64_t, 2>{ { static_cast<int64_t>(defaultMinFrameDuration.get<std::micro>()),
8488
static_cast<int64_t>(defaultMinFrameDuration.get<std::micro>()) } }) },
89+
{ &controls::EnableLensShadingCorrectionMapOutput, ControlInfo(false, true, false) },
8590
{ &controls::draft::NoiseReductionMode, ControlInfo(controls::draft::NoiseReductionModeValues) },
8691
{ &controls::rpi::StatsOutputEnable, ControlInfo(false, true, false) },
8792
{ &controls::rpi::CnnEnableInputTensor, ControlInfo(false, true, false) },
@@ -129,7 +134,7 @@ LOG_DEFINE_CATEGORY(IPARPI)
129134
namespace ipa::RPi {
130135

131136
IpaBase::IpaBase()
132-
: controller_(), frameLengths_(FrameLengthsQueueSize, 0s), statsMetadataOutput_(false),
137+
: controller_(), frameLengths_(FrameLengthsQueueSize, 0s), lscMapsOutput_(false), statsMetadataOutput_(false),
133138
stitchSwapBuffers_(false), frameCount_(0), mistrustCount_(0), lastRunTimestamp_(0),
134139
firstStart_(true), flickerState_({ 0, 0s }), cnnEnableInputTensor_(false), awbEnabled_(true)
135140
{
@@ -245,7 +250,6 @@ int32_t IpaBase::configure(const IPACameraSensorInfo &sensorInfo, const ConfigPa
245250
agcStatus.exposureTime = defaultExposureTime;
246251
agcStatus.analogueGain = defaultAnalogueGain;
247252
applyAGC(&agcStatus, ctrls);
248-
249253
}
250254

251255
result->sensorControls = std::move(ctrls);
@@ -795,8 +799,8 @@ static const std::map<int32_t, std::string> HdrModeTable = {
795799

796800
void IpaBase::applyControls(const ControlList &controls)
797801
{
798-
using RPiController::AgcAlgorithm;
799802
using RPiController::AfAlgorithm;
803+
using RPiController::AgcAlgorithm;
800804
using RPiController::ContrastAlgorithm;
801805
using RPiController::DenoiseAlgorithm;
802806
using RPiController::HdrAlgorithm;
@@ -1478,6 +1482,10 @@ void IpaBase::applyControls(const ControlList &controls)
14781482
break;
14791483
}
14801484

1485+
case controls::ENABLE_LENS_SHADING_CORRECTION_MAP_OUTPUT:
1486+
lscMapsOutput_ = ctrl.second.get<bool>();
1487+
break;
1488+
14811489
case controls::rpi::STATS_OUTPUT_ENABLE:
14821490
statsMetadataOutput_ = ctrl.second.get<bool>();
14831491
break;
@@ -1762,6 +1770,43 @@ void IpaBase::reportMetadata(unsigned int ipaContext)
17621770
static_cast<int32_t>(kpiInfo->dspRuntime) });
17631771
}
17641772

1773+
NoiseStatus *noiseStatus = rpiMetadata.getLocked<NoiseStatus>("noise.status");
1774+
if (noiseStatus) {
1775+
float noiseProfile[] = { static_cast<float>(noiseStatus->noiseSlope),
1776+
static_cast<float>(noiseStatus->noiseConstant) };
1777+
1778+
libcameraMetadata_.set(controls::NoiseProfile, noiseProfile);
1779+
}
1780+
1781+
ContrastStatus *contrastStatus = rpiMetadata.getLocked<ContrastStatus>("contrast.status");
1782+
if (contrastStatus && contrastStatus->gammaCurve.size() > 0) {
1783+
std::vector<float> contrast;
1784+
contrast.reserve(contrastStatus->gammaCurve.size() * 2);
1785+
1786+
contrastStatus->gammaCurve.map([&](double x, double y) {
1787+
contrast.emplace_back(static_cast<float>(x));
1788+
contrast.emplace_back(static_cast<float>(y));
1789+
});
1790+
libcameraMetadata_.set(controls::ToneCurve, contrast);
1791+
}
1792+
1793+
if (lscMapsOutput_) {
1794+
AlscStatus *alscStatus = rpiMetadata.getLocked<AlscStatus>("alsc.status");
1795+
if (alscStatus) {
1796+
uint32_t elements = alscStatus->cols * alscStatus->rows;
1797+
std::vector<float> map(3 * elements);
1798+
1799+
std::copy(alscStatus->r.begin(), alscStatus->r.end(), map.begin() + 0 * elements);
1800+
std::copy(alscStatus->g.begin(), alscStatus->g.end(), map.begin() + 1 * elements);
1801+
std::copy(alscStatus->b.begin(), alscStatus->b.end(), map.begin() + 2 * elements);
1802+
1803+
uint32_t sizeTable[] = { 3, alscStatus->cols, alscStatus->rows };
1804+
libcameraMetadata_.set(controls::LensShadingCorrectionMaps, map);
1805+
libcameraMetadata_.set(controls::LensShadingCorrectionMapSize, sizeTable);
1806+
libcameraMetadata_.set(controls::EnableLensShadingCorrectionMapOutput, true);
1807+
}
1808+
}
1809+
17651810
metadataReady.emit(libcameraMetadata_);
17661811
}
17671812

src/ipa/rpi/common/ipa_base.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class IpaBase : public IPARPiInterface
6868
std::deque<utils::Duration> frameLengths_;
6969
utils::Duration lastTimeout_;
7070
ControlList libcameraMetadata_;
71+
bool lscMapsOutput_;
7172
bool statsMetadataOutput_;
7273

7374
/* Remember the HDR status after a mode switch. */

src/ipa/rpi/common/meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ rpi_ipa_common_sources = files([
55
])
66

77
rpi_ipa_common_includes = [
8-
include_directories('..'),
8+
include_directories('..','../..'),
99
]
1010

1111
rpi_ipa_common_deps = [

src/ipa/rpi/controller/rpi/alsc.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,9 @@ void Alsc::prepare(Metadata *imageMetadata)
409409
status.r = prevSyncResults_[0].data();
410410
status.g = prevSyncResults_[1].data();
411411
status.b = prevSyncResults_[2].data();
412+
status.cols = config_.tableSize.width;
413+
status.rows = config_.tableSize.height;
414+
412415
imageMetadata->set("alsc.status", status);
413416
/*
414417
* Put the results in the global metadata as well. This will be used by

src/libcamera/control_ids_core.yaml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,4 +1374,42 @@ controls:
13741374
The nominal range is [-180, 180], where 0° leaves hues unchanged and the
13751375
range wraps around continuously, with 180° == -180°.
13761376
1377+
- EnableLensShadingCorrectionMapOutput:
1378+
type: bool
1379+
direction: inout
1380+
description: |
1381+
Indicates if the lens shading correction maps should be set in frame-
1382+
metadata for each frame. Returns true if tables are successfully set.
1383+
1384+
- LensShadingCorrectionMaps:
1385+
type: float
1386+
direction: out
1387+
description: |
1388+
A map giving the lens shading correction factors. Dimesnions of the
1389+
returned table is [number of channels, sizeX, sizeY] (planar tables)
1390+
size: [n]
1391+
1392+
- LensShadingCorrectionMapSize:
1393+
type: uint32_t
1394+
direction: out
1395+
description: |
1396+
The number of channels/maps and the size of the lens shading correction
1397+
maps in pixels. E.g. [3, 32, 32]
1398+
size: [3]
1399+
1400+
- ToneCurve:
1401+
type: float
1402+
direction: out
1403+
description: |
1404+
A profile tone curve to apply on linear RGB - as it seems it has the sRGB
1405+
gamma curve baked in.
1406+
size: [n]
1407+
1408+
- NoiseProfile:
1409+
type: float
1410+
direction: out
1411+
description: |
1412+
The noise profile [Scale, Offset].
1413+
size: [2]
1414+
13771415
...

0 commit comments

Comments
 (0)