Image processing operations

Overview

imageproc

crates.io Build Status License

An image processing library, based on the image library. There may initially be overlap between the functions in this library and those in image::imageops.

This is very much a work in progress. If you have ideas for things that could be done better, or new features you'd like to see, then please create issues for them. Nothing's set in stone.

API documentation

Goals

A performant, well-tested, well-documented library with a consistent API, suitable for use as the basis of computer vision applications or graphics editors.

Non-goals

Maximum genericity over image storages or formats, or support for higher-dimensional images.

Full blown computer vision applications (e.g. face recognition or image registration) probably also belong elsewhere, but the line's a bit blurred here (e.g. is image in-painting an image processing task or a computer vision task?). However, worrying about how to structure the code can probably wait until we have more code to structure...

Crate Features

Imageproc is built with these features enabled by default:

  • rayon enables multithreading for certain operations (e.g., geometric transformations) via rayon

Optionally, the following dependencies can be enabled:

  • property-testing exposes helper types and methods to enable property testing via quickcheck
  • display-window enables the displaying of images (using imageproc::window) with sdl2

How to contribute

All pull requests are welcome. Some specific areas that would be great to get some help with are:

  • New features! If you're planning on adding some new functions or modules, please create an issue with a name along the lines of "Add [feature name]" and assign it to yourself (or comment on the issue that you're planning on doing it). This way we'll not have multiple people working on the same functionality.
  • Performance - profiling current code, documenting or fixing performance problems, adding benchmarks, comparisons to other libraries.
  • Testing - more unit tests and regression tests. Some more property-based testing would be particularly nice.
  • APIs - are the current APIs hard to use or inconsistent? Some open questions: Should we return Result types more often? How should functions indicate acceptable input image dimensions? Should we use enum arguments or have lots of similarly named functions? What's the best way to get concise code while still allowing control over allocations?
  • Documentation - particularly more example code showing what's currently possible. Pretty pictures in this README.
  • Feature requests - are there any functions you'd like to see added? Is the library currently unsuitable for your use case for some reason?
Comments
  • Geometric Transformations Module

    Geometric Transformations Module

    Added a module named proj that defines projective transformations, and means to construct, combine and apply them to images.

    The module exports warp* functions that allow performing projective transformations on images. Some of the functionality of this module overlaps with the affine module.

    It exports a type Proj that can be used to define projective transformations by

    • Constructing them from primitive transformations
    • From a given 3x3 projective matrix (in homogeneous coordinates)
    • Or from a set of 4 control point pairs (for this calculation I have added a new dependency rulinalg 0.4.2 - a linear algebra crate

    image dependency bumped to 0.22.1 and all functions deprecated in the image crate marked with #[allow_deprecated] to suppress warnings.

    Bumped the version of the imageproc crate. Don't know if this is common practice in additions like this one.

    opened by hepek 16
  • Initial crate release

    Initial crate release

    We don't have to make this polished, just less rough than the code is now.

    • ~~Try to reduce signature bloat a little. Unfortunately I think we're stuck with the I: 'static, I::Pixel: 'static, <I::Pixel as Pixel>::Subpixel: + 'static spam for now (but I'd be very happy to be shown wrong).~~
    • Check the TODOs for anything easily fixable.
    • Profile performance. I've still not looked at this, but I fear the performance is pretty woeful. If we're 2x slower than, say, OpenCV that's fine for now. If we're 100x slower not so much.
    • ~~Make the existing functions nicer to call, probably with a mix of functions taking loads of options and functions providing sensible defaults for some of those options that forward to the verbose ones.~~
    • ~~Stop spamming everything directly into master. I'll create a fork and move my future commits to go via pull requests.~~
    • ~~Set up continuous integration. Anyone want to help with this one?~~
    • ~~Better readme - give usage examples, and briefly discuss future plans and how to contribute.~~
    • ~~Add a license.~~
    • ~~Build on stable.~~
    opened by theotherphil 15
  • Drawing TTF fonts/text

    Drawing TTF fonts/text

    It would be interesting to look at ways to draw TTF fonts (or just any text) onto supported images. Let me know what you think!

    Take a look at https://github.com/dylanede/rusttype as well

    opened by mhsjlw 13
  • Add image tinting

    Add image tinting

    @softprops was looking for something like ImageMagick's TintImage function: https://github.com/ImageMagick/ImageMagick/blob/master/MagickCore/fx.c.

    Visual effects seem like something that should eventually go in a separate crate, but for now it should be pretty easy to add a module containing some ImageMagick-y effects.

    opened by theotherphil 13
  • draw_text_mut does not respect color

    draw_text_mut does not respect color

    I am trying to create an image containing text with different color. But it looks like draw_text_mut always print using the first color used

    the line is:

    Rgba([ (fps * 20), 0u8, 0u8, 255u8]),
    

    where fps is increased of 1 every loop (I am printing it, even with u8 cast)

    edit: the full command is taken from one of the examples

    imageproc::drawing::draw_text_mut(
    				&mut image,
    				Rgba([ (fps * 20), 0u8, 0u8, 255u8]),
    				x,
    				y,
    				scale,
    				&font,
    				&c,
    			);
    
    opened by lestofante 10
  • `draw_filled_circle_mut` gives an ugly circle when radius is small

    `draw_filled_circle_mut` gives an ugly circle when radius is small

    This happens in when I try to draw a circle with small radius.

    Expected

    (draw by pillow) circle_py

    Actual behaviour

    circle

    (a more intuitive picture) 图片

    Reproduction steps

    let mut circle = DynamicImage::new_luma8(21, 21);
    
    draw_filled_circle_mut(
        &mut circle,
        (10, 10),
        10,
        Rgba([255, 255, 255, 255]),
    );
    circle.save(std::path::Path::new("circle.png"));
    
    circle = Image.new('L', (21, 21), 0)
    draw = ImageDraw.Draw(circle)
    draw.ellipse((0, 0, 20, 20), fill=255)
    circle.save('circle_py.png')
    
    opened by Aloxaf 10
  • Implement canny edge detection algorithm.

    Implement canny edge detection algorithm.

    This commit adds a new module edges, which currently only contains the canny edge detection algorithm. The provided implementation is heavily based on the implementation proposed by the corresponding wikipedia article (https://en.wikipedia.org/wiki/Canny_edge_detector), with some simple optimizations.

    opened by nicokoch 10
  • no `text_size` in `drawing`

    no `text_size` in `drawing`

    Running the font.rs example on the latest crate outputs an error regarding the text_size function.

    error[E0432]: unresolved import `imageproc::drawing::text_size`
     --> src\main.rs:4:41
      |
    4 | use imageproc::drawing::{draw_text_mut, text_size};
      |                                         ^^^^^^^^^ no `text_size` in `drawing`
    
    [dependencies]
    imageproc = "0.22.0"
    image = { version = "0.23.6", default-features = false }
    rusttype = "0.9.2"
    
    opened by joseyose 9
  • Add bicubic interpolation support for affine transforms (resolves #351)

    Add bicubic interpolation support for affine transforms (resolves #351)

    I have implemented a version of this. Some caveats:

    • It's my first attempt at really doing anything in Rust so let me know where my code sucks :)
    • It loses a pixel off the edge because of the 4x4 kernel. I want to improve edge behavior for all the affine code, but that would be a separate change.
    • It's not super fast.. about 1/2 the speed of the bilinear stuff. Here are the bench results on my laptop:
    test affine::tests::bench_affine_bicubic                                       ... bench:   2,054,455 ns/iter (+/- 574,716)
    test affine::tests::bench_affine_bilinear                                      ... bench:     822,706 ns/iter (+/- 198,371)
    test affine::tests::bench_affine_nearest                                       ... bench:     390,691 ns/iter (+/- 22,217)
    test affine::tests::bench_rotate_bicubic                                       ... bench:     804,275 ns/iter (+/- 182,569)
    test affine::tests::bench_rotate_bilinear                                      ... bench:     430,449 ns/iter (+/- 23,885)
    test affine::tests::bench_rotate_nearest                                       ... bench:     292,266 ns/iter (+/- 26,284)
    
    opened by mduggan 9
  • Can't draw semi-transparent shapes

    Can't draw semi-transparent shapes

    I want to be able to draw semi-transparent rectangles. I have tried doing this using colors with a suitable alpha channel. Take this code for example:

    extern crate image;
    extern crate imageproc;
    
    use std::path::Path;
    use image::{Rgba, RgbaImage};
    use imageproc::drawing::draw_filled_rect_mut;
    
    fn main() {
        let path = Path::new("1.png");
        let solid_white = Rgba([255u8, 255u8, 255u8, 255u8]);
        let blue = Rgba([0u8, 0u8, 255u8, 255u8]);
        let semi_red = Rgba([255u8, 0u8, 0u8, 127u8]);
        let mut img = RgbaImage::new(200, 200);
        draw_filled_rect_mut( // Solid white background
            &mut img, imageproc::rect::Rect::at(0, 0).of_size(200, 200),
            solid_white);
        draw_filled_rect_mut( // Solid blue square
            &mut img, imageproc::rect::Rect::at(25, 25).of_size(100, 100),
            blue);
        draw_filled_rect_mut( // Semi-transparent red square
            &mut img, imageproc::rect::Rect::at(75, 75).of_size(75, 75),
            semi_red);
        img.save(path).unwrap();
    }
    

    I expected this to draw a 200x200 square in solid white (which it does), then to draw a 100x100 solid blue square on top (which it does), then to draw a 75x75 semi-transparent red square that overlaps the blue and the white (which it does -- but not quite right). I expected the red to "show through" some blue where it overlaps the blue square and to "show through" some white (i.e., look pink) where it overlaps the white background.

    But there is no show through at all.

    Is it possible to achieve this effect? If so, where is it documented?

    opened by mark-summerfield 9
  • Added basic support for ttf and otf generic image font drawing

    Added basic support for ttf and otf generic image font drawing

    This is a work-in-progress, use this pull request for tracking checklist completion:

    • [ ] handling of point sizes and converting between pixels and absolute sizes
    • [x] positioning of font, and out-of-bounds checks
    • [x] make it generic over pixel type
    • [x] example
    • [ ] newline support (?)
    • [ ] outline support (?)
    • [ ] add some regression tests
    • [ ] add some unit tests - probably by writing the imageproc rendering function in terms of something with a signature like the draw function from rusttype, and then mocking out draw in the unit test ourselves
    opened by mhsjlw 9
  • Refactor Gradients [Discussion]

    Refactor Gradients [Discussion]

    This PR is intended to facilitate discussion about a proposed refactor. It isn't a complete PR—probably won't even compile.

    I suggest the gradient filter module & API be refactored to achieve the following:

    • unify the API with respect to the choice of kernel
    • increase orthogonality
    • allow for the addition of the Roberts cross kernel, which is a $2\times 2$ kernel, not a $3\times 3$ kernel and so isn't compatible with present-day code
    • reduce code duplication (DRY)

    A summary of the suggested design

    1. Have a GradientKernel (alt. named GradientMethod) enum with variants Sobel, Scharr, etc.
    2. Change the pub static HORIZONTAL_* and pub static VERTICAL_* kernels to be actual Kernel<i32> struct instances rather than [i32; 9] arrays.
    3. Member functions of GradientKernel return references to the appropriate pub static Kernel<i32> instance.
    4. Move the filtering functions into member functions of GradientKernel. Optionally have free function aliases that take the GradientKernel variant as a parameter. (The Sobel kernel would no longer be distinguished.)
    5. Change the function and purpose of gradient_map so that it applies a function to the gradient vector of each point to produce a single pixel result. Consequently, the member functions gradient_L1_norm, gradient_angle, gradient_L2_norm (with alias gradient_magnitude) trivially reduce to calls to gradient_map.
    6. Gradient operations only work on single channel images. Do away with the functionality currently being provided by gradient_map. (Justified by replacing multichannel functionality with better, more general imageprocfeature.)

    More Details

    The suggestion is to have a GradientKernel (alt. name could be GradientMethod) enum:

    pub enum GradientKernel {
        Sobel,
        Scharr,
        Prewitt,
        Roberts
    }
    

    4. Move the filtering functions into member functions of GradientKernel.

    The free functions in gradients.rs would be brought into GradientKernel member functions:

    impl GradientKernel {
        pub fn horizontal_gradient(&self, image: &GrayImage) -> Image<Luma<i16>> {…}
        pub fn vertical_gradient(&self, image: &GrayImage) -> Image<Luma<i16>> {…}
        pub fn gradient_map<P, F, Q>(&self, image: &GrayImage, f: F) -> Image<Q> where … {…}
        pub fn gradient_magnitude(&self, image: &GrayImage) -> Image<Luma<i16>> {…}
        ⋮
    }
    

    5. Change the function and purpose of gradient_map

    I'll argue for the existence of a new function in this section. I will argue for the deletion of the current version of gradient_map in the next section, as these are two distinct questions.

    I want a function called gradient_map, but I do not want it to do what the current definition of gradient_map does. Instead, it makes sense to me to have a gradient_map function that maps a function over the gradient vector at each point to produce an output image. This would literally map a function onto the gradient, which strikes me as linguistically more accurate. Such a function would be useful to client code and would reduce the computations of gradient_angle and gradient_magnitude to the composition of gradient_map with the appropriate function of the gradient vector, which is satisfyingly orthogonal.

    6. Gradient operations only work on single channel images

    The current version of gradient_map enables an arbitrary function of an n-channel pixel to produce an m-channel pixel for the output. I speculate that this function exists because gradient computations are often needed to produce a "magnitude of rate of change at a point" from a color source image, and since kernel convolution in a single channel operation, there needed to be a way to go from three channels to one. But if magnitude of perceptual rate of change is what is of interest, then the color source image should be converted to luminance before a gradient operation is ever applied. (Note also that any linear function of channels commutes with a channel-wise gradient operation.) In my view, this functionality doesn't belong in the gradients module at all, and in any case it isn't well-described by the function name gradient_map.

    This refactor is agnostic to whether and to where the existing functionality to move. But I'll say a few words about that anyway. Producing an image via a function of another image's channels can be done by the client code. If it is useful functionality and/or is cumbersome for client code to implement, the functionality should be implemented in a generic way in some other module, or in its own module. In fact, I would like to draft a second feature proposal independent of this one that implements fast generic high-level elementwise mathematical operations on images: add two images, multiply two images, find the max of two images. But this is a digression.

    A gradient operation is fundamentally a single channel operation. Splitting and combining channels and images is a distinct collection of operations from gradient operations.

    opened by rljacobson 0
  • 100% CPU usage during `imageproc::window::display_image` on Linux

    100% CPU usage during `imageproc::window::display_image` on Linux

    While running the display_image function, one of the CPU's on my computer suddenly rockets up to using 100% of the CPU.

    100% usage on one CPU

    Looking into the backtraces while running gdb, it appears to be happening during sdl2 event retrieval. However, a brief investigation into sdl2's codebase yields nothing that would cause this, and I'm unsure if this issue originates in imageproc or in one of its dependencies.

    Here is the program I'm using it in, although I doubt it's that.

    opened by notgull 1
  • add an explicit way to define the shape of drawn text

    add an explicit way to define the shape of drawn text

    the current text scaling system makes it needlessly difficult to define the "shape" of a character.

    i feel that something more explicit than the current rusttype::Scale based system may be beneficial to the usability of this library . one possibility is taking four numeric arguments, (x, y, width, height). where x and y define the position of the top left corner of the character, and width and height define how far the character extends from x and y

    opened by anytarseir67 1
Owner
image-rs
Image libraries for Rust
image-rs
ePaperify: Framebuffer/image pre-processing library for e-Paper displays

ePaperify: Framebuffer/image pre-processing library for e-Paper displays

Jackson Ming Hu 5 Mar 15, 2022
Image processing proxy and API, created to allow faster media delivery for the Holaplex storefront.

Description imgopt is an image processing proxy with a very simple API, created to download and dynamically scaledown, convert, and cache different me

Holaplex 5 Nov 3, 2022
Lust is a static image server designed to automatically convert uploaded image to several formats and preset sizes

What is Lust? Lust is a static image server designed to automatically convert uploaded image to several formats and preset sizes with scaling in mind.

Harrison Burt 242 Dec 22, 2022
Takes a folder of images (as a palette), and an image, and figures out how to tile the palette to resemble the image!

Takes a folder of images (as a palette), and an image, and figures out how to tile the palette to resemble the image!

Jacob 258 Dec 30, 2022
Rust Lean Image Viewer - Fast and configurable image viewer inspired by JPEGView by David Kleiner

Rust Lean Image Viewer - Fast and configurable image viewer inspired by JPEGView by David Kleiner

3top1a 4 Apr 9, 2022
Image Compression Algorithm

Image Compression Algorithm ?? A new lossless image compression algorithm. In the newest version the algorithm performs rather good, but manages to su

Hannes 31 May 10, 2022
tai (Terminal Ascii Image) tool to convert images to ascii written in Rust

TAI Terminal Ascii Image A tool to convert images to ascii art written in Rust ?? Notes This tool is still in development stage. Contributions All Con

Mustafa Salih 258 Dec 5, 2022
Artsy pixel image to vector graphics converter

inkdrop inkdrop is an artsy bitmap to vector converter. Command line interface The CLI binary is called inkdrop-cli and reads almost any image bitmap

Matthias Vogelgesang 62 Dec 26, 2022
Automated image compression for efficiently distributing images on the web.

Imager Apparently this project made it into the GitHub Archive Program. About Imager is a tool for automated image compression, and can competitively

Imager IO 487 Dec 25, 2022
Open Graphic Image Writer

Open Graphic Image Writer Documentation You can generate Open Graphic Image dynamically. A CSS-like API. You can generate image by using template imag

keiya sasaki 46 Dec 15, 2022
Signed distance field font and image command line tool based on OpenCL.

SDFTool Signed distance field font and image command line tool based on OpenCL. Build Windows Run cargo build --release in Visual Studio developer x64

弦语蝶梦 7 Oct 16, 2022
A simple image average color extractor written in 🦀 Rust

A simple image average color extractor written in ?? Rust

Victor Aremu 3 Sep 23, 2021
A simple command-line utility (and Rust crate!) for converting from a conventional image file (e.g. a PNG file) into a pixel-art version constructed with emoji

EmojiPix This is a simple command-line utility (and Rust crate!) for converting from a conventional image file (e.g. a PNG file) into a pixel-art vers

Michael Milton 22 Dec 6, 2022
A Simple Image to Ascii converter in Rust

Image to Ascii A Simple Image to Ascii converter in Rust Brief ?? In my way to learn Rust i decided to make this converter. Challenges ?? new to Rust

WasixXD 7 Sep 16, 2022
Rust library for fast image resizing with using of SIMD instructions.

fast_image_resize Rust library for fast image resizing with using of SIMD instructions. CHANGELOG Supported pixel formats and available optimisations:

Kirill Kuzminykh 115 Jan 5, 2023
Experimental vectorized-raster image editor

Sverg Sverg is an experimental image editor that leverages the power of modern hardware so that you can create images as if they were raster images (e

sdfgeoff 3 Jan 25, 2022
Rust port of the Quite Okay Image format

qoi_rs What is this? A pretty boring Rust translation of qoi. Status What's there Encode & Decode works Results agree with the C implementation for al

null 9 Dec 9, 2021
A Rust encoder/decoder for Dominic Szablewski's QOI format for fast, lossless image compression.

QOI - The “Quite OK Image” format This is a Rust encoder and decoder for Dominic Szablewski's QOI format for fast, lossless image compression. See the

Chevy Ray Johnston 62 Nov 29, 2022
Web-app that simulates different types of color blindness from a user-provided input image.

What is Dalted? Web-app that simulates different types of color blindness from a user-provided input image. Resources The color blindness simulation i

Jorge Carrasco 18 Dec 20, 2022