Spaces:
Sleeping
Sleeping
File size: 2,564 Bytes
f67bbda bb8764b f67bbda bb8764b f67bbda bb8764b f67bbda bb8764b f67bbda bb8764b f67bbda bb8764b f67bbda bb8764b f67bbda |
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 |
import numpy as np
def apply_s_curve_tone_mapping(
x: np.ndarray,
shadow_boost: float = 0.,
highlight_boost: float = 0.,
contrast: float = 0.,
exposure: float = 0.
) -> np.ndarray:
"""
Apply an S-curve tone mapping to input x with given parameters.
Parameters:
x : array-like
Input values in the range [0, 1].
shadow_boost : float
Shadow boost parameter. Positive values increase the steepness in shadows.
highlight_boost : float
Highlight boost parameter. Positive values increase the steepness in highlights.
contrast : float
Contrast parameter. Positive values increase the steepness at midtones.
exposure : float
Exposure adjustment parameter. When exposure=0, 0.5 maps to 0.5.
Exposure defines the mapping of 0.5 to 0.5 * (2 ** exposure).
Returns:
y : array-like
Tone-mapped output values in the range [0, 1].
"""
# Compute the midtone mapped value based on exposure
midtone_mapped_value = 0.5 * (2 ** exposure)
midtone_mapped_value = np.clip(midtone_mapped_value, 0, 1)
# Define the slopes (derivatives) at the three key points
s0 = 1 + shadow_boost # Slope at x = 0 (shadows)
s1 = 1 + contrast # Slope at x = 0.5 (midtone)
s2 = 1 + highlight_boost # Slope at x = 1 (highlights)
# Initialize the output array
y = np.zeros_like(x)
# Segment 1: x in [0, 0.5]
idx1 = x <= 0.5
x0, x1 = 0.0, 0.5
y0, y1 = 0.0, midtone_mapped_value
m0, m1 = s0, s1
delta_x = x1 - x0
t = (x[idx1] - x0) / delta_x # Normalize x to parameter t in [0, 1]
# Hermite basis functions
h00 = 2 * t ** 3 - 3 * t ** 2 + 1
h10 = t ** 3 - 2 * t ** 2 + t
h01 = -2 * t ** 3 + 3 * t ** 2
h11 = t ** 3 - t ** 2
# Calculate the spline for the first segment
y[idx1] = (h00 * y0 + h10 * m0 * delta_x + h01 * y1 + h11 * m1 * delta_x)
# Segment 2: x in (0.5, 1]
idx2 = x > 0.5
x0, x1 = 0.5, 1.0
y0, y1 = midtone_mapped_value, 1.0
m0, m1 = s1, s2
delta_x = x1 - x0
t = (x[idx2] - x0) / delta_x # Normalize x to parameter t in [0, 1]
# Hermite basis functions for the second segment
h00 = 2 * t ** 3 - 3 * t ** 2 + 1
h10 = t ** 3 - 2 * t ** 2 + t
h01 = -2 * t ** 3 + 3 * t ** 2
h11 = t ** 3 - t ** 2
# Calculate the spline for the second segment
y[idx2] = (h00 * y0 + h10 * m0 * delta_x + h01 * y1 + h11 * m1 * delta_x)
# Ensure the output is within [0, 1]
y = np.clip(y, 0, 1)
return y
|