1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2024, Red Hat Inc.
*
* black level handling
*/
#include "black_level.h"
#include <numeric>
#include <libcamera/base/log.h>
namespace libcamera {
LOG_DEFINE_CATEGORY(IPASoftBL)
namespace ipa::soft {
/**
* \class BlackLevel
* \brief Object providing black point level for software ISP
*
* Black level can be provided in hardware tuning files or, if no tuning file is
* available for the given hardware, guessed automatically, with less accuracy.
* As tuning files are not yet implemented for software ISP, BlackLevel
* currently provides only guessed black levels.
*
* This class serves for tracking black level as a property of the underlying
* hardware, not as means of enhancing a particular scene or image.
*
* The class is supposed to be instantiated for the given camera stream.
* The black level can be retrieved using BlackLevel::get() method. It is
* initially 0 and may change when updated using BlackLevel::update() method.
*/
BlackLevel::BlackLevel()
: blackLevel_(255), blackLevelSet_(false)
{
}
/**
* \brief Return the current black level
*
* \return The black level, in the range from 0 (minimum) to 255 (maximum).
* If the black level couldn't be determined yet, return 0.
*/
uint8_t BlackLevel::get() const
{
return blackLevelSet_ ? blackLevel_ : 0;
}
/**
* \brief Update black level from the provided histogram
* \param[in] yHistogram The histogram to be used for updating black level
*
* The black level is property of the given hardware, not image. It is updated
* only if it has not been yet set or if it is lower than the lowest value seen
* so far.
*/
void BlackLevel::update(SwIspStats::Histogram &yHistogram)
{
/*
* The constant is selected to be "good enough", not overly conservative or
* aggressive. There is no magic about the given value.
*/
constexpr float ignoredPercentage_ = 0.02;
const unsigned int total =
std::accumulate(begin(yHistogram), end(yHistogram), 0);
const unsigned int pixelThreshold = ignoredPercentage_ * total;
const unsigned int histogramRatio = 256 / SwIspStats::kYHistogramSize;
const unsigned int currentBlackIdx = blackLevel_ / histogramRatio;
for (unsigned int i = 0, seen = 0;
i < currentBlackIdx && i < SwIspStats::kYHistogramSize;
i++) {
seen += yHistogram[i];
if (seen >= pixelThreshold) {
blackLevel_ = i * histogramRatio;
blackLevelSet_ = true;
LOG(IPASoftBL, Debug)
<< "Auto-set black level: "
<< i << "/" << SwIspStats::kYHistogramSize
<< " (" << 100 * (seen - yHistogram[i]) / total << "% below, "
<< 100 * seen / total << "% at or below)";
break;
}
};
}
} /* namespace ipa::soft */
} /* namespace libcamera */
|