Skip to content

Commit

Permalink
Histogram equalization should use HSV color space
Browse files Browse the repository at this point in the history
Fix the previous error in histogram equalization, where I did each
channel separately. This makes no sense. First convert to HSV and then
equalize only the V values. Much better results without that red shift
to the results.
  • Loading branch information
leouieda committed Sep 26, 2023
1 parent 1eb013c commit 24baf90
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 19 deletions.
8 changes: 6 additions & 2 deletions doc/equalize-histogram.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,12 @@ in the cloud-free regions:

But, as we mentioned earlier, this means we don't get to see details of the
clouds anymore. For a more pleasing image, we can use the adaptive histogram
equalization in :func:`xlandsat.equalize_histogram`. It helps to do a bit of
contrast stretching first, but to a lesser degree than we did previously.
equalization in :func:`xlandsat.equalize_histogram`.

.. tip::

It can be helpful to do a bit of contrast stretching first, but to a lesser
degree than we did previously.

.. jupyter-execute::

Expand Down
44 changes: 27 additions & 17 deletions xlandsat/_enhancement.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,28 @@
"""
Operations to enhance composites. Basically wrappers for skimage.exposure.
"""
import skimage.color
import skimage.exposure


def equalize_histogram(composite, kernel_size=None, clip_limit=0.01):
"""
Adaptive histogram equalization on each band of a composite
Adaptive histogram equalization for a composite
Use this function to enhance the contrast of a composite when there are a
few very dark or very light patches that dominate the color range. Use this
instead of rescaling intensity (contrast stretching) to try to preserve
some detail in the light/dark patches.
This is a wrapper around :func:`skimage.exposure.equalize_adapthist`.
.. tip::
Results can be very bad if there are missing values in the scene. Use
:func:`xlandsat.interpolate_missing` first if that is the case.
If the composite has an alpha channel (transparency), it will be copied to
the output intact.
.. warning::
Results can be very bad if there are missing values (NaNs) in the
composite. Use :func:`xlandsat.interpolate_missing` on the scene first
(before creating the composite) if that is the case.
Parameters
----------
composite : :class:`xarray.DataArray`
Expand All @@ -42,15 +42,25 @@ def equalize_histogram(composite, kernel_size=None, clip_limit=0.01):
equalized_composite : :class:`xarray.DataArray`
The composite after equalization, scaled back to unsigned 8-bit integer
range.
Notes
-----
This function first converts the composite from the RGB color space to the
`HSV color space <https://en.wikipedia.org/wiki/HSL_and_HSV>`__. Then, it
applies :func:`skimage.exposure.equalize_adapthist` to the values
(intensity) channel. Finally, the composite is converted back into the RGB
color space.
"""
result = composite.copy(deep=True)
for i in range(3):
result.values[:, :, i] = skimage.exposure.rescale_intensity(
skimage.exposure.equalize_adapthist(
result.values[:, :, i],
kernel_size=kernel_size,
clip_limit=clip_limit,
),
out_range="uint8",
)
hsv = skimage.color.rgb2hsv(result.values[:, :, :3])
hsv[:, :, 2] = skimage.exposure.equalize_adapthist(

Check warning on line 57 in xlandsat/_enhancement.py

View check run for this annotation

Codecov / codecov/patch

xlandsat/_enhancement.py#L56-L57

Added lines #L56 - L57 were not covered by tests
hsv[:, :, 2],
kernel_size=kernel_size,
clip_limit=clip_limit,
)
result.values[:, :, :3] = skimage.exposure.rescale_intensity(

Check warning on line 62 in xlandsat/_enhancement.py

View check run for this annotation

Codecov / codecov/patch

xlandsat/_enhancement.py#L62

Added line #L62 was not covered by tests
skimage.color.hsv2rgb(hsv),
out_range="uint8",
)
return result

0 comments on commit 24baf90

Please sign in to comment.