Shortcuts

Source code for caer.transforms.simulate

#    _____           ______  _____ 
#  / ____/    /\    |  ____ |  __ \
# | |        /  \   | |__   | |__) | Caer - Modern Computer Vision
# | |       / /\ \  |  __|  |  _  /  Languages: Python, C, C++, Cuda
# | |___   / ____ \ | |____ | | \ \  http://github.com/jasmcaus/caer
#  \_____\/_/    \_ \______ |_|  \_\

# Licensed under the MIT License <http://opensource.org/licenses/MIT>
# SPDX-License-Identifier: MIT
# Copyright (c) 2020-2021 The Caer Authors <http://github.com/jasmcaus>

#pylint:disable=unused-argument,unused-variable,eval-used

import numpy as np 
import cv2 as cv 
import random
import math 

from ..coreten import Tensor, is_tensor
from ..annotations import Tuple, Optional, Union


from .functional import (
    is_numeric, 
    is_numeric_list_or_tuple, 
    is_tuple, 
    _rgb,
    _snow_process,
    _generate_random_lines,
    _rain_process,
    _generate_random_blur_coordinates,
    _add_blur,
    _gravel_process,
    _add_sun_flare_line,
    _add_sun_process,
    _apply_motion_blur,
    _autumn_process,
    _shadow_process
)

__all__ = [
    "sim_snow",
    "sim_rain",
    "sim_fog",
    "sim_gravel",
    "sim_sun_flare",
    "sim_motion_blur",
    "sim_autumn",
    "sim_shadow"
]

[docs]def sim_snow(tens: Tensor, snow_coeff : Union[float, int] = -1) -> Tensor: r""" Simulate snowy conditions on an image. Args: tens (Tensor) : Any regular ``caer.Tensor``. snow_coeff (int): Coefficient value. Returns: Tensor of shape ``(height, width, channels)``. Examples:: >> tens = caer.data.sunrise >> filtered = caer.filters.sim_snow(tens, snow_coeff=-1) >> filtered (427, 640, 3) """ if snow_coeff != -1: if snow_coeff < 0.0 or snow_coeff > 1.0: raise ValueError("Snow coeff must only be between 0 and 1") else: snow_coeff = random.uniform(0, 1) snow_coeff *= 255/2 snow_coeff += 255/3 return _snow_process(tens, snow_coeff)
# Rain_type = "drizzle", "heavy", "torrential"
[docs]def sim_rain( tens: Tensor, slant: int = -1, drop_length: int = 20, drop_width: int = 1, drop_color: Tuple = (200,200,200), rain_type: Optional[str] = "None" ) -> Tensor: ## (200,200,200) is a shade of gray r""" Simulate rainy conditions on an image. Args: tens (Tensor) : Any regular ``caer.Tensor``. slant (int): Slant value. drop_length (int): Length of the raindrop. drop_width (int): Width of the raindrop. drop_color (tuple): Color of the raindrop. rain_type (str): Type of rain. Can be either "drizzle", "heavy" or "torrential". Returns: Tensor of shape ``(height, width, channels)``. Examples:: >> tens = caer.data.sunrise >> filtered = caer.filters.sim_rain(tens) >> filtered (427, 640, 3) """ slant_extreme = slant if not(is_numeric(slant_extreme) and (slant_extreme >=-20 and slant_extreme <= 20) or slant_extreme==-1): raise ValueError("Numeric value must be between -20 and 20") if not(is_numeric(drop_width) and drop_width>=1 and drop_width<=5): raise ValueError("Width must be between 1 and 5") if not(is_numeric(drop_length) and drop_length>=0 and drop_length<=100): raise ValueError("Length must be between 0 and 100") imshape = tens.shape if slant_extreme == -1: slant= np.random.randint(-10,10) # generate random slant if no slant value is given rain_drops, drop_length= _generate_random_lines(imshape, slant, drop_length, rain_type) return _rain_process(tens, slant_extreme, drop_length, drop_color, drop_width, rain_drops)
[docs]def sim_fog(tens: Tensor, fog_coeff:int=-1) -> Tensor: r""" Simulate foggy conditions on an image. Args: tens (Tensor) : Any regular ``caer.Tensor``. fog_coeff (int): Coefficient value. Returns: Tensor of shape ``(height, width, channels)``. Examples:: >> tens = caer.data.sunrise >> filtered = caer.filters.sim_fog(tens, fog_coeff=-1) >> filtered (427, 640, 3) """ if fog_coeff != -1: if fog_coeff < 0.0 or fog_coeff > 1.0: raise ValueError("Fog coefficient must be between 0 and 1") imshape = tens.shape if fog_coeff == -1: fog_coeff_t = random.uniform(0.3,1) else: fog_coeff_t = fog_coeff hw = int(imshape[1]//3*fog_coeff_t) haze_list = _generate_random_blur_coordinates(imshape,hw) for haze_points in haze_list: tens = _add_blur(tens, haze_points[0], haze_points[1], hw, fog_coeff_t) tens = cv.blur(tens, (hw//10, hw//10)) return _rgb(tens)
[docs]def sim_gravel(tens: Tensor, rectangular_roi:Tuple=(-1,-1,-1,-1), num_patches:int=8) -> Tensor: r""" Simulate gravelly conditions on an image. Args: tens (Tensor) : Any regular ``caer.Tensor``. rectangular_roi (tuple): Rectanglar co-ordinates of the intended region of interest. Default: (-1,-1,-1,-1). num_patches (int): Number of patches to operate on. Returns: Tensor of shape ``(height, width, channels)``. Examples:: >> tens = caer.data.sunrise >> filtered = caer.filters.sim_gravel(tens) >> filtered (427, 640, 3) """ if is_tuple(rectangular_roi) and is_numeric_list_or_tuple(rectangular_roi) and len(rectangular_roi)==4: x1 = rectangular_roi[0] y1 = rectangular_roi[1] x2 = rectangular_roi[2] y2 = rectangular_roi[3] else: raise ValueError("Rectangular ROI dimensions are invalid.") if rectangular_roi == (-1,-1,-1,-1): if is_tensor(tens): x1 = 0 y1 = int(tens.shape[0]*3/4) x2 = tens.shape[1] y2 = tens.shape[0] else: x1 = 0 y1 = int(tens[0].shape[0]*3/4) x2 = tens[0].shape[1] y2 = tens[0].shape[0] elif x1 == -1 or y1 == -1 or x2 == -1 or y2 == -1 or x2 <= x1 or y2 <= y1: raise ValueError("Rectangular ROI dimensions are invalid.") return _gravel_process(tens, x1, x2, y1, y2, num_patches)
[docs]def sim_sun_flare(tens: Tensor, flare_center:int=-1, angle:int=-1, num_flare_circles:int=8, src_radius:int=400, src_color:Tuple=(255,255,255)) -> Tensor: r""" Add a source of light (flare) on an specific region of an image. Args: tens (Tensor) : Any regular ``caer.Tensor``. flare_center (int): Center of the flare. Default: -1. angle (int): Angle of the flare. Default: -1 num_flare_circles (int): Number of flare circles to operate on. src_radius (int): Intended size of the flare src_color (tuple): Intended source color of the flare Returns: Tensor of shape ``(height, width, channels)``. Examples:: >> tens = caer.data.sunrise >> filtered = caer.filters.sim_sun_flare(tens) >> filtered (427, 640, 3) """ if angle != -1: angle = angle % (2*math.pi) # type: ignore if not(num_flare_circles >= 0 and num_flare_circles <= 20): raise ValueError("Numeric value must be between 0 and 20") imshape = tens.shape if angle == -1: angle_t = random.uniform(0, 2*math.pi) if angle_t == math.pi/2: angle_t = 0 else: angle_t = angle if flare_center == -1: flare_center_t = (random.randint(0, imshape[1]), random.randint(0, imshape[0]//2)) # type: ignore else: flare_center_t = flare_center # type: ignore x, y = _add_sun_flare_line(flare_center_t, angle_t, imshape) return _add_sun_process(tens, num_flare_circles, flare_center_t, src_radius, x, y, src_color)
[docs]def sim_motion_blur(tens: Tensor, speed_coeff:int=-1) -> Tensor: r""" Simulate motion-blur conditions on an image. Args: tens (Tensor) : Any regular ``caer.Tensor``. speed_coeff (int, float): Speed coefficient. Value must be between 0 and 1. Returns: Tensor of shape ``(height, width, channels)``. Examples:: >> tens = caer.data.sunrise >> filtered = caer.filters.sim_motion_blur(tens, speed_coeff=-1) >> filtered (427, 640, 3) """ if speed_coeff != -1: if speed_coeff < 0.0 or speed_coeff > 1.0: raise ValueError("Speed coefficient must be between 0 and 1") if speed_coeff == -1: count_t = int(15 * random.uniform(0, 1)) else: count_t = int(15 * speed_coeff) return _apply_motion_blur(tens, count_t)
[docs]def sim_autumn(tens: Tensor) -> Tensor: r""" Simulate autumn conditions on an image. Args: tens (Tensor) : Any regular ``caer.Tensor``. Returns: Tensor of shape ``(height, width, channels)``. Examples:: >> tens = caer.data.sunrise >> filtered = caer.filters.sim_autumn(tens) >> filtered (427, 640, 3) """ return _autumn_process(tens)
## ROI:(top-left x1,y1, bottom-right x2,y2), shadow_dimension=no. of sides of polygon generated
[docs]def sim_shadow( tens: Tensor, num_shadows : int = 1, rectangular_roi : Tuple = (-1,-1,-1,-1), shadow_dimension : int = 5 ) -> Tensor: r""" Simulate shadowy conditions on an image. Args: tens (Tensor) : Any regular ``caer.Tensor``. num_shadows (int): Number of shadows to work with. Value must be between 1 and 10. rectangular_roi (tuple): Rectanglar co-ordinates of the intended region of interest. Default: (-1,-1,-1,-1). shadow_dimensions (int): Number of shadow dimensions. Value must be > 3. Returns: Tensor of shape ``(height, width, channels)``. Examples:: >> tens = caer.data.sunrise >> filtered = caer.filters.sim_shadow(tens) >> filtered (427, 640, 3) """ if not(is_numeric(num_shadows) and num_shadows >= 1 and num_shadows <= 10): raise ValueError("Only 1-10 shadows can be introduced in an image") if not(is_numeric(shadow_dimension) and shadow_dimension >= 3 and shadow_dimension <= 10): raise ValueError("Polygons with dimensions < 3 don't exist and take time to plot") if is_tuple(rectangular_roi) and is_numeric_list_or_tuple(rectangular_roi) and len(rectangular_roi)==4: x1 = rectangular_roi[0] y1 = rectangular_roi[1] x2 = rectangular_roi[2] y2 = rectangular_roi[3] else: raise ValueError("Rectangular ROI dimensions are not valid") if rectangular_roi==(-1,-1,-1,-1): x1 = 0 if(is_tensor(tens)): y1 = tens.shape[0] // 2 x2 = tens.shape[1] y2 = tens.shape[0] else: y1 = tens[0].shape[0] // 2 x2 = tens[0].shape[1] y2 = tens[0].shape[0] elif x1 == -1 or y1 == -1 or x2 == -1 or y2 == -1 or x2 <= x1 or y2 <= y1: raise ValueError("Rectangular ROI dimensions are not valid") return _shadow_process(tens,num_shadows, x1, y1, x2, y2, shadow_dimension)