#recovery #implemented #solver #image-denoising #bredies #chambolle

nightly image-recovery

Image recovery algorithms, implemented in Rust

4 releases (2 breaking)

0.3.1 Aug 7, 2023
0.3.0 Aug 7, 2023
0.2.10 Aug 7, 2023
0.1.0 Apr 18, 2022

#1134 in Math

22 downloads per month

AGPL-3.0-or-later

785KB
639 lines

Image Recovery

Image recovery algorithms, implemented in Rust.

The solvers on this library are based on the algorithms presented in Chambolle, A. and Pock, T. (2011), with modifications inspired by Bredies, K. (2014).

Uses the image crate for loading and saving images, and the ndarray crate for manipulating matrices.

Only denoising algorithms is implemented so far, see the roadmap section for planned algorithm implementations.

Crates.io GitHub Workflow Status (with event) GitHub

See the docs

How to use:

Declare the dependency in you Cargo.toml

[dependencies]
image-recovery = "0.2"

Examples:

Only the denoise solver is currently implemented. The examples for it can be found in the examples folder, and can be run with cargo run --example denoise. Furthermore, a quick example usage is shown below:

Image denoising (multichannel)

use image_recovery::{
    image, // re-exported `image` crate
    ImageArray, // struct for holding images
};

fn main() {
    // the `image` crate provides functionality to decode images
    let img = image::open("examples/source_images/angry_birb_noisy.png")
        .expect("image could not be open")
        .into_rgb8(); // the algorithms in this library are implemented for the Luma and Rgb types

    // load the RGB image into an object which is composed
    // of 3 matrices, one for each channel
    let img_array = ImageArray::from(&img);

    // choose inputs for the denoising solver:
    // according to Chambolle, A. and Pock, T. (2011),
    // tau and lambda should be chosen such that
    // `tau * lambda * L2 norm^2 <= 1`
    // while `L2 norm^2 <= 8`
    // If we choose `tau * lambda * L2 norm^2 == 1`, then:
    let tau: f64 = 1.0 / 2_f64.sqrt();
    let sigma: f64 = 1_f64 / (8.0 * tau);

    // lambda drives the dual objective function
    // closer to zero results in a smoother output image
    // closer to infinity results in an output closer to the input
    let lambda: f64 = 0.0259624705;

    // gamma is a variable used to update the internal
    // state of the algorithm's variables, providing
    // an accelerated method for convergence.
    // Chambolle, A. and Pock, T. (2011), choose
    // the value to be `0.35 * lambda`
    let gamma: f64 = 0.35 * lambda;

    // choose bounds for denoising solver
    // the algorithm will run for at most `max_iter` iterations
    let max_iter: u32 = 500;

    // the algorithm will stop running if:
    // `convergence_threshold < norm(current - previous) / norm(previous)`
    // where `current` is the output candidate for the current iteration,
    // and `previous` is the output candidate of the previous iteration.
    let convergence_threshold = 10_f64.powi(-10);

    // now we can call the denoising solver with the chosen variables
    let denoised_array = image_array
        .denoise(lambda, tau, sigma, gamma, max_iter, convergence_threshold)
        .unwrap(); // will fail if image is 1 pixel in either x or y

    // we convert the solution into an RGB image format
    let denoised_img = denoised_array.into_rgb();

    // encode it and save it to a file
    new_img.save("examples/result_images/angry_birb_denoised.png")
        .expect("image could not be saved");
}

This should provide the following result:

Source image: Output image:
source image, noisy output image, denoised

Testing

Tests can be run with cargo test. Unittests and Doc-tests are provided.

Note that the Doc-test in src/lib.rs will run very slowly in debug mode, it is recommended to run tests in release mode: cargo test --release.

Benchmarking

Benchmarking can be run with cargo bench.

Roadmap

Image recovery algorithms to implement:

  • Denoising
  • Zooming
  • Deblurring
  • Dequantization
  • Inpainting
  • Compressive imaging

This code is licensed under the GNU Affero General Public License version 3 or later. See LICENSE or gnu.org/licenses/agpl-3.0.en.html.

Acknowledgements

Code by Lílian Ferreira de Freitas, mathematics by Emilia L. K. Blåsten

Dependencies

~6.5MB
~96K SLoC