7.1 KiB
7.1 KiB
filmgrain
- Realistic Film Grain Simulation
filmgrain
is a Python script that applies realistic film grain to digital images. It implements the procedural grain synthesis method described by Zhang et al. (2023) in "Procedural Synthesis of Film Grain Noise". This method leverages GPU acceleration via the warp
library for efficient processing.
Features
- Implements the film grain model by Zhang et al. (2023).
- GPU accelerated using
warp-lang
(requires a CUDA-capable NVIDIA GPU). - Adjustable Grain Parameters:
--mu_r
: Mean grain radius (relative to pixel size), controlling grain size.--sigma
: Standard deviation of the Gaussian filter for noise blurring (sigma_filter
), controlling grain softness/sharpness.
- Monochrome Option: Apply spectrally uniform (monochromatic) grain based on image luminance, or apply independent RGB grain.
- Precomputes a variance lookup table (LUT) for performance.
- Supports RAW (Sony ARW, DNG), TIFF, PNG, and JPG inputs.
- Outputs TIFF (16-bit uncompressed), PNG (8-bit), or JPG (8-bit).
Requirements
- NVIDIA GPU: A CUDA-enabled NVIDIA graphics card is required as
warp-lang
currently targets CUDA. - CUDA Toolkit: Ensure you have a compatible version of the CUDA Toolkit installed.
uv
: For easy execution and dependency management.
Usage
The script is designed to be run with uv
.
Direct Execution with uv
(Recommended)
You can run filmgrain
directly from its Git repository URL:
uv run https://git.dws.rip/dubey/filmsim/raw/branch/main/filmgrain -- <input_image> <output_image> [options]
Example:
# Ensure input.png is in your current directory or provide a full path
# Output will be output_grained.jpg
uv run https://git.dws.rip/dubey/filmsim/raw/branch/main/filmgrain -- input.png output_grained.jpg --mu_r 0.1 --sigma 0.8 --mono
Local Execution
If you have cloned the repository or downloaded the script:
-
Navigate to the script's directory or ensure it's in your PATH.
-
Run the script:
uv run ./filmgrain -- <input_image> <output_image> [options]
Or, if
filmgrain
is in the current directory and executable:./filmgrain <input_image> <output_image> [options]
Arguments
Positional Arguments:
input_image
: Path to the input image.- Supported formats: TIFF, PNG, JPG, Sony ARW, DNG.
output_image
: Path to save the output image with film grain.- Output format is determined by the file extension:
.tiff
/.tif
: 16-bit uncompressed TIFF..png
: 8-bit PNG..jpg
/.jpeg
: 8-bit JPG (quality 95).
- Output format is determined by the file extension:
Options:
--mu_r FLOAT
: Mean grain radius (relative to pixel size). (Default:0.1
)- Controls the apparent size of the grain particles. Larger values mean larger grains.
- Must be positive.
--sigma FLOAT
: Standard deviation of the Gaussian Filter for noise blurring (sigma_filter
). (Default:0.8
)- Controls the sharpness or softness of the grain. Higher values result in softer, more blurred grain.
- Must be positive.
- The paper suggests
sigma_filter
should ideally be >=3 * mu_r
for the model's approximations to hold well. The script will issue a warning if this condition is not met.
--seed INT
: Random seed for noise generation. (Default:42
)- Allows for reproducible grain patterns.
--mono
: Apply monochrome film grain across channels based on luminance. (Default:False
- apply RGB grain)- If enabled, grain is generated based on the image's luminance and applied uniformly to R, G, and B channels.
- If disabled, grain is generated and applied independently for each color channel (R, G, B), leading to colored grain.
Workflow
- Load Image:
- Reads the input image. RAW files (ARW, DNG) are post-processed using
rawpy
(16-bit output, camera WB, no auto-bright, linear gamma). Other formats (TIFF, PNG, JPG) are read usingimageio
. - The image is converted to a 0-1 float32 range.
- Reads the input image. RAW files (ARW, DNG) are post-processed using
- Precompute Variance LUT:
- Calculates a lookup table (LUT) for the variance of the Boolean-Poisson (BP) noise model. This involves numerically integrating a complex function derived from the grain model, significantly speeding up per-pixel variance calculation later.
- Prepare Gaussian Kernel:
- Creates a 2D Gaussian kernel based on the
sigma_filter
parameter. This kernel is used to blur the initial noise, shaping the grain's appearance. The kernel radius is determined bysigma_filter
.
- Creates a 2D Gaussian kernel based on the
- Process Channels (RGB or Monochrome):
- Monochrome Mode (
--mono
):- The input image is converted to grayscale (luminance).
generate_noise_kernel
(Warp kernel): Generates initial random noise for the grayscale image. The noise variance at each pixel is determined by the pixel's intensity (u_val) and the precomputed variance LUT, scaled bymu_r
andsigma_filter
.convolve_2d_kernel
(Warp kernel): Convolves the generated noise with the 2D Gaussian kernel to produce the filtered (shaped) grain.- This single-channel filtered noise is then used for all R, G, and B output channels.
- RGB Mode (default):
- The process above (noise generation and convolution) is performed independently for each color channel (R, G, B) of the input image.
- Different random seeds are used for each channel (seed, seed+1, seed+2) to ensure decorrelated grain patterns.
- If the input is grayscale, the R channel's noise is copied to G and B.
- Monochrome Mode (
- Add Noise and Clip:
add_rgb_noise_and_clip_kernel
(Warp kernel): Adds the filtered noise (either monochrome or per-channel RGB) to the original image channels.- The result is clipped to the 0.0 - 1.0 range.
- Save Output:
- The final image with added grain is copied from the GPU back to the CPU.
- It's converted to the appropriate bit depth (16-bit for TIFF, 8-bit for PNG/JPG) and saved.
Technical Details (from Zhang et al. 2023)
- Boolean-Poisson (BP) Model: The grain is modeled as randomly placed circular grains (disks) of radius
mu_r
. The local density of these grains depends on the image intensity. - Variance Calculation: The core of the model involves calculating the variance of the noise that would result from this BP process. This variance is intensity-dependent. The
w_func
andCB_const_radius_unit
functions in the script are related to the geometric calculations of overlapping disks, which are part of this variance derivation. The integral ofCB_const_radius_unit * x
gives the key component for variance, which is precomputed into the LUT. - Filtering: The raw noise generated based on this variance is then filtered (convolved) with a Gaussian kernel (
h
in the paper, controlled bysigma_filter
) to achieve the final grain appearance. The paper notes that the filter's standard deviationsigma_filter
should be significantly larger thanmu_r
(e.g.,sigma_filter >= 3 * mu_r
) for certain approximations in their model to be accurate.