Spaces:
Sleeping
Sleeping
Commit ·
2376099
1
Parent(s): 2e80d4c
Fix color balance logic for Sentinel-2 TIFFs by using global instead of per-channel percentile stretching
Browse files- inference/geotiff.py +10 -46
inference/geotiff.py
CHANGED
|
@@ -88,55 +88,19 @@ def normalize_rgb(
|
|
| 88 |
):
|
| 89 |
"""
|
| 90 |
Convert Sentinel-2 reflectance/DN values to uint8 RGB.
|
| 91 |
-
|
| 92 |
-
Percentile normalization is performed independently
|
| 93 |
-
for each channel.
|
| 94 |
"""
|
| 95 |
-
|
| 96 |
rgb = rgb.astype(np.float32)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
-
|
| 99 |
-
rgb,
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
for channel in range(3):
|
| 104 |
-
|
| 105 |
-
band = rgb[:, :, channel]
|
| 106 |
-
|
| 107 |
-
low = np.percentile(
|
| 108 |
-
band,
|
| 109 |
-
lower_percentile
|
| 110 |
-
)
|
| 111 |
-
|
| 112 |
-
high = np.percentile(
|
| 113 |
-
band,
|
| 114 |
-
upper_percentile
|
| 115 |
-
)
|
| 116 |
-
|
| 117 |
-
if high <= low:
|
| 118 |
-
result[:, :, channel] = np.clip(
|
| 119 |
-
band,
|
| 120 |
-
0,
|
| 121 |
-
255
|
| 122 |
-
).astype(np.uint8)
|
| 123 |
-
|
| 124 |
-
else:
|
| 125 |
-
|
| 126 |
-
normalized = (
|
| 127 |
-
(band - low) /
|
| 128 |
-
(high - low)
|
| 129 |
-
)
|
| 130 |
-
|
| 131 |
-
normalized = np.clip(
|
| 132 |
-
normalized,
|
| 133 |
-
0,
|
| 134 |
-
1
|
| 135 |
-
)
|
| 136 |
-
|
| 137 |
-
result[:, :, channel] = (
|
| 138 |
-
normalized * 255
|
| 139 |
-
).astype(np.uint8)
|
| 140 |
|
| 141 |
return result
|
| 142 |
|
|
|
|
| 88 |
):
|
| 89 |
"""
|
| 90 |
Convert Sentinel-2 reflectance/DN values to uint8 RGB.
|
| 91 |
+
Global percentile normalization preserves color balance.
|
|
|
|
|
|
|
| 92 |
"""
|
|
|
|
| 93 |
rgb = rgb.astype(np.float32)
|
| 94 |
+
|
| 95 |
+
# Calculate global percentiles across all channels to preserve color balance
|
| 96 |
+
low = np.percentile(rgb, lower_percentile)
|
| 97 |
+
high = np.percentile(rgb, upper_percentile)
|
| 98 |
|
| 99 |
+
if high <= low:
|
| 100 |
+
result = np.clip(rgb, 0, 255).astype(np.uint8)
|
| 101 |
+
else:
|
| 102 |
+
normalized = (rgb - low) / (high - low)
|
| 103 |
+
result = (np.clip(normalized, 0, 1) * 255).astype(np.uint8)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
|
| 105 |
return result
|
| 106 |
|