图像下采样算法

时间:2011-05-26 05:10:31

标签: c++ c image image-processing image-manipulation

我可以使用什么样的最佳重采样算法将图像分成原始大小的一半。速度是最重要的,但它不应该降低质量太差。我基本上试图生成图像金字塔。

我原本计划跳过像素。这是最好的方式吗?从我所看到的,像素跳过产生的图像太尖锐了。有人试过这个评论。我的图片包含类似this.

的地图数据

6 个答案:

答案 0 :(得分:28)

跳过像素会导致混叠,其中高频变化(例如交替的亮/暗带)将转换为低频(例如恒定亮或暗)。

在没有混叠的情况下缩小到一半的最快方法是将2x2像素平均为单个像素。使用更复杂的还原内核可以获得更好的结果,但它们将以牺牲速度为代价。

编辑:以下是目前讨论的技术的一些示例。

跳过所有其他像素 - 通过查看左侧的图例,您可以看到结果不是很好。这几乎是不可读的:

Skipping every other pixel

平均每2x2网格 - 文字现在清晰可读:

Average 2x2

R.建议的高斯模糊 - 有点模糊,但在某一点上更具可读性。可以调整模糊量以得到不同的结果:

enter image description here

R.对影响结果的Gamma曲线也是正确的,但这只应在要求最苛刻的应用中才能看到。我的例子没有伽马校正。

答案 1 :(得分:6)

对于缩小尺寸,区域平均(参见Mark的回答)接近你所能达到的最佳值。

主要的另一个竞争者是高斯,半径稍大。这会增加一点点模糊,这可能被视为一个缺点,但会使模糊更均匀,而不是依赖于像素mod 2的对齐。

如果我不清楚我的意思,请考虑像素模式0,0,2,2,0,0和0,0,0,2,2,0。通过面积平均,它们分别缩小到0,2,0和0,1,1 - 也就是说,一个将是清晰明亮而另一个将是模糊和暗淡的。使用较长的滤镜,两者都会模糊不清,但它们看起来会更相似,这对人类观察者来说很重要。

要考虑的另一个问题是伽玛。除非伽玛是线性的,否则强度k的两个像素将具有比强度2*k的单个像素小得多的总强度。如果你的过滤器表现出足够的模糊,那么它可能并不重要,但是对于普通的区域平均过滤器,它可能是一个主要问题。我知道的唯一解决方法是在缩放之前和之后应用和反转伽马曲线......

答案 2 :(得分:4)

如果速度是一个问题,如上所述,我建议采用2x2块并计算平均值作为结果像素。质量不是最好的,但接近。您可以激发此算法以显示其弱点,但在大多数图像上,您不会看到可以证明计算时间多倍的差异。 你也没有任何内存开销。 如果颜色分辨率可以降低到每通道6位,这是一种非常快速的方法,可以防止你分解ARGB通道(这里假设是32位ARGB):

destPixel[x,y] = ((sourcePixel[2*x  ,2*y  ]>>2)&0x3f3f3f3f) +
                 ((sourcePixel[2*x+1,2*y  ]>>2)&0x3f3f3f3f) +
                 ((sourcePixel[2*x  ,2*y+1]>>2)&0x3f3f3f3f) +
                 ((sourcePixel[2*x+1,2*y+1]>>2)&0x3f3f3f3f);

这种算法的副作用是,如果保存为PNG,文件大小会变小。 这是它的样子: Test image downscaled with the above algorithm

答案 3 :(得分:2)

我试图概括ThiloKöhler的解决方案(但在Python中):

STRIDE = 2
MASK = 0x3F3F3F3F
color = 0
for Δx, Δy in itertools.product(range(STRIDE), repeat=2):
    color += (get_pixel(x + Δx, y + Δy) // STRIDE) & MASK

这适用于缩放2(四分之一大小结果),但不适用于按3或4或其他int值缩放。有可能推广这个吗?

对于非Pythonist的BTW,上面的for循环等同于此(除了第一个版本可通过更改STRIDE进行扩展):

for Δx, Δy in [(0, 0), (0, 1), (1, 0), (1, 1)]:
    color += (get_pixel(x + Δx, y + Δy) // STRIDE) & MASK

我使用的是32位ARGB值。

答案 4 :(得分:1)

NetPBM suite包含一个名为pamscale的实用程序,它为下采样提供了一些选项。它是开源的,所以你可以尝试各种选项,然后复制你最喜欢的算法(或者只使用libnetpbm)。

答案 5 :(得分:0)