image-processing - 这种用于图像缩放的最近邻算法有什么问题?

标签 image-processing rust nearest-neighbor

我已经蹲了好几天试图找出在将图像缩放一半大小时我的最近邻插值有什么问题。我使用 Rust,但我认为它不如算法重要:

/// Interpolate using nearest neighbor.
pub fn nearest(mut src: &mut Image, w2: i32, h2: i32) -> RasterResult<()> {

    // Compute scale
    let x_scale: f64 = src.width as f64 / w2 as f64;
    let y_scale: f64 = src.height as f64 / h2 as f64;

    // Create destination image
    let mut dest = Image::blank(w2, h2);

    // Loop thru destination image's pixels
    for y2 in 0..h2 {
        for x2 in 0..w2 {

            // Get location from src using nearest neighbor
            let x1: i32 = ( x2 as f64 * x_scale ).floor() as i32;
            let y1: i32 = ( y2 as f64 * y_scale ).floor() as i32;
            let pixel = try!(src.get_pixel(x1, y1));

            // Apply the pixels
            try!(dest.set_pixel(x2, y2, pixel));
        }
    }

    // Update the source image
    src.width = dest.width;
    src.height = dest.height;
    src.bytes = dest.bytes;

    Ok(())
}

我的调用代码:

// Open
let mut image = raster::open(r"test.png").unwrap();

// Resize to half
raster::interpolate::nearest(&mut image, 256, 128).unwrap();

// Save
raster::save(&image, r"out.png").unwrap();

它适用于常规图像,但不适用于特殊情况。 这是测试图像: test image

用我的代码缩放到一半:

scaled to half with my code

这里是 Photoshop 的比较:

Scaled to half with Photoshop's

我用 GD 进行了测试,它产生了与 Photoshop 相似的结果。

我的调查使我认为我对源像素(红色方 block )的计算与其他像素(绿色方 block )相比有偏差:

zoom of problem area

我也尝试寻找 into GD's source code获得线索,但我不完全理解它的作用。

澄清一下,我不是在谈论使用不同的插值方法,例如双线性和双三次。我正在将我的最近邻算法及其结果与 Photoshop 和 GD 的最近邻算法的结果进行比较。我不是在问为什么我在 Photoshop 中的结果很丑,因为我使用了最近邻算法。

(测试图片由 Jonas Berlin 通过 Eric Brasseur 提供)

最佳答案

进行最近邻插值的一种稍微好一点的方法是使插值经过目标像素的中心而不是它们的左上角。在您的代码中,这意味着添加 0.5x2y2在计算 x1 时和 y1 .

let x1: i32 = ( (x2 as f64 + 0.5) * x_scale ).floor() as i32;
let y1: i32 = ( (y2 as f64 + 0.5) * y_scale ).floor() as i32;

当您按 1/2 缩放时,这不一定会产生更好的结果:每个目标像素都是从 2x2 源区域中选择的,因此您选择哪个源像素并不重要。但是当按 1/3 缩放时,这意味着您选择 3x3 区域的中心而不是左上角,这样更好。

Photoshop 可能使用这样的方法,这就是为什么您会看到不同的结果。

请注意,即使这使测试图像看起来缩放得更好,也可以制作另一张使用新算法看起来很糟糕的测试图像。将您的测试图像偏移 (1,1) 可能会做到这一点。

关于image-processing - 这种用于图像缩放的最近邻算法有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45249860/

相关文章:

android - 数字识别的建议

matlab - 从matlab中的特定文件夹访问图像

rust - 尽管正确安装了VC++,使用链接的Rust链接失败(代码1120)

c - 邻居发现 C

python - 找到 map 中每个像素的最近邻居

c# - 图像处理

image-processing - 如何从可变数量的图像描述符 (SURF) 创建单个恒定长度特征向量

types - 如何将一个方法的 'self'值传递给另一个方法?

rust - 在 Rust 中,如何从 HashMap 的键创建 HashSet?

java - Java 中的距离度量