lsst.pipe.tasks
g2c8cee2ce7+363d2db7ea
Toggle main menu visibility
Loading...
Searching...
No Matches
python
lsst
pipe
tasks
prettyPictureMaker
_functors
_lum_scale.py
Go to the documentation of this file.
1
# This file is part of pipe_tasks.
2
#
3
# Developed for the LSST Data Management System.
4
# This product includes software developed by the LSST Project
5
# (https://www.lsst.org).
6
# See the COPYRIGHT file at the top-level directory of this distribution
7
# for details of code ownership.
8
#
9
# This program is free software: you can redistribute it and/or modify
10
# it under the terms of the GNU General Public License as published by
11
# the Free Software Foundation, either version 3 of the License, or
12
# (at your option) any later version.
13
#
14
# This program is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
# GNU General Public License for more details.
18
#
19
# You should have received a copy of the GNU General Public License
20
# along with this program. If not, see <https://www.gnu.org/licenses/>.
21
22
from
__future__
import
annotations
23
24
__all__ = (
"LumCompressor"
,)
25
26
import
skimage
27
import
numpy
as
np
28
import
logging
29
30
31
from
lsst.pipe.tasks.prettyPictureMaker.types
import
FloatImagePlane
32
from
lsst.pex.config.configurableActions
import
ConfigurableAction
33
from
lsst.pex.config
import
Field, ListField
34
from
lsst.rubinoxide
import
rgb
35
36
from
.._equalizers
import
contrast_equalizer, tone_equalizer
37
38
logger = logging.getLogger(__name__)
39
40
41
class
LumCompressor
(ConfigurableAction):
42
"""Compress and enhance luminance using multi-stage processing.
43
44
This class implements luminance compression for RGB image generation using
45
a multi-stage algorithm that includes:
46
47
- Asinh stretching for non-linear brightness mapping
48
- Linear contrast manipulation
49
- Midtone adjustment
50
- Optional Gaussian denoising
51
- Optional contrast equalization
52
- Optional tone adjustment
53
54
The configuration fields control the parameters for each stage of the
55
processing pipeline.
56
"""
57
58
stretch = Field[float](doc=
"The stretch of the luminance in asinh"
, default=400)
59
max = Field[float](doc=
"The maximum allowed luminance on a 0 to 1 scale"
, default=0.85)
60
floor = Field[float](doc=
"A value in nJy that is used to map luminances to a very dark gray"
, default=0.0)
61
Q = Field[float](
62
doc=
"softening parameter"
,
63
default=0.7,
64
deprecated=
"This field is no longer used and will be removed after v31."
,
65
)
66
highlight = Field[float](
67
doc=
"The value of highlights in scaling factor applied to post asinh streaching"
, default=1.0
68
)
69
shadow = Field[float](
70
doc=
"The value of shadows in scaling factor applied to post asinh streaching"
, default=0.0
71
)
72
midtone = Field[float](
73
doc=
"The value of midtone in scaling factor applied to post asinh streaching"
, default=0.5
74
)
75
equalizerLevels = ListField[float](
76
doc=(
77
"A list of factors to modify the constrast in a scale-dependent way. "
78
"One coefficient for each spatial scale, starting from the largest. "
79
"Values large than 1 increase contrast, while less than 1 decreases. "
80
"This adjustment is multiplicative. "
81
"Only scales upto and including the largest to be modified need specified, "
82
"i.e. [1.1,0.9] modifies the first two [1.1,1,0.9] modifies the first three."
83
),
84
optional=
True
,
85
)
86
toneAdjustment = ListField[float](
87
doc=(
88
"A list of length 10 that adjusts the brightness of the image ranging "
89
"from dark regions to light. These 10 values represent control points along "
90
"the lumanance interval 0-1, but the actual adjustments made are continuous "
91
"and are calculated from these control points."
92
),
93
length=10,
94
optional=
True
,
95
)
96
toneWidth = Field[float](
97
doc=(
98
"This parameters controls how each tone control point affect the adjustment "
99
"of the values in between. Increase the value to have a more continuous "
100
"change between control points, decrease to make the control sharper. Value "
101
"must be greater than zero."
102
),
103
default=0.07,
104
)
105
doDenoise = Field[bool](doc=
"Denoise the luminance image"
, default=
False
)
106
107
def
__call__
(self, intensities: FloatImagePlane) -> FloatImagePlane:
108
"""Compress and enhance luminance using multi-stage processing.
109
110
This method applies the configured luminance compression algorithm to
111
the input image. The processing pipeline includes optional denoising,
112
asinh stretching, linear contrast manipulation, midtone adjustment,
113
contrast equalization, and tone adjustment.
114
115
Parameters
116
----------
117
intensities : `FloatImagePlane`
118
Input image with pixel intensities. This FloatImagePlane should
119
contain the luminance data to be compressed.
120
121
Returns
122
-------
123
result : `FloatImagePlane`
124
The processed image with luminance compression applied. Values
125
are clipped to the range [0, 1].
126
127
Notes
128
-----
129
The processing pipeline consists of the following stages:
130
131
1. Optional wavelet denoising if doDenoise is True
132
2. Asinh stretching with configurable stretch parameter
133
3. Linear contrast adjustment using highlight, shadow parameters
134
4. Midtone adjustment using midtone parameter
135
5. Optional contrast equalization if equalizerLevels is configured
136
6. Optional tone adjustment if toneAdjustment is configured
137
7. Final clipping to [0, 1] range
138
139
The configuration fields (stretch, highlight, shadow, midtone,
140
equalizerLevels, toneAdjustment, toneWidth) control the behavior
141
of each processing stage.
142
"""
143
if
self.
doDenoise
:
144
intensities = skimage.restoration.denoise_wavelet(intensities)
145
146
# Scale the values with linear manipulation for contrast
147
intensities = abs(intensities)
148
nj_to_lum = rgb.RGB_to_Oklab(
149
np.array([[[self.
floor
, self.
floor
, self.
floor
]]], dtype=float), (0.28, 0.28)
150
)[0, 0, 0]
151
top = np.arcsinh(self.
stretch
)
152
bottom = (np.arcsinh(nj_to_lum * self.
stretch
) - 0.2 * top) / 0.8
153
intensities = (np.arcsinh(intensities * self.
stretch
) - bottom) / (top - bottom)
154
logger.debug(
"arcsinh max %.4f"
, intensities.max())
155
intensities = np.clip(intensities, 0, 1)
156
intensities = (intensities - self.
shadow
) / ((self.
highlight
) - self.
shadow
)
157
logger.debug(
"post lin stretch max %.4f"
, intensities.max())
158
intensities = ((self.
midtone
- 1) * intensities) / (
159
((2 * self.
midtone
- 1) * intensities) - self.
midtone
160
)
161
logger.debug(
"midtone adjustment max %.4f"
, intensities.max())
162
intensities = np.clip(intensities, 0.0, self.
max
)
163
164
if
self.
equalizerLevels
is
not
None
:
165
intensities = contrast_equalizer(intensities, self.
equalizerLevels
)
166
logger.debug(
"equalizer max %.4f"
, intensities.max())
167
168
if
self.
toneAdjustment
is
not
None
:
169
intensities = np.clip(intensities, 0, self.
max
)
170
intensities = tone_equalizer(intensities, self.
toneAdjustment
, self.
toneWidth
, 10, 5)
171
172
intensities = np.clip(intensities, 0, 1)
173
174
return
intensities
lsst::pex::config::configurableActions
lsst.pipe.tasks.prettyPictureMaker._functors._lum_scale.LumCompressor
Definition
_lum_scale.py:41
lsst.pipe.tasks.prettyPictureMaker._functors._lum_scale.LumCompressor.floor
floor
Definition
_lum_scale.py:60
lsst.pipe.tasks.prettyPictureMaker._functors._lum_scale.LumCompressor.toneAdjustment
toneAdjustment
Definition
_lum_scale.py:86
lsst.pipe.tasks.prettyPictureMaker._functors._lum_scale.LumCompressor.equalizerLevels
equalizerLevels
Definition
_lum_scale.py:75
lsst.pipe.tasks.prettyPictureMaker._functors._lum_scale.LumCompressor.highlight
highlight
Definition
_lum_scale.py:66
lsst.pipe.tasks.prettyPictureMaker._functors._lum_scale.LumCompressor.doDenoise
doDenoise
Definition
_lum_scale.py:105
lsst.pipe.tasks.prettyPictureMaker._functors._lum_scale.LumCompressor.midtone
midtone
Definition
_lum_scale.py:72
lsst.pipe.tasks.prettyPictureMaker._functors._lum_scale.LumCompressor.__call__
FloatImagePlane __call__(self, FloatImagePlane intensities)
Definition
_lum_scale.py:107
lsst.pipe.tasks.prettyPictureMaker._functors._lum_scale.LumCompressor.max
max
Definition
_lum_scale.py:59
lsst.pipe.tasks.prettyPictureMaker._functors._lum_scale.LumCompressor.shadow
shadow
Definition
_lum_scale.py:69
lsst.pipe.tasks.prettyPictureMaker._functors._lum_scale.LumCompressor.toneWidth
toneWidth
Definition
_lum_scale.py:96
lsst.pipe.tasks.prettyPictureMaker._functors._lum_scale.LumCompressor.stretch
stretch
Definition
_lum_scale.py:58
lsst::pex::config
lsst.pipe.tasks.prettyPictureMaker.types
Definition
types.py:1
Generated on
for lsst.pipe.tasks by
1.17.0