tenflowers-dataset 0.1.1

Data pipeline and dataset utilities for TenfloweRS
Documentation
// GPU-accelerated Gaussian noise shader
// Adds Gaussian noise to image for data augmentation

struct Uniforms {
    width: u32,
    height: u32,
    channels: u32,
    seed: u32,
    mean: f32,
    std_dev: f32,
    padding1: f32,
    padding2: f32,
};

@group(0) @binding(0) var<storage, read> input_data: array<f32>;
@group(0) @binding(1) var<storage, read_write> output_data: array<f32>;
@group(0) @binding(2) var<uniform> uniforms: Uniforms;

fn get_input_pixel(channel: u32, y: u32, x: u32) -> f32 {
    let idx = channel * uniforms.height * uniforms.width + y * uniforms.width + x;
    if (idx >= arrayLength(&input_data)) {
        return 0.0;
    }
    return input_data[idx];
}

fn set_output_pixel(channel: u32, y: u32, x: u32, value: f32) {
    let idx = channel * uniforms.height * uniforms.width + y * uniforms.width + x;
    if (idx < arrayLength(&output_data)) {
        output_data[idx] = value;
    }
}

// Simple pseudo-random number generator (LCG)
fn rand(seed: u32) -> u32 {
    let a = 1664525u;
    let c = 1013904223u;
    return a * seed + c;
}

fn rand_float(seed: u32) -> f32 {
    return f32(rand(seed)) / 4294967295.0;
}

// Box-Muller transform for Gaussian distribution
fn gaussian_noise(seed1: u32, seed2: u32, mean: f32, std_dev: f32) -> f32 {
    let u1 = rand_float(seed1);
    let u2 = rand_float(seed2);
    
    // Ensure u1 is not zero to avoid log(0)
    let u1_safe = max(u1, 1e-10);
    
    let z0 = sqrt(-2.0 * log(u1_safe)) * cos(2.0 * 3.14159265 * u2);
    return mean + std_dev * z0;
}

@compute @workgroup_size(8, 8, 1)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
    let x = global_id.x;
    let y = global_id.y;
    let channel = global_id.z;
    
    if (x >= uniforms.width || y >= uniforms.height || channel >= uniforms.channels) {
        return;
    }
    
    // Get original pixel value
    let original_value = get_input_pixel(channel, y, x);
    
    // Generate unique seeds for this pixel
    let pixel_id = channel * uniforms.height * uniforms.width + y * uniforms.width + x;
    let seed1 = uniforms.seed + pixel_id;
    let seed2 = uniforms.seed + pixel_id + 1000000u;
    
    // Generate Gaussian noise
    let noise = gaussian_noise(seed1, seed2, uniforms.mean, uniforms.std_dev);
    
    // Add noise to original pixel and clamp to [0, 1]
    let noisy_value = clamp(original_value + noise, 0.0, 1.0);
    
    // Store result
    set_output_pixel(channel, y, x, noisy_value);
}