【问题标题】:Why is my gaussian blur approximation half strength?为什么我的高斯模糊近似强度是一半?
【发布时间】:2021-05-19 06:41:21
【问题描述】:

我在 Rust 中实现了 stackblur algorithm(由 Mario Klingemann 编写),并重写了水平传递以使用迭代器而不是索引。但是,与 GIMP 相比,模糊需要运行两次才能达到全部强度。将半径加倍会引入光晕。

/// Performs a horizontal pass of stackblur.
/// Input is expected to be in linear RGB color space.
/// Needs to be ran twice for full effect!
pub fn blur_horiz(src: &mut [u32], width: NonZeroUsize, radius: NonZeroU8) {
    let width = width.get();
    let radius = u32::from(min(radius.get() | 1, 255));
    let r = radius as usize;

    src.chunks_exact_mut(width).for_each(|row| {
        let first = *row.first().unwrap();
        let mut last = *row.last().unwrap();

        let mut queue_r = VecDeque::with_capacity(r);
        let mut queue_g = VecDeque::with_capacity(r);
        let mut queue_b = VecDeque::with_capacity(r);

        // fill with left edge pixel
        for v in iter::repeat(first).take(r / 2 + 1) {
            queue_r.push_back(red(v));
            queue_g.push_back(green(v));
            queue_b.push_back(blue(v));
        }

        // fill with starting pixels
        for v in row.iter().copied().chain(iter::repeat(last)).take(r / 2) {
            queue_r.push_back(red(v));
            queue_g.push_back(green(v));
            queue_b.push_back(blue(v));
        }

        debug_assert_eq!(queue_r.len(), r);

        let mut row_iter = peek_nth(row.iter_mut());

        while let Some(px) = row_iter.next() {
            // set pixel
            *px = pixel(
                queue_r.iter().sum::<u32>() / radius,
                queue_g.iter().sum::<u32>() / radius,
                queue_b.iter().sum::<u32>() / radius,
            );

            // drop left edge of kernel
            let _ = queue_r.pop_front();
            let _ = queue_g.pop_front();
            let _ = queue_b.pop_front();

            // add right edge of kernel
            let next = **row_iter.peek_nth(r / 2).unwrap_or(&&mut last);
            queue_r.push_back(red(next));
            queue_g.push_back(green(next));
            queue_b.push_back(blue(next));
        }
    });
}

[Full Code]

以 radius=15 运行两次 blur_horiz 后的结果:

以 radius=30 运行一次 blur_horiz 后的结果:

【问题讨论】:

  • 请注意,您实现的是常规框过滤器,而不是 stackblur(使用三角形过滤器)。
  • “发挥全部力量”是什么意思?你能澄清一下你的意思吗?
  • @CrisLuengo 与高斯模糊相比,例如GIMP。我将进行编辑以添加说明。
  • @Jmb 哦,我想这可以解释吗?由于框模糊的重复通道近似于高斯模糊。
  • Gimp 可能根据 sigma 参数而不是半径来调整其过滤器的大小。此外,您创建了一个全尺寸为“半径”的过滤器,因此您的“半径”参数实际上是过滤器的全尺寸,而不是实际半径。

标签: image-processing rust blur gaussianblur


【解决方案1】:

请注意,您实现的是常规框过滤器,而不是 stackblur(使用三角形过滤器)。此外,使用半径为R 的框进行两次过滤相当于使用半径为2*R 的三角形进行过滤一次,这解释了为什么在运行blur_horiz 两次时会得到预期的结果。

【讨论】:

    猜你喜欢
    • 2018-07-16
    • 2014-06-22
    • 1970-01-01
    • 1970-01-01
    • 2017-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多