Unverified Commit 105fe550 authored by Jiazhen Wang's avatar Jiazhen Wang Committed by GitHub
Browse files

[Feature] Add adjust_hue (#1628)



* [Impl] impl adjust hue

* Update docstring

* Fix docstring

* add copyright
Co-authored-by: default avatarZaida Zhou <58739961+zhouzaida@users.noreply.github.com>
parent 1dbb5d36
......@@ -9,10 +9,10 @@ from .geometric import (cutout, imcrop, imflip, imflip_, impad,
from .io import imfrombytes, imread, imwrite, supported_backends, use_backend
from .misc import tensor2imgs
from .photometric import (adjust_brightness, adjust_color, adjust_contrast,
adjust_lighting, adjust_sharpness, auto_contrast,
clahe, imdenormalize, imequalize, iminvert,
imnormalize, imnormalize_, lut_transform, posterize,
solarize)
adjust_hue, adjust_lighting, adjust_sharpness,
auto_contrast, clahe, imdenormalize, imequalize,
iminvert, imnormalize, imnormalize_, lut_transform,
posterize, solarize)
__all__ = [
'bgr2gray', 'bgr2hls', 'bgr2hsv', 'bgr2rgb', 'gray2bgr', 'gray2rgb',
......@@ -24,5 +24,6 @@ __all__ = [
'solarize', 'rgb2ycbcr', 'bgr2ycbcr', 'ycbcr2rgb', 'ycbcr2bgr',
'tensor2imgs', 'imshear', 'imtranslate', 'adjust_color', 'imequalize',
'adjust_brightness', 'adjust_contrast', 'lut_transform', 'clahe',
'adjust_sharpness', 'auto_contrast', 'cutout', 'adjust_lighting'
'adjust_sharpness', 'auto_contrast', 'cutout', 'adjust_lighting',
'adjust_hue'
]
......@@ -426,3 +426,46 @@ def clahe(img, clip_limit=40.0, tile_grid_size=(8, 8)):
clahe = cv2.createCLAHE(clip_limit, tile_grid_size)
return clahe.apply(np.array(img, dtype=np.uint8))
def adjust_hue(img: np.ndarray, hue_factor: float) -> np.ndarray:
"""Adjust hue of an image.
The image hue is adjusted by converting the image to HSV and cyclically
shifting the intensities in the hue channel (H). The image is then
converted back to original image mode.
`hue_factor` is the amount of shift in H channel and must be in the
interval `[-0.5, 0.5]`.
Modified from
https://github.com/pytorch/vision/blob/main/torchvision/
transforms/functional.py
Args:
img (ndarray): Image to be adjusted.
hue_factor (float): How much to shift the hue channel. Should be in
[-0.5, 0.5]. 0.5 and -0.5 give complete reversal of hue channel in
HSV space in positive and negative direction respectively.
0 means no shift. Therefore, both -0.5 and 0.5 will give an image
with complementary colors while 0 gives the original image.
Returns:
ndarray: Hue adjusted image.
"""
if not (-0.5 <= hue_factor <= 0.5):
raise ValueError(f'hue_factor:{hue_factor} is not in [-0.5, 0.5].')
if not (isinstance(img, np.ndarray) and (img.ndim in {2, 3})):
raise TypeError('img should be ndarray with dim=[2 or 3].')
dtype = img.dtype
img = img.astype(np.uint8)
hsv_img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV_FULL)
h, s, v = cv2.split(hsv_img)
h = h.astype(np.uint8)
# uint8 addition take cares of rotation across boundaries
with np.errstate(over='ignore'):
h += np.uint8(hue_factor * 255)
hsv_img = cv2.merge([h, s, v])
return cv2.cvtColor(hsv_img, cv2.COLOR_HSV2RGB_FULL).astype(dtype)
......@@ -378,3 +378,37 @@ class TestPhotometric:
assert np.allclose(img, img_std)
assert id(img) != id(self.img[:, :, i])
assert id(img_std) != id(self.img[:, :, i])
def test_adjust_hue(self):
from PIL import Image
def _adjust_hue(img, hue_factor):
input_mode = img.mode
if input_mode in {'L', '1', 'I', 'F'}:
return img
h, s, v = img.convert('HSV').split()
np_h = np.array(h, dtype=np.uint8)
# uint8 addition take cares of rotation across boundaries
with np.errstate(over='ignore'):
np_h += np.uint8(hue_factor * 255)
h = Image.fromarray(np_h, 'L')
img = Image.merge('HSV', (h, s, v)).convert(input_mode)
return img
pil_img = Image.fromarray(self.img)
# test case with img is not ndarray
with pytest.raises(TypeError):
mmcv.adjust_hue(pil_img, hue_factor=0.0)
# test case with hue_factor > 0.5 or hue_factor < -0.5
with pytest.raises(ValueError):
mmcv.adjust_hue(self.img, hue_factor=-0.6)
with pytest.raises(ValueError):
mmcv.adjust_hue(self.img, hue_factor=0.6)
for i in np.arange(-0.5, 0.5, 0.2):
pil_res = _adjust_hue(pil_img, hue_factor=i)
pil_res = np.array(pil_res)
cv2_res = mmcv.adjust_hue(self.img, hue_factor=i)
assert np.allclose(pil_res, cv2_res, atol=10.0)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment