From 611ed999b5df5a0e0ec422b922ddd25d7db604ef Mon Sep 17 00:00:00 2001 From: ripytide <62516857+ripytide@users.noreply.github.com> Date: Thu, 23 May 2024 23:17:52 +0100 Subject: [PATCH] Remove noisy `ImageBuffer` type (#636) * refactored `ImageBuffer` type to `Image` and `GrayImage` type synonyms --- examples/blend.rs | 8 ++++---- examples/hog.rs | 5 +++-- src/binary_descriptors/brief.rs | 15 +++++--------- src/contrast.rs | 4 ++-- src/distance_transform.rs | 7 +++---- src/drawing/bezier.rs | 4 ++-- src/drawing/conics.rs | 10 ++++----- src/drawing/cross.rs | 4 ++-- src/drawing/line.rs | 6 +++--- src/drawing/polygon.rs | 6 +++--- src/drawing/rect.rs | 6 +++--- src/drawing/text.rs | 4 ++-- src/edges.rs | 24 +++++++++------------- src/filter/mod.rs | 15 +++++++------- src/geometric_transformations.rs | 10 ++++----- src/gradients.rs | 18 ++++++++-------- src/haar.rs | 4 ++-- src/hog.rs | 4 ++-- src/hough.rs | 8 ++++---- src/integral_image.rs | 4 ++-- src/map.rs | 10 ++++----- src/property_testing.rs | 6 +++--- src/region_labelling.rs | 8 ++++---- src/suppress.rs | 29 +++++++++++++------------- src/utils.rs | 35 +++++++++++++++++++++----------- tests/regression.rs | 29 ++++++++++++-------------- 26 files changed, 141 insertions(+), 142 deletions(-) diff --git a/examples/blend.rs b/examples/blend.rs index 43b2b741..8cce3bf9 100644 --- a/examples/blend.rs +++ b/examples/blend.rs @@ -1,7 +1,7 @@ //! Demonstrates the current incorrect handling of gamma for RGB images -use image::{ImageBuffer, Rgb}; -use imageproc::pixelops::interpolate; +use image::Rgb; +use imageproc::{definitions::Image, pixelops::interpolate}; fn main() { let red = Rgb::([255, 0, 0]); @@ -12,7 +12,7 @@ fn main() { let naive_blend = |x| interpolate(red, green, left_weight(x)); - let mut naive_image = ImageBuffer::new(800, 400); + let mut naive_image = Image::new(800, 400); for y in 0..naive_image.height() { for x in 0..naive_image.width() { naive_image.put_pixel(x, y, naive_blend(x)); @@ -39,7 +39,7 @@ fn main() { ]) }; - let mut gamma_image = ImageBuffer::new(800, 400); + let mut gamma_image = Image::new(800, 400); for y in 0..gamma_image.height() { for x in 0..gamma_image.width() { gamma_image.put_pixel(x, y, gamma_blend(x)); diff --git a/examples/hog.rs b/examples/hog.rs index b6819c72..f0f58c97 100644 --- a/examples/hog.rs +++ b/examples/hog.rs @@ -1,6 +1,7 @@ //! Demonstrates computing and visualising HoG gradients. -use image::{open, ImageBuffer}; +use image::open; +use imageproc::definitions::Image; use imageproc::hog::*; use std::env; use std::path::Path; @@ -32,7 +33,7 @@ fn create_hog_image(input: &Path, signed: bool) { // Crop image to a suitable size let (cropped_width, cropped_height) = (10 * (width / 10), 10 * (height / 10)); - let mut cropped = ImageBuffer::new(cropped_width, cropped_height); + let mut cropped = Image::new(cropped_width, cropped_height); for y in 0..cropped_height { for x in 0..cropped_width { cropped.put_pixel(x, y, *image.get_pixel(x, y)); diff --git a/src/binary_descriptors/brief.rs b/src/binary_descriptors/brief.rs index 5db4e924..1ebf52ce 100644 --- a/src/binary_descriptors/brief.rs +++ b/src/binary_descriptors/brief.rs @@ -2,10 +2,10 @@ //! described in [Calonder, et. al. (2010)]. /// /// [Calonder, et. al. (2010)]: https://www.cs.ubc.ca/~lowe/525/papers/calonder_eccv10.pdf -use image::{GenericImageView, GrayImage, ImageBuffer, Luma}; +use image::{GenericImageView, GrayImage, Luma}; use rand_distr::{Distribution, Normal}; -use crate::{corners::Corner, integral_image::integral_image, point::Point}; +use crate::{corners::Corner, definitions::Image, integral_image::integral_image, point::Point}; use super::{ constants::{BRIEF_PATCH_DIAMETER, BRIEF_PATCH_RADIUS}, @@ -67,12 +67,7 @@ pub struct TestPair { pub p1: Point, } -fn local_pixel_average( - integral_image: &ImageBuffer, Vec>, - x: u32, - y: u32, - radius: u32, -) -> u8 { +fn local_pixel_average(integral_image: &Image>, x: u32, y: u32, radius: u32) -> u8 { if radius == 0 { return 0; } @@ -114,7 +109,7 @@ fn local_pixel_average( } pub(crate) fn brief_impl( - integral_image: &ImageBuffer, Vec>, + integral_image: &Image>, keypoints: &[Point], test_pairs: &[TestPair], length: usize, @@ -318,7 +313,7 @@ mod tests { 5, 237, 254, 171, 172, 165, 50, 39; 92, 31, 238, 88, 44, 67, 140, 255 ); - let integral_image: ImageBuffer, Vec> = integral_image(&image); + let integral_image: Image> = integral_image(&image); assert_eq!(local_pixel_average(&integral_image, 3, 3, 2), 117); } } diff --git a/src/contrast.rs b/src/contrast.rs index 1e4124a7..120786e7 100644 --- a/src/contrast.rs +++ b/src/contrast.rs @@ -2,7 +2,7 @@ use std::cmp::{max, min}; -use image::{GrayImage, ImageBuffer, Luma}; +use image::{GrayImage, Luma}; #[cfg(feature = "rayon")] use rayon::prelude::*; @@ -19,7 +19,7 @@ use crate::stats::{cumulative_histogram, histogram}; pub fn adaptive_threshold(image: &GrayImage, block_radius: u32, delta: i32) -> GrayImage { assert!(block_radius > 0); let integral = integral_image::<_, u32>(image); - let mut out = ImageBuffer::from_pixel(image.width(), image.height(), Luma::black()); + let mut out = GrayImage::from_pixel(image.width(), image.height(), Luma::black()); for y in 0..image.height() { for x in 0..image.width() { diff --git a/src/distance_transform.rs b/src/distance_transform.rs index 6a453fa1..86fd473f 100644 --- a/src/distance_transform.rs +++ b/src/distance_transform.rs @@ -2,7 +2,7 @@ //! image from the nearest pixel of interest. use crate::definitions::Image; -use image::{GenericImage, GenericImageView, GrayImage, ImageBuffer, Luma}; +use image::{GenericImage, GenericImageView, GrayImage, Luma}; use std::cmp::min; /// How to measure distance between coordinates. @@ -115,8 +115,7 @@ pub(crate) fn distance_transform_impl(image: &mut GrayImage, norm: Norm, from: D .iter_mut() .for_each(|p| *p = if *p == 0 { 1 } else { 0 }), } - let float_dist: ImageBuffer, Vec> = - euclidean_squared_distance_transform(image); + let float_dist: Image> = euclidean_squared_distance_transform(image); image .iter_mut() .zip(float_dist.iter()) @@ -222,7 +221,7 @@ unsafe fn check( /// [Distance Transforms of Sampled Functions]: https://www.cs.cornell.edu/~dph/papers/dt.pdf pub fn euclidean_squared_distance_transform(image: &Image>) -> Image> { let (width, height) = image.dimensions(); - let mut result = ImageBuffer::new(width, height); + let mut result = Image::new(width, height); let mut column_envelope = LowerEnvelope::new(height as usize); // Compute 1d transforms of each column diff --git a/src/drawing/bezier.rs b/src/drawing/bezier.rs index b82f69ee..47c01116 100644 --- a/src/drawing/bezier.rs +++ b/src/drawing/bezier.rs @@ -1,7 +1,7 @@ use crate::definitions::Image; use crate::drawing::line::draw_line_segment_mut; use crate::drawing::Canvas; -use image::{GenericImage, ImageBuffer}; +use image::GenericImage; /// Draws a cubic Bézier curve on an image. /// @@ -18,7 +18,7 @@ pub fn draw_cubic_bezier_curve( where I: GenericImage, { - let mut out = ImageBuffer::new(image.width(), image.height()); + let mut out = Image::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); draw_cubic_bezier_curve_mut(&mut out, start, end, control_a, control_b, color); out diff --git a/src/drawing/conics.rs b/src/drawing/conics.rs index 5c07b161..9f4a9e05 100644 --- a/src/drawing/conics.rs +++ b/src/drawing/conics.rs @@ -2,7 +2,7 @@ use crate::definitions::Image; use crate::drawing::draw_if_in_bounds; use crate::drawing::line::draw_line_segment_mut; use crate::drawing::Canvas; -use image::{GenericImage, ImageBuffer}; +use image::GenericImage; /// Draws the outline of an ellipse on an image. /// @@ -25,7 +25,7 @@ pub fn draw_hollow_ellipse( where I: GenericImage, { - let mut out = ImageBuffer::new(image.width(), image.height()); + let mut out = Image::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); draw_hollow_ellipse_mut(&mut out, center, width_radius, height_radius, color); out @@ -77,7 +77,7 @@ pub fn draw_filled_ellipse( where I: GenericImage, { - let mut out = ImageBuffer::new(image.width(), image.height()); + let mut out = Image::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); draw_filled_ellipse_mut(&mut out, center, width_radius, height_radius, color); out @@ -179,7 +179,7 @@ pub fn draw_hollow_circle( where I: GenericImage, { - let mut out = ImageBuffer::new(image.width(), image.height()); + let mut out = Image::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); draw_hollow_circle_mut(&mut out, center, radius, color); out @@ -228,7 +228,7 @@ pub fn draw_filled_circle( where I: GenericImage, { - let mut out = ImageBuffer::new(image.width(), image.height()); + let mut out = Image::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); draw_filled_circle_mut(&mut out, center, radius, color); out diff --git a/src/drawing/cross.rs b/src/drawing/cross.rs index 6c046ba7..bb3be8ca 100644 --- a/src/drawing/cross.rs +++ b/src/drawing/cross.rs @@ -1,6 +1,6 @@ use crate::definitions::Image; use crate::drawing::Canvas; -use image::{GenericImage, ImageBuffer}; +use image::GenericImage; /// Draws a colored cross on an image. /// @@ -10,7 +10,7 @@ pub fn draw_cross(image: &I, color: I::Pixel, x: i32, y: i32) -> Image( where I: GenericImage, { - let mut out = ImageBuffer::new(image.width(), image.height()); + let mut out = Image::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); draw_line_segment_mut(&mut out, start, end, color); out @@ -220,7 +220,7 @@ where B: Fn(I::Pixel, I::Pixel, f32) -> I::Pixel, { - let mut out = ImageBuffer::new(image.width(), image.height()); + let mut out = Image::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); draw_antialiased_line_segment_mut(&mut out, start, end, color, blend); out diff --git a/src/drawing/polygon.rs b/src/drawing/polygon.rs index 0d9c78ba..cff5fb14 100644 --- a/src/drawing/polygon.rs +++ b/src/drawing/polygon.rs @@ -2,7 +2,7 @@ use crate::definitions::Image; use crate::drawing::line::{draw_antialiased_line_segment_mut, draw_line_segment_mut}; use crate::drawing::Canvas; use crate::point::Point; -use image::{GenericImage, ImageBuffer}; +use image::GenericImage; use std::cmp::{max, min}; /// Draws a polygon and its contents on an image. @@ -88,7 +88,7 @@ pub fn draw_hollow_polygon( where I: GenericImage, { - let mut out = ImageBuffer::new(image.width(), image.height()); + let mut out = Image::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); draw_hollow_polygon_mut(&mut out, poly, color); out @@ -138,7 +138,7 @@ where I: GenericImage, L: Fn(&mut Image, (f32, f32), (f32, f32), I::Pixel), { - let mut out = ImageBuffer::new(image.width(), image.height()); + let mut out = Image::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); draw_polygon_with_mut(&mut out, poly, color, plotter); out diff --git a/src/drawing/rect.rs b/src/drawing/rect.rs index 5d0817d1..ee2c99ea 100644 --- a/src/drawing/rect.rs +++ b/src/drawing/rect.rs @@ -2,7 +2,7 @@ use crate::definitions::Image; use crate::drawing::line::draw_line_segment_mut; use crate::drawing::Canvas; use crate::rect::Rect; -use image::{GenericImage, ImageBuffer}; +use image::GenericImage; use std::f32; /// Draws the outline of a rectangle on an image. @@ -13,7 +13,7 @@ pub fn draw_hollow_rect(image: &I, rect: Rect, color: I::Pixel) -> Image(image: &I, rect: Rect, color: I::Pixel) -> Image::Subpixel: Into + Clamp, { - let mut out = ImageBuffer::new(image.width(), image.height()); + let mut out = Image::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); draw_text_mut(&mut out, color, x, y, scale, font, text); out diff --git a/src/edges.rs b/src/edges.rs index 03a332be..38ce3d9e 100644 --- a/src/edges.rs +++ b/src/edges.rs @@ -1,9 +1,9 @@ //! Functions for detecting edges in images. -use crate::definitions::{HasBlack, HasWhite}; +use crate::definitions::{HasBlack, HasWhite, Image}; use crate::filter::{filter_clamped, gaussian_blur_f32}; use crate::kernel::{self}; -use image::{GenericImageView, GrayImage, ImageBuffer, Luma}; +use image::{GenericImageView, GrayImage, Luma}; use std::f32; /// Runs the canny edge detection algorithm. @@ -43,7 +43,7 @@ pub fn canny(image: &GrayImage, low_threshold: f32, high_threshold: f32) -> Gray .map(|(h, v)| (*h as f32).hypot(*v as f32)) .collect::>(); - let g = ImageBuffer::from_raw(image.width(), image.height(), g).unwrap(); + let g = Image::from_raw(image.width(), image.height(), g).unwrap(); // 3. Non-maximum-suppression (Make edges thinner) let thinned = non_maximum_suppression(&g, &gx, &gy); @@ -54,12 +54,12 @@ pub fn canny(image: &GrayImage, low_threshold: f32, high_threshold: f32) -> Gray /// Finds local maxima to make the edges thinner. fn non_maximum_suppression( - g: &ImageBuffer, Vec>, - gx: &ImageBuffer, Vec>, - gy: &ImageBuffer, Vec>, -) -> ImageBuffer, Vec> { + g: &Image>, + gx: &Image>, + gy: &Image>, +) -> Image> { const RADIANS_TO_DEGREES: f32 = 180f32 / f32::consts::PI; - let mut out = ImageBuffer::from_pixel(g.width(), g.height(), Luma([0.0])); + let mut out = Image::from_pixel(g.width(), g.height(), Luma([0.0])); for y in 1..g.height() - 1 { for x in 1..g.width() - 1 { let x_gradient = gx[(x, y)][0] as f32; @@ -111,15 +111,11 @@ fn non_maximum_suppression( /// Filter out edges with the thresholds. /// Non-recursive breadth-first search. -fn hysteresis( - input: &ImageBuffer, Vec>, - low_thresh: f32, - high_thresh: f32, -) -> ImageBuffer, Vec> { +fn hysteresis(input: &Image>, low_thresh: f32, high_thresh: f32) -> Image> { let max_brightness = Luma::white(); let min_brightness = Luma::black(); // Init output image as all black. - let mut out = ImageBuffer::from_pixel(input.width(), input.height(), min_brightness); + let mut out = Image::from_pixel(input.width(), input.height(), min_brightness); // Stack. Possible optimization: Use previously allocated memory, i.e. gx. let mut edges = Vec::with_capacity(((input.width() * input.height()) / 2) as usize); for y in 1..input.height() - 1 { diff --git a/src/filter/mod.rs b/src/filter/mod.rs index 8d6f5e91..46e1c148 100644 --- a/src/filter/mod.rs +++ b/src/filter/mod.rs @@ -8,7 +8,7 @@ pub use self::median::median_filter; mod sharpen; pub use self::sharpen::*; -use image::{GenericImage, GenericImageView, GrayImage, ImageBuffer, Luma, Pixel, Primitive}; +use image::{GenericImage, GenericImageView, GrayImage, Luma, Pixel, Primitive}; use crate::definitions::{Clamp, Image}; use crate::integral_image::{column_running_sum, row_running_sum}; @@ -32,7 +32,7 @@ use std::f32; #[must_use = "the function does not modify the original image"] pub fn box_filter(image: &GrayImage, x_radius: u32, y_radius: u32) -> Image> { let (width, height) = image.dimensions(); - let mut out = ImageBuffer::new(width, height); + let mut out = Image::new(width, height); if width == 0 || height == 0 { return out; } @@ -447,7 +447,7 @@ mod tests { use super::*; use crate::definitions::{Clamp, Image}; use crate::utils::gray_bench_image; - use image::{GrayImage, ImageBuffer, Luma}; + use image::{GrayImage, Luma}; use std::cmp::{max, min}; use test::black_box; @@ -773,14 +773,14 @@ mod tests { #[test] fn test_gaussian_on_u8_white_idempotent() { - let image = ImageBuffer::, Vec>::from_pixel(12, 12, Luma([255])); + let image = Image::>::from_pixel(12, 12, Luma([255])); let image2 = gaussian_blur_f32(&image, 6f32); assert_pixels_eq_within!(image2, image, 0); } #[test] fn test_gaussian_on_f32_white_idempotent() { - let image = ImageBuffer::, Vec>::from_pixel(12, 12, Luma([1.0])); + let image = Image::>::from_pixel(12, 12, Luma([1.0])); let image2 = gaussian_blur_f32(&image, 6f32); assert_pixels_eq_within!(image2, image, 1e-6); } @@ -860,7 +860,7 @@ mod benches { use crate::definitions::Image; use crate::utils::{gray_bench_image, rgb_bench_image}; use image::imageops::blur; - use image::{GenericImage, ImageBuffer, Luma, Rgb}; + use image::{GenericImage, Luma, Rgb}; use test::{black_box, Bencher}; #[bench] @@ -914,8 +914,7 @@ mod benches { ], 3, 3); b.iter(|| { - let filtered: ImageBuffer, Vec> = - filter_clamped::<_, _, i16>(&image, kernel); + let filtered: Image> = filter_clamped::<_, _, i16>(&image, kernel); black_box(filtered); }); } diff --git a/src/geometric_transformations.rs b/src/geometric_transformations.rs index 49864b61..ed802e70 100644 --- a/src/geometric_transformations.rs +++ b/src/geometric_transformations.rs @@ -2,7 +2,7 @@ //! projective transformations. use crate::definitions::{Clamp, Image}; -use image::{GenericImageView, ImageBuffer, Pixel}; +use image::{GenericImageView, Pixel}; #[cfg(feature = "rayon")] use rayon::prelude::*; use std::{cmp, ops::Mul}; @@ -330,7 +330,7 @@ where let (tx, ty) = t; let (w, h) = (width as i32, height as i32); let num_channels = P::CHANNEL_COUNT as usize; - let mut out = ImageBuffer::new(width, height); + let mut out = Image::new(width, height); for y in 0..height { let y_in = cmp::max(0, cmp::min(y as i32 - ty, h - 1)); @@ -385,7 +385,7 @@ where

::Subpixel: Into + Clamp, { let (width, height) = image.dimensions(); - let mut out = ImageBuffer::new(width, height); + let mut out = Image::new(width, height); warp_into(image, projection, interpolation, default, &mut out); out } @@ -457,7 +457,7 @@ where

::Subpixel: Into + Clamp, { let (width, height) = image.dimensions(); - let mut out = ImageBuffer::new(width, height); + let mut out = Image::new(width, height); warp_into_with(image, mapping, interpolation, default, &mut out); out } @@ -1170,7 +1170,7 @@ mod benches { b.iter(|| { let (width, height) = image.dimensions(); - let mut out = ImageBuffer::new(width, height); + let mut out = Image::new(width, height); warp_into_with( &image, |x, y| (x - 30.0, y - 30.0), diff --git a/src/gradients.rs b/src/gradients.rs index 8a99ef2a..132afa95 100644 --- a/src/gradients.rs +++ b/src/gradients.rs @@ -332,12 +332,12 @@ mod tests { use crate::filter::filter_clamped; use super::*; - use image::{ImageBuffer, Luma}; + use image::Luma; #[test] fn test_gradients_constant_image_sobel() { - let image = ImageBuffer::from_pixel(5, 5, Luma([15u8])); - let expected = ImageBuffer::from_pixel(5, 5, Luma([0u16])); + let image = Image::from_pixel(5, 5, Luma([15u8])); + let expected = Image::from_pixel(5, 5, Luma([0u16])); assert_pixels_eq!( gradients( @@ -351,8 +351,8 @@ mod tests { } #[test] fn test_gradients_constant_image_scharr() { - let image = ImageBuffer::from_pixel(5, 5, Luma([15u8])); - let expected = ImageBuffer::from_pixel(5, 5, Luma([0u16])); + let image = Image::from_pixel(5, 5, Luma([15u8])); + let expected = Image::from_pixel(5, 5, Luma([0u16])); assert_pixels_eq!( gradients( @@ -366,8 +366,8 @@ mod tests { } #[test] fn test_gradients_constant_image_prewitt() { - let image = ImageBuffer::from_pixel(5, 5, Luma([15u8])); - let expected = ImageBuffer::from_pixel(5, 5, Luma([0u16])); + let image = Image::from_pixel(5, 5, Luma([15u8])); + let expected = Image::from_pixel(5, 5, Luma([0u16])); assert_pixels_eq!( gradients( @@ -381,8 +381,8 @@ mod tests { } #[test] fn test_gradients_constant_image_roberts() { - let image = ImageBuffer::from_pixel(5, 5, Luma([15u8])); - let expected = ImageBuffer::from_pixel(5, 5, Luma([0u16])); + let image = Image::from_pixel(5, 5, Luma([15u8])); + let expected = Image::from_pixel(5, 5, Luma([0u16])); assert_pixels_eq!( gradients( diff --git a/src/haar.rs b/src/haar.rs index 8a77c34c..8eb7cd39 100644 --- a/src/haar.rs +++ b/src/haar.rs @@ -3,7 +3,7 @@ //! [Haar-like features]: https://en.wikipedia.org/wiki/Haar-like_features use crate::definitions::{HasBlack, HasWhite, Image}; -use image::{GenericImage, GenericImageView, ImageBuffer, Luma}; +use image::{GenericImage, GenericImageView, Luma}; use itertools::Itertools; use std::marker::PhantomData; use std::ops::Range; @@ -386,7 +386,7 @@ where I: GenericImage, I::Pixel: HasBlack + HasWhite, { - let mut out = ImageBuffer::new(image.width(), image.height()); + let mut out = Image::new(image.width(), image.height()); out.copy_from(image, 0, 0).unwrap(); draw_haar_feature_mut(&mut out, feature); out diff --git a/src/hog.rs b/src/hog.rs index bf574546..793ae098 100644 --- a/src/hog.rs +++ b/src/hog.rs @@ -5,7 +5,7 @@ use crate::definitions::{Clamp, Image}; use crate::filter::filter_clamped; use crate::kernel::{self}; use crate::math::l2_norm; -use image::{GenericImage, GrayImage, ImageBuffer, Luma}; +use image::{GenericImage, GrayImage, Luma}; use num::Zero; use std::f32; @@ -373,7 +373,7 @@ impl Interpolation { pub fn render_hist_grid(star_side: u32, grid: &View3d<'_, f32>, signed: bool) -> Image> { let width = grid.lengths[1] as u32 * star_side; let height = grid.lengths[2] as u32 * star_side; - let mut out = ImageBuffer::new(width, height); + let mut out = Image::new(width, height); for y in 0..grid.lengths[2] { let y_window = y as u32 * star_side; diff --git a/src/hough.rs b/src/hough.rs index ea285ebf..659a4813 100644 --- a/src/hough.rs +++ b/src/hough.rs @@ -5,7 +5,7 @@ use crate::definitions::Image; use crate::drawing::draw_line_segment_mut; use crate::suppress::suppress_non_maximum; -use image::{GenericImage, GenericImageView, GrayImage, ImageBuffer, Luma, Pixel}; +use image::{GenericImage, GenericImageView, GrayImage, Luma, Pixel}; use std::f32; /// A detected line, in polar coordinates. @@ -45,7 +45,7 @@ pub fn detect_lines(image: &GrayImage, options: LineDetectionOptions) -> Vec, Vec> = ImageBuffer::new(2 * rmax as u32 + 1, 180u32); + let mut acc: Image> = Image::new(2 * rmax as u32 + 1, 180u32); // Precalculate values of (cos(m), sin(m)) let lut: Vec<(f32, f32)> = (0..180u32) @@ -538,7 +538,7 @@ mod tests { #[cfg(test)] mod benches { use super::*; - use image::{GrayImage, ImageBuffer, Luma}; + use image::{GrayImage, Luma}; use test::{black_box, Bencher}; macro_rules! bench_detect_lines { @@ -572,7 +572,7 @@ mod benches { bench_detect_lines!(bench_detect_line_neg10_120, -10.0, 120); fn chessboard(width: u32, height: u32) -> GrayImage { - ImageBuffer::from_fn(width, height, |x, y| { + GrayImage::from_fn(width, height, |x, y| { if (x + y) % 2 == 0 { Luma([255u8]) } else { diff --git a/src/integral_image.rs b/src/integral_image.rs index d9f285c1..cabeac18 100644 --- a/src/integral_image.rs +++ b/src/integral_image.rs @@ -467,7 +467,7 @@ mod tests { use crate::definitions::Image; use crate::property_testing::GrayTestImage; use crate::utils::pixel_diff_summary; - use image::{GenericImage, ImageBuffer, Luma}; + use image::{GenericImage, Luma}; use quickcheck::{quickcheck, TestResult}; #[test] @@ -561,7 +561,7 @@ mod tests { { let (in_width, in_height) = image.dimensions(); let (out_width, out_height) = (in_width + 1, in_height + 1); - let mut out = ImageBuffer::from_pixel(out_width, out_height, Luma([0u32])); + let mut out = Image::from_pixel(out_width, out_height, Luma([0u32])); for y in 1..out_height { for x in 0..out_width { diff --git a/src/map.rs b/src/map.rs index 466682e5..4b188495 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,6 +1,6 @@ //! Functions for mapping over pixels, colors or subpixels of images. -use image::{GenericImage, ImageBuffer, Luma, LumaA, Pixel, Primitive, Rgb, Rgba}; +use image::{GenericImage, Luma, LumaA, Pixel, Primitive, Rgb, Rgba}; use crate::definitions::Image; @@ -82,7 +82,7 @@ where F: Fn(P::Subpixel) -> S, { let (width, height) = image.dimensions(); - let mut out: ImageBuffer, Vec> = ImageBuffer::new(width, height); + let mut out: Image> = Image::new(width, height); for y in 0..height { for x in 0..width { @@ -179,7 +179,7 @@ where F: Fn(P) -> Q, { let (width, height) = image.dimensions(); - let mut out: ImageBuffer> = ImageBuffer::new(width, height); + let mut out: Image = Image::new(width, height); for y in 0..height { for x in 0..width { @@ -282,7 +282,7 @@ where assert_eq!(image1.dimensions(), image2.dimensions()); let (width, height) = image1.dimensions(); - let mut out: ImageBuffer> = ImageBuffer::new(width, height); + let mut out: Image = Image::new(width, height); for y in 0..height { for x in 0..width { @@ -331,7 +331,7 @@ where F: Fn(u32, u32, P) -> Q, { let (width, height) = image.dimensions(); - let mut out: ImageBuffer> = ImageBuffer::new(width, height); + let mut out: Image = Image::new(width, height); for y in 0..height { for x in 0..width { diff --git a/src/property_testing.rs b/src/property_testing.rs index ed22d5dd..5346ea66 100644 --- a/src/property_testing.rs +++ b/src/property_testing.rs @@ -4,7 +4,7 @@ //! [quickcheck]: https://github.com/BurntSushi/quickcheck use crate::definitions::Image; -use image::{GenericImage, ImageBuffer, Luma, Pixel, Primitive, Rgb}; +use image::{GenericImage, Luma, Pixel, Primitive, Rgb}; use quickcheck::{Arbitrary, Gen}; use rand_distr::{Distribution, Standard}; use std::fmt; @@ -25,7 +25,7 @@ where { fn arbitrary(g: &mut Gen) -> Self { let (width, height) = small_image_dimensions(g); - let mut image = ImageBuffer::new(width, height); + let mut image = Image::new(width, height); for y in 0..height { for x in 0..width { let pix: T = ArbitraryPixel::arbitrary(g); @@ -77,7 +77,7 @@ fn copy_sub(image: &I, x: u32, y: u32, width: u32, height: u32) -> Image GrayImage { - ImageBuffer::from_fn(width, height, |x, y| { + GrayImage::from_fn(width, height, |x, y| { if (x + y) % 2 == 0 { Luma([255u8]) } else { diff --git a/src/suppress.rs b/src/suppress.rs index fa191745..0431d646 100644 --- a/src/suppress.rs +++ b/src/suppress.rs @@ -1,19 +1,19 @@ //! Functions for suppressing non-maximal values. -use crate::definitions::{Position, Score}; -use image::{GenericImage, ImageBuffer, Luma, Primitive}; +use crate::definitions::{Image, Position, Score}; +use image::{GenericImage, Luma, Primitive}; use std::cmp; /// Returned image has zeroes for all inputs pixels which do not have the greatest /// intensity in the (2 * radius + 1) square block centred on them. /// Ties are resolved lexicographically. -pub fn suppress_non_maximum(image: &I, radius: u32) -> ImageBuffer, Vec> +pub fn suppress_non_maximum(image: &I, radius: u32) -> Image> where I: GenericImage>, C: Primitive + Ord, { let (width, height) = image.dimensions(); - let mut out: ImageBuffer, Vec> = ImageBuffer::new(width, height); + let mut out: Image> = Image::new(width, height); if width == 0 || height == 0 { return out; } @@ -174,10 +174,10 @@ where #[cfg(test)] mod tests { use super::{local_maxima, suppress_non_maximum}; - use crate::definitions::{Position, Score}; + use crate::definitions::{Image, Position, Score}; use crate::property_testing::GrayTestImage; use crate::utils::pixel_diff_summary; - use image::{GenericImage, GrayImage, ImageBuffer, Luma, Primitive}; + use image::{GenericImage, GrayImage, Luma, Primitive}; use quickcheck::{quickcheck, TestResult}; use std::cmp; @@ -274,13 +274,13 @@ mod tests { /// Reference implementation of suppress_non_maximum. Used to validate /// the (presumably faster) actual implementation. - fn suppress_non_maximum_reference(image: &I, radius: u32) -> ImageBuffer, Vec> + fn suppress_non_maximum_reference(image: &I, radius: u32) -> Image> where I: GenericImage>, C: Primitive + Ord, { let (width, height) = image.dimensions(); - let mut out = ImageBuffer::new(width, height); + let mut out = Image::new(width, height); out.copy_from(image, 0, 0).unwrap(); let iradius = radius as i32; @@ -345,8 +345,9 @@ mod tests { #[cfg(test)] mod benches { use super::{local_maxima, suppress_non_maximum, tests::T}; + use crate::definitions::Image; use crate::noise::gaussian_noise_mut; - use image::{GrayImage, ImageBuffer, Luma}; + use image::{GrayImage, Luma}; use test::Bencher; #[bench] @@ -376,7 +377,7 @@ mod benches { fn bench_suppress_non_maximum_increasing_gradient(b: &mut Bencher) { // Increasing gradient in both directions. This can be a worst-case for // early-abort strategies. - let img = ImageBuffer::from_fn(40, 20, |x, y| Luma([(x + y) as u8])); + let img = Image::from_fn(40, 20, |x, y| Luma([(x + y) as u8])); b.iter(|| suppress_non_maximum(&img, 7)); } @@ -384,7 +385,7 @@ mod benches { fn bench_suppress_non_maximum_decreasing_gradient(b: &mut Bencher) { let width = 40u32; let height = 20u32; - let img = ImageBuffer::from_fn(width, height, |x, y| { + let img = Image::from_fn(width, height, |x, y| { Luma([((width - x) + (height - y)) as u8]) }); b.iter(|| suppress_non_maximum(&img, 7)); @@ -392,21 +393,21 @@ mod benches { #[bench] fn bench_suppress_non_maximum_noise_7(b: &mut Bencher) { - let mut img: GrayImage = ImageBuffer::new(40, 20); + let mut img: GrayImage = GrayImage::new(40, 20); gaussian_noise_mut(&mut img, 128f64, 30f64, 1); b.iter(|| suppress_non_maximum(&img, 7)); } #[bench] fn bench_suppress_non_maximum_noise_3(b: &mut Bencher) { - let mut img: GrayImage = ImageBuffer::new(40, 20); + let mut img: GrayImage = GrayImage::new(40, 20); gaussian_noise_mut(&mut img, 128f64, 30f64, 1); b.iter(|| suppress_non_maximum(&img, 3)); } #[bench] fn bench_suppress_non_maximum_noise_1(b: &mut Bencher) { - let mut img: GrayImage = ImageBuffer::new(40, 20); + let mut img: GrayImage = GrayImage::new(40, 20); gaussian_noise_mut(&mut img, 128f64, 30f64, 1); b.iter(|| suppress_non_maximum(&img, 1)); } diff --git a/src/utils.rs b/src/utils.rs index 9af25dff..033fa286 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -88,8 +88,10 @@ macro_rules! gray_image { // Empty image with the given channel type (type: $channel_type:ty) => { { - use image::{ImageBuffer, Luma}; - ImageBuffer::, Vec<$channel_type>>::new(0, 0) + use image::Luma; + use $crate::definitions::Image; + + Image::>::new(0, 0) } }; // Non-empty image of default channel type u8 @@ -99,7 +101,8 @@ macro_rules! gray_image { // Non-empty image of given channel type (type: $channel_type:ty, $( $( $x: expr ),*);*) => { { - use image::{ImageBuffer, Luma}; + use image::Luma; + use $crate::definitions::Image; let nested_array = [ $( [ $($x),* ] ),* ]; let height = nested_array.len() as u32; @@ -110,7 +113,7 @@ macro_rules! gray_image { .cloned() .collect(); - ImageBuffer::, Vec<$channel_type>>::from_raw(width, height, flat_array) + Image::>::from_raw(width, height, flat_array) .unwrap() } } @@ -190,8 +193,10 @@ macro_rules! rgb_image { // Empty image with the given channel type (type: $channel_type:ty) => { { - use image::{ImageBuffer, Rgb}; - ImageBuffer::, Vec<$channel_type>>::new(0, 0) + use image::Rgb; + use $crate::definitions::Image; + + Image::>::new(0, 0) } }; // Non-empty image of default channel type u8 @@ -201,7 +206,9 @@ macro_rules! rgb_image { // Non-empty image of given channel type (type: $channel_type:ty, $( $( [$r: expr, $g: expr, $b: expr]),*);*) => { { - use image::{ImageBuffer, Rgb}; + use image::Rgb; + use $crate::definitions::Image; + let nested_array = [$( [ $([$r, $g, $b]),*]),*]; let height = nested_array.len() as u32; let width = nested_array[0].len() as u32; @@ -211,7 +218,7 @@ macro_rules! rgb_image { .cloned() .collect(); - ImageBuffer::, Vec<$channel_type>>::from_raw(width, height, flat_array) + Image::>::from_raw(width, height, flat_array) .unwrap() } } @@ -291,8 +298,10 @@ macro_rules! rgba_image { // Empty image with the given channel type (type: $channel_type:ty) => { { - use image::{ImageBuffer, Rgba}; - ImageBuffer::, Vec<$channel_type>>::new(0, 0) + use image::Rgba; + use $crate::definitions::Image; + + Image::>::new(0, 0) } }; // Non-empty image of default channel type u8 @@ -302,7 +311,9 @@ macro_rules! rgba_image { // Non-empty image of given channel type (type: $channel_type:ty, $( $( [$r: expr, $g: expr, $b: expr, $a: expr]),*);*) => { { - use image::{ImageBuffer, Rgba}; + use image::Rgba; + use $crate::definitions::Image; + let nested_array = [$( [ $([$r, $g, $b, $a]),*]),*]; let height = nested_array.len() as u32; let width = nested_array[0].len() as u32; @@ -312,7 +323,7 @@ macro_rules! rgba_image { .cloned() .collect(); - ImageBuffer::, Vec<$channel_type>>::from_raw(width, height, flat_array) + Image::>::from_raw(width, height, flat_array) .unwrap() } } diff --git a/tests/regression.rs b/tests/regression.rs index b34fa150..325a8153 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -18,11 +18,11 @@ extern crate imageproc; use std::{env, f32, path::Path}; use image::{ - DynamicImage, GrayImage, ImageBuffer, Luma, Pixel, PixelWithColorType, Rgb, RgbImage, Rgba, - RgbaImage, + DynamicImage, GrayImage, Luma, Pixel, PixelWithColorType, Rgb, RgbImage, Rgba, RgbaImage, }; use imageproc::contrast::ThresholdType; +use imageproc::definitions::Image; use imageproc::filter::bilateral::GaussianEuclideanColorDistance; use imageproc::filter::bilateral_filter; use imageproc::kernel::{self}; @@ -73,8 +73,8 @@ impl FromDynamic for RgbaImage { fn compare_to_truth(input_file_name: &str, truth_file_name: &str, op: F) where P: Pixel + PixelWithColorType, - ImageBuffer>: FromDynamic, - F: Fn(&ImageBuffer>) -> ImageBuffer>, + Image

: FromDynamic, + F: Fn(&Image

) -> Image

, { compare_to_truth_with_tolerance(input_file_name, truth_file_name, op, 0u8); } @@ -88,10 +88,10 @@ fn compare_to_truth_with_tolerance( tol: u8, ) where P: Pixel + PixelWithColorType, - ImageBuffer>: FromDynamic, - F: Fn(&ImageBuffer>) -> ImageBuffer>, + Image

: FromDynamic, + F: Fn(&Image

) -> Image

, { - let input = ImageBuffer::>::from_dynamic(&load_image_or_panic( + let input = Image::

::from_dynamic(&load_image_or_panic( Path::new(INPUT_DIR).join(input_file_name), )); let actual = op(&input); @@ -99,29 +99,26 @@ fn compare_to_truth_with_tolerance( } /// Checks that an image matches a 'truth' image. -fn compare_to_truth_image

(actual: &ImageBuffer>, truth_file_name: &str) +fn compare_to_truth_image

(actual: &Image

, truth_file_name: &str) where P: Pixel + PixelWithColorType, - ImageBuffer>: FromDynamic, + Image

: FromDynamic, { compare_to_truth_image_with_tolerance(actual, truth_file_name, 0u8); } /// Checks that an image matches a 'truth' image to within a given per-pixel tolerance. -fn compare_to_truth_image_with_tolerance

( - actual: &ImageBuffer>, - truth_file_name: &str, - tol: u8, -) where +fn compare_to_truth_image_with_tolerance

(actual: &Image

, truth_file_name: &str, tol: u8) +where P: Pixel + PixelWithColorType, - ImageBuffer>: FromDynamic, + Image

: FromDynamic, { if should_regenerate() { actual .save(Path::new(TRUTH_DIR).join(truth_file_name)) .unwrap(); } else { - let truth = ImageBuffer::>::from_dynamic(&load_image_or_panic( + let truth = Image::

::from_dynamic(&load_image_or_panic( Path::new(TRUTH_DIR).join(truth_file_name), )); assert_pixels_eq_within!(*actual, truth, tol);