图像降采样算法

7
有人知道微软在Paint中用了哪些算法来缩小图片吗?
我想开发一个小软件(仅供个人使用)来缩小大量图片(使用Java)。在使用Java的“内置”函数NearestNeighbor、Bilinear和Bicubic后,结果质量很差...我使用了Lanczos算法,结果好多了,但仍然没有达到MS Paint的效果。注意:所使用的Paint版本是Windows 7版,我使用的Lanczos实现是Millie项目LanczosResamplePlugin.java中的,而内置的Java函数来自Graphics2D:
    g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
    g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
    g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);

如果有人有想法可以达到相同的高质量结果,这将对我的结果图片和知识也有帮助。

以下是一些结果:

(我不会发布NN、双线性和双三次结果,因为它们给出的结果质量非常差)

下面是一张风景图片(在Google图片中找到)。原始文件大小为1680x1050,原始文件中的草地非常锐利(所以Paint的结果似乎比Lanczos更好)。

原始图像可以在此处查看: landscape-wallpaper-11a.jpg

Lanczos结果:

Lanczos landscape

vs Paint 结果:

Paint landscape

下面是另一张图片(个人图片),附有一些文字说明。您可以注意到,在Lanczos处理结果中,文本不太清晰易读(不够锐利),而在Paint处理结果中则较为清晰。此外,在黑色标题文本和白色文本区域之间,在Lanczos结果中存在一些噪点,而在Paint结果中却不存在。在底部,纸上的URL在第一种结果中完全模糊/不可读,在Paint结果中则可读。

Lanczos cheese

vs Paint 结果:

Paint chesse

我首先认为微软使用了两种算法:一种用于缩小图片,另一种用于锐化结果图像?但是由于上一个示例中底部的url仍然可读,这可能不是由于缩小结果的锐化造成的...?
谢谢
编辑
好的,我有点傻...图片上的噪声是由于jpeg压缩质量引起的(当我保存图片时,我的Java代码没有设置它)。
下面是png格式的结果,所以没有噪声。但结果仍然无法像画笔一样读取。
Lanczos cheese png

Lanczos cheese png


你也有原始图片的链接吗? - Lasse V. Karlsen
我已经将第一个示例原始图片的链接放在了结果上方。对于第二个文件,我已经找到了上传和共享的方法(文件大小为3.5Mo)。 - Alexxx
旧版的 MSPaint 在缩小图片时表现得很糟糕,而 Windows 7 的 Paint 明显有所改进。 - Ander Biguri
3个回答

6

MSPaint使用双线性插值,然后使用卷积核锐化图像:

0.0,-0.125,0.0

-0.125,1.5,-0.125

0.0,-0.125,0.0

ImageMagick命令:

magick image.png -scale 512 -morphology Convolve "3x3: 0.0, -0.125, 0.0 -0.125, 1.5, -0.125 0.0, -0.125, 0.0" image_resized.png

1
据我所知,这似乎是最正确的答案(-scale,然后卷积),或者至少非常接近。但在等比例缩放时,较小的图像尺寸如何舍入有一个显着的区别 - 因此,例如,如果限制因素是图像高度,则 mspaint 有时可能会生成宽度比 ImageMagick 生成的少1像素的图像。真希望我可以多次点赞,我已经想了好几年了! - dialer

3

好的,我明白了!事实上,在MS Paint(Win7)中并没有魔法。它必须使用众所周知的Lanczos算法来调整图像大小(向下和向上?),这似乎是最好的一般重采样算法(在XnView中,我们可以选择重采样算法,在那里它是默认选项)。

因此,我发现了另外两个Java实现,它们分别给出不同的结果:

原始图像: landscape-wallpaper-11a.jpg

  1. 来自Milli项目的Lanczos 此处 landscape Lanczos 1

  2. 来自“atyou”日本博客的Lanczos 此处 landscape Lanczos 2

  3. 来自“zattonaka”日本博客的Lanczos 此处 landscape Lanczos 3

  4. 来自MS Paint Win7的算法(Lanczos?) landscape MS Paint

我的第二组结果是我个人图片中的:

  1. 从Milli项目这里得到 cheese Lanczos 1

  2. 从"atyou"日本博客这里得到 cheese Lanczos 2

  3. 从"zattonaka"日本博客这里得到 cheese Lanczos 3

  4. 来自MS Paint Win7的算法(Lanczos?) cheese MS Paint

以上项目中,第3项的结果似乎最接近MS Paint的结果(但不完全相同)。它具有清晰易读的文本(第二个测试)和与原始图像中一样锐利的草地(第一个测试)。

此外,正如我之前在问题编辑部分中提到的那样,噪点是由于保存时使用了jpeg压缩。上面的结果是PNG格式,因此不会受到jpeg压缩引起的伪影的影响。


有关调整大小滤镜及其参数的良好参考,请参阅ImageMagick页面https://www.imagemagick.org/Usage/filter/和https://www.imagemagick.org/Usage/filter/nicolas/。 - fmw42

2
与Alex所说的相反,我很确定Paint使用由GDI+提供的高质量双三次方法,而不是像Zattonaka的实现。您可以通过要求两者将交替的黑白扫描线图像缩小一行来验证。
在Paint中,黑白扫描线保留在顶部和底部,但在中间淡入深灰色。
Zattonaka的实现始终保留交替的黑白扫描线,但删除一条扫描线。原因在于这段代码:
int bsx = (int)(dx / scale), bsy = (int)(dy / scale);

虽然这在人造条形码图像上可以得到良好的结果,但它实际上是最近邻缩放加上Lanczos预处理阶段。对于一些真实世界的图像,它将表现得非常糟糕,与最近邻缩放不起作用的原因相同:它倾向于削减小细节。由于Lanczos卷积,Zattonaka的实现并不像最近邻缩放那样糟糕,但有些图像仍然会变得非常糟糕。
如果你想要类似于Paint的东西,最好尝试一个好的双三次插值器,再进行预锐化以抵消缩小模糊。你可能需要微调一下。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接