-
Notifications
You must be signed in to change notification settings - Fork 148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add fast blur algorithm #683
Conversation
607707b
to
d8771e1
Compare
Thanks for opening another PR in this repo, I feel it is much better placed here. I don't have much knowledge about the specific blurring algorithm but I am happy to help with the code quality and maybe adding some benchmarks. |
Some beautification is needed |
channel_num * idx + channel | ||
} | ||
|
||
fn my_fast_horizontal_blur<P: Primitive>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I renamed this to horizontal_fast_blur_half
in the original PR.
/ (-4.0 * (w_l) - 4.0); | ||
let m = f32::round(m_ideal) as usize; | ||
|
||
let mut box_sizes: Vec<usize> = vec![]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vec::with_capcity(n)
or iter
+ collect
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I chose the latter. As n is usually between 3 and 6 (and in our case it is always 3) the effect is little, that's why I optimized this code for readability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the explicit Vec<usize>
type for readability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's already gone (in the PR to the image
crate).
channel: usize, | ||
channel_num: usize, | ||
) -> P { | ||
let x = min(width as isize - 1, max(0, x)) as usize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
replace with clamp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed (again in original PR)
/// Kovesi, P.: Fast Almost-Gaussian Filtering The Australian Pattern | ||
/// Recognition Society Conference: DICTA 2010. December 2010. Sydney. | ||
pub fn fast_blur<P: Pixel>( | ||
image_buffer: &ImageBuffer<P, Vec<P::Subpixel>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace with Image
type alias from crate::definitions
and rename arg to image
or img
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- fix this once it is decided that 'fast_blur
will land in
imageproc`
pub fn fast_blur<P: Pixel>( | ||
image_buffer: &ImageBuffer<P, Vec<P::Subpixel>>, | ||
sigma: f32, | ||
) -> ImageBuffer<P, Vec<P::Subpixel>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace with Image
type alias
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- fix this once it is decided that
fast_blur
will land inimageproc
let val = P::from(val).unwrap(); | ||
|
||
out_samples[channel_idx(channel, i + j * height, channel_num)] = val; | ||
vals[channel] = vals[channel] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expression is soo long!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I extracted the index into a speaking variable. I hope this makes the code more readable.
for j in 0..width { | ||
for channel in 0..channel_num { | ||
let val = vals[channel] / (2.0 * r as f32 + 1.0); | ||
let val = if val < min_value { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace entire if {} else if {} else {} with val.clamp(min_value, max_value)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
) -> Vec<P> { | ||
let channel_size = width * height; | ||
|
||
let mut out_samples: Vec<P> = vec![P::from(0).unwrap(); channel_size * channel_num]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for explicit Vec type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
/// Test blur doesn't panick when passed 0.0 | ||
fn test_fast_blur_zero() { | ||
let image = RgbaImage::new(50, 50); | ||
let _ = super::fast_blur(&image, -1.0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add use super::*
above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
@@ -0,0 +1,163 @@ | |||
use std::cmp::{max, min}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All min/max function calls can be avoided
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
}; | ||
let w_u = w_l + 2.0; | ||
|
||
let m_ideal = (12.0 * sigma * sigma |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expression is too long, I'm sure there is a way to simplify it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It`s II (5) in https://peterkovesi.com/papers/FastGaussianSmoothing.pdf. It results from inverting the equation of ideal sigma and the one coming from repeated box blurs. I don't know how to further simplify this polynomial as all of the terms are linearly independent (as polynomials).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let m_ideal = 0.25 * (n as f32) * (w_l + 3.0) - 3.0 * sigma.powi(2) * (w_l + 1.0).recip();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, now the formula fits into one line.
use image::RgbaImage; | ||
|
||
#[test] | ||
/// Test blur doesn't panick when passed 0.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's -1.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed already in original PR
@cospectrum thank you for your review comments. I am going to address them here and in my PR on the |
I just wanted to give a short status report (I also cross post this comment to #683)
What would be the next steps? |
merged into |
As the code is now in the |
This PR is an alternative to image-rs/image#2302 which adds the corresponding functionality in the
image
crate. It adds a fast approximation of Gaussian blur to this library.It is an attempt to solve image-rs/image#986. For the discussion discussion please refer to the PR in
image
until it is decided where the functionality will go.