为何我实现的Stackblur模糊效果仅为预期强度的一半?
Rust Stackblur算法实现问题
我在Rust中实现了Mario Klingemann提出的Stackblur算法,并且将水平遍历步骤重写为使用迭代器而非索引访问。但对比GIMP的模糊效果,目前的实现需要运行两次模糊才能达到完整强度,直接将模糊半径翻倍则会出现晕轮效应。
/// 执行Stackblur的水平遍历步骤 /// 输入需为线性RGB色彩空间 /// 需要运行两次才能达到完整模糊效果! 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); // 使用左边缘像素填充队列 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)); } // 补充起始位置像素填充队列 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() { // 计算并设置当前像素值 *px = pixel( queue_r.iter().sum::<u32>() / radius, queue_g.iter().sum::<u32>() / radius, queue_b.iter().sum::<u32>() / radius, ); // 移出队列中卷积核左边缘的元素 let _ = queue_r.pop_front(); let _ = queue_g.pop_front(); let _ = queue_b.pop_front(); // 将卷积核右边缘的新元素加入队列 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)); } }); }
效果对比:
- 半径为15时运行两次
blur_horiz的效果:
- 半径为30时运行一次
blur_horiz的效果:
内容的提问来源于stack exchange,提问作者owenthewizard
相关产品推荐
相关产品推荐

