Skip to content

Blur functional transforms (augmentations.blur.functional)

def create_motion_kernel (kernel_size, angle, direction, allow_shifted, random_state) [view source on GitHub]

Create a motion blur kernel.

Parameters:

Name Type Description
kernel_size int

Size of the kernel (must be odd)

angle float

Angle in degrees (counter-clockwise)

direction float

Blur direction (-1.0 to 1.0)

allow_shifted bool

Allow kernel to be randomly shifted from center

random_state Random

Python's random.Random instance

Returns:

Type Description
np.ndarray

Motion blur kernel

Source code in albumentations/augmentations/blur/functional.py
Python
def create_motion_kernel(
    kernel_size: int,
    angle: float,
    direction: float,
    allow_shifted: bool,
    random_state: Random,
) -> np.ndarray:
    """Create a motion blur kernel.

    Args:
        kernel_size: Size of the kernel (must be odd)
        angle: Angle in degrees (counter-clockwise)
        direction: Blur direction (-1.0 to 1.0)
        allow_shifted: Allow kernel to be randomly shifted from center
        random_state: Python's random.Random instance

    Returns:
        Motion blur kernel
    """
    kernel = np.zeros((kernel_size, kernel_size), dtype=np.float32)
    center = kernel_size // 2

    # Convert angle to radians
    angle_rad = np.deg2rad(angle)

    # Calculate direction vector
    dx = np.cos(angle_rad)
    dy = np.sin(angle_rad)

    # Create line points with direction bias
    line_length = kernel_size // 2
    t = np.linspace(-line_length, line_length, kernel_size * 2)

    # Apply direction bias
    if direction != 0:
        t = t * (1 + abs(direction))
        if direction < 0:
            t = t * -1

    # Generate line coordinates
    x = center + dx * t
    y = center + dy * t

    # Apply random shift if allowed
    if allow_shifted and random_state is not None:
        shift_x = random_state.uniform(-1, 1) * line_length / 2
        shift_y = random_state.uniform(-1, 1) * line_length / 2
        x += shift_x
        y += shift_y

    # Round coordinates and clip to kernel bounds
    x = np.clip(np.round(x), 0, kernel_size - 1).astype(int)
    y = np.clip(np.round(y), 0, kernel_size - 1).astype(int)

    # Keep only unique points to avoid multiple assignments
    points = np.unique(np.column_stack([y, x]), axis=0)
    kernel[points[:, 0], points[:, 1]] = 1

    # Ensure at least one point is set
    if not kernel.any():
        kernel[center, center] = 1

    return kernel

def process_blur_limit (value, info, min_value=0) [view source on GitHub]

Process blur limit to ensure valid kernel sizes.

Source code in albumentations/augmentations/blur/functional.py
Python
def process_blur_limit(value: ScaleIntType, info: ValidationInfo, min_value: int = 0) -> tuple[int, int]:
    """Process blur limit to ensure valid kernel sizes."""
    result = value if isinstance(value, Sequence) else (min_value, value)

    result = _ensure_min_value(result, min_value, info.field_name)
    result = _ensure_odd_values(result, info.field_name)

    if result[0] > result[1]:
        final_result = (result[1], result[1])
        warn(
            f"{info.field_name}: Invalid range {result} (min > max). "
            f"Range automatically adjusted to {final_result}.",
            UserWarning,
            stacklevel=2,
        )
        return final_result

    return result

def sample_odd_from_range (random_state, low, high) [view source on GitHub]

Sample an odd number from the range [low, high] (inclusive).

Parameters:

Name Type Description
random_state Random

instance of random.Random

low int

lower bound (will be converted to nearest valid odd number)

high int

upper bound (will be converted to nearest valid odd number)

Returns:

Type Description
int

Randomly sampled odd number from the range

Note

  • Input values will be converted to nearest valid odd numbers:
  • Values less than 3 will become 3
  • Even values will be rounded up to next odd number
  • After normalization, high must be >= low
Source code in albumentations/augmentations/blur/functional.py
Python
def sample_odd_from_range(random_state: Random, low: int, high: int) -> int:
    """Sample an odd number from the range [low, high] (inclusive).

    Args:
        random_state: instance of random.Random
        low: lower bound (will be converted to nearest valid odd number)
        high: upper bound (will be converted to nearest valid odd number)

    Returns:
        Randomly sampled odd number from the range

    Note:
        - Input values will be converted to nearest valid odd numbers:
          * Values less than 3 will become 3
          * Even values will be rounded up to next odd number
        - After normalization, high must be >= low
    """
    # Normalize low value
    low = max(3, low + (low % 2 == 0))
    # Normalize high value
    high = max(3, high + (high % 2 == 0))

    # Ensure high >= low after normalization
    high = max(high, low)

    if low == high:
        return low

    # Calculate number of possible odd values
    num_odd_values = (high - low) // 2 + 1
    # Generate random index and convert to corresponding odd number
    rand_idx = random_state.randint(0, num_odd_values - 1)
    return low + (2 * rand_idx)