created_at2022-04-18 02:49:26.830566
updated_at2023-08-07 19:22:13.878021
descriptionImage recovery algorithms, implemented in Rust.
Lílian (lily-mosquitoes)



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. GitHub Workflow Status (with event) GitHub

See the docs

How to use:

Declare the dependency in you Cargo.toml

image-recovery = "0.2"


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"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


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

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


Benchmarking can be run with cargo bench.


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


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

Commit count: 76

cargo fmt