Skip to content

Commit

Permalink
hue
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanklut committed Apr 22, 2024
1 parent 440ddbb commit adc75c5
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 16 deletions.
5 changes: 5 additions & 0 deletions configs/extra_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@
_C.INPUT.SATURATION.MIN_INTENSITY = 0.5
_C.INPUT.SATURATION.MAX_INTENSITY = 1.5

_C.INPUT.HUE = CN()
_C.INPUT.HUE.PROBABILITY = 0.5
_C.INPUT.HUE.MIN_DELTA = -0.5
_C.INPUT.HUE.MAX_DELTA = 0.5

_C.INPUT.GAUSSIAN_FILTER = CN()
_C.INPUT.GAUSSIAN_FILTER.PROBABILITY = 0.5
_C.INPUT.GAUSSIAN_FILTER.MIN_SIGMA = 0.0
Expand Down
68 changes: 52 additions & 16 deletions datasets/augmentations.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
GaussianFilterTransform,
GrayscaleTransform,
HFlipTransform,
HueTransform,
JPEGCompressionTransform,
OrientationTransform,
PadTransform,
Expand Down Expand Up @@ -865,14 +866,39 @@ def get_transform(self, image):
return BlendTransform(src_image=np.asarray(0).astype(np.float32), src_weight=1 - w, dst_weight=w)


class RandomHue(Augmentation):
"""
Randomly transforms image hue
"""

def __init__(self, hue_delta_min: float = -0.5, hue_delta_max: float = 0.5, image_format="RGB") -> None:
"""
Initialize the RandomHue class.
Args:
hue_delta_min (float, optional): lowest hue change. Defaults to -0.5.
hue_delta_max (float, optional): highest hue change. Defaults to 0.5.
image_format (str, optional): Color formatting. Defaults to "RGB".
"""
super().__init__()
self.hue_delta_min = hue_delta_min
self.hue_delta_max = hue_delta_max

self.image_format = image_format

def get_transform(self, image: np.ndarray) -> T.Transform:
hue_delta = np.random.uniform(self.hue_delta_min, self.hue_delta_max)
return HueTransform(hue_delta, self.image_format)


class RandomOrientation(Augmentation):
"""
Apply a random orientation to the image
"""

def __init__(self, orientation_percentages: Optional[list[float | int]] = None) -> None:
"""
Initialize the Augmentations class.
Initialize the RandomOrientation class.
Args:
orientation_percentages (Optional[list[float | int]]): A list of orientation percentages.
Expand Down Expand Up @@ -1239,14 +1265,6 @@ def build_augmentation(cfg: CfgNode, mode: str = "train") -> list[T.Augmentation
)

# Color augments
augmentation.append(
RandomApply(
Grayscale(
image_format=cfg.INPUT.FORMAT,
),
prob=cfg.INPUT.GRAYSCALE.PROBABILITY,
)
)

augmentation.append(
RandomApply(
Expand Down Expand Up @@ -1275,6 +1293,15 @@ def build_augmentation(cfg: CfgNode, mode: str = "train") -> list[T.Augmentation
prob=cfg.INPUT.SATURATION.PROBABILITY,
)
)
augmentation.append(
RandomApply(
RandomHue(
hue_delta_min=cfg.INPUT.HUE.MIN_DELTA,
hue_delta_max=cfg.INPUT.HUE.MAX_DELTA,
),
prob=cfg.INPUT.HUE.PROBABILITY,
)
)

augmentation.append(
RandomApply(
Expand All @@ -1288,20 +1315,29 @@ def build_augmentation(cfg: CfgNode, mode: str = "train") -> list[T.Augmentation

augmentation.append(
RandomApply(
Invert(
max_value=cfg.INPUT.INVERT.MAX_VALUE,
RandomJPEGCompression(
min_quality=cfg.INPUT.JPEG_COMPRESSION.MIN_QUALITY,
max_quality=cfg.INPUT.JPEG_COMPRESSION.MAX_QUALITY,
),
prob=cfg.INPUT.INVERT.PROBABILITY,
prob=cfg.INPUT.JPEG_COMPRESSION.PROBABILITY,
)
)

augmentation.append(
RandomApply(
RandomJPEGCompression(
min_quality=cfg.INPUT.JPEG_COMPRESSION.MIN_QUALITY,
max_quality=cfg.INPUT.JPEG_COMPRESSION.MAX_QUALITY,
Grayscale(
image_format=cfg.INPUT.FORMAT,
),
prob=cfg.INPUT.JPEG_COMPRESSION.PROBABILITY,
prob=cfg.INPUT.GRAYSCALE.PROBABILITY,
)
)

augmentation.append(
RandomApply(
Invert(
max_value=cfg.INPUT.INVERT.MAX_VALUE,
),
prob=cfg.INPUT.INVERT.PROBABILITY,
)
)

Expand Down
65 changes: 65 additions & 0 deletions datasets/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,71 @@ def inverse(self) -> T.Transform:
raise NotImplementedError


class HueTransform(T.Transform):
def __init__(self, hue_delta: float, color_space: str = "RGB"):
"""
Args:
delta (float): the amount to shift the hue channel. The hue channel is
shifted in degrees within the range [-180, 180].
"""
super().__init__()
self.hue_delta = hue_delta * 180
self.color_space = color_space

def apply_image(self, img: np.ndarray) -> np.ndarray:
"""
Apply hue transform to the image(s).
Args:
img (np.ndarray): image array assume the array is in range [0, 255].
Returns:
ndarray: hue transformed image(s).
"""
img = img.astype(np.uint8)
if self.color_space == "RGB":
img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
img[:, :, 0] = (img[:, :, 0] + self.hue_delta) % 180
img = cv2.cvtColor(img, cv2.COLOR_HSV2RGB)
else:
img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
img[:, :, 0] = (img[:, :, 0] + self.hue_delta) % 180
img = cv2.cvtColor(img, cv2.COLOR_HSV2BGR)
return img

def apply_coords(self, coords: np.ndarray) -> np.ndarray:
"""
Apply no transform on the coordinates.
Args:
coords (np.ndarray): floating point array of shape Nx2. Each row is (x, y).
Returns:
np.ndarray: original coords
"""
return coords

def apply_segmentation(self, segmentation: np.ndarray) -> np.ndarray:
"""
Apply no transform on the full-image segmentation.
Args:
segmentation (np.ndarray): labels of shape HxW
Returns:
np.ndarray: original segmentation
"""
return segmentation

def inverse(self) -> T.Transform:
"""
Compute the inverse of the transformation. The inverse of a hue change is a negative hue change.
Returns:
Transform: Inverse transformation.
"""
return HueTransform(-self.hue_delta, self.color_space)


class OrientationTransform(T.Transform):
"""
Transform that applies 90 degrees rotation to an image and its corresponding coordinates.
Expand Down

0 comments on commit adc75c5

Please sign in to comment.