C++ 图像下采样算法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6133957/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Image downsampling algorithms
提问by sleeping.ninja
What's the best re-sampling algorithm I can use to divide an image into half its original size. Speed is of primary importance but it shouldn't degrade quality too bad. I'm basically trying to generate an image pyramid.
我可以用来将图像分成原始大小的一半的最佳重采样算法是什么。速度是最重要的,但它不应该太糟糕地降低质量。我基本上是在尝试生成图像金字塔。
I was originally planning to skip pixels. Is this the best way to go? From what I've read the image produced by pixel skipping is too sharp. Could someone who has tried this comment. My images contain map data sort of like this.
我原本打算跳过像素。这是最好的方法吗?从我读到的像素跳跃产生的图像太清晰了。尝试过此评论的人可以吗?我的图像包含类似这样的地图数据。
回答by Mark Ransom
Skipping pixels will result in aliasing, where high frequency changes (such as alternating light/dark bands) will convert to low frequencies (such as constant light or dark).
跳过像素会导致混叠,其中高频变化(例如交替亮/暗带)将转换为低频(例如恒定亮或暗)。
The quickest way to downsize to half without aliasing is to average 2x2 pixels into a single pixel. Better results can be had with more sophisticated reduction kernels, but they will come at the expense of speed.
将 2x2 像素平均化为单个像素,将尺寸缩小到一半而不出现锯齿的最快方法。使用更复杂的归约内核可以获得更好的结果,但它们会以牺牲速度为代价。
Here are some examples of the techniques discussed so far.
以下是目前讨论的技术的一些示例。
Skipping every other pixel - you can see that the results aren't very good by looking at the legend on the left side. It's almost unreadable:
跳过所有其他像素 - 通过查看左侧的图例,您可以看到结果不是很好。这几乎是不可读的:
Averaging every 2x2 grid - The text is now sharp and readable:
平均每个 2x2 网格 - 文本现在清晰易读:
Gaussian blur, as suggested by R.- a little blurrier, but more readable up to a point. The amount of blur can be adjusted to give different results:
高斯模糊,如R.所建议的那样- 有点模糊,但在某种程度上更具可读性。可以调整模糊量以获得不同的结果:
R.is also correct about the Gamma curve affecting the results, but this should only be visible in the most demanding applications. My examples were done without gamma correction.
R.关于影响结果的 Gamma 曲线也是正确的,但这应该只在最苛刻的应用程序中可见。我的例子是在没有伽马校正的情况下完成的。
Edit:And here is an example of a more sophisticated but slow kernel, a Lanczos-5performed in a linear (not gamma-adjusted) color space.
编辑:这是一个更复杂但速度较慢的内核的示例,Lanczos-5在线性(非伽马调整)色彩空间中执行。
The contrast in the lettering is lower, probably because of the conversion of color spaces. But look at the coastline detail.
字体中的对比度较低,可能是因为色彩空间的转换。但是看看海岸线的细节。
回答by R.. GitHub STOP HELPING ICE
For downscaling, area-averaging (see Mark's answer) is close to the best you'll get.
对于缩小比例,区域平均(请参阅马克的回答)接近您将获得的最佳结果。
The main other contender is gaussian, with a slightly larger radius. This will increase blurring a little bit, which could be seen as a disadvantage, but would make the blurring more uniform rather than dependent on the alignment of pixels mod 2.
另一个主要的竞争者是高斯的,半径稍大。这会稍微增加模糊,这可能被视为一个缺点,但会使模糊更均匀,而不是依赖于像素 mod 2 的对齐。
In case it's not immediately clear what I mean, consider the pixel patterns 0,0,2,2,0,0 and 0,0,0,2,2,0. With area-averaging, they'd downscale to 0,2,0 and 0,1,1, respectively - that is, one will be sharp and bright while the other will be blurred and dim. Using a longer filter, both will be blurred, but they'll appear more similar, which presumably matters to human observers.
如果不是很清楚我的意思,请考虑像素模式 0,0,2,2,0,0 和 0,0,0,2,2,0。通过区域平均,它们将分别缩小到 0,2,0 和 0,1,1 - 也就是说,一个会清晰明亮,而另一个会变得模糊和暗淡。使用更长的过滤器,两者都会变得模糊,但它们看起来更相似,这可能对人类观察者很重要。
Another issue to consider is gamma. Unless gamma is linear, two pixels of intensity k
will have much less total intensity than a single pixel of intensity 2*k
. If your filter performs sufficient blurring, it might not matter so much, but with the plain area-average filter it can be a major issue. The only work-around I know is to apply and reverse the gamma curve before and after scaling...
另一个需要考虑的问题是伽马。除非伽玛是线性的,否则两个强度像素的k
总强度将比强度的单个像素小得多2*k
。如果您的过滤器进行了足够的模糊处理,那么它可能并不重要,但对于普通面积平均过滤器,它可能是一个主要问题。我知道的唯一解决方法是在缩放之前和之后应用和反转伽马曲线......
回答by Thilo K?hler
If speed is an issue, as mentioned, I recommend to take a 2x2 Block and calculate the average as the resulting pixel. The quality is not the best that can be achieved, but close to. You can provoke this algorithm to show its weaknesses, but on most images you won't see a difference that would justify the many times higher computation time. You also dont have any memory overhead. If color resolution can be lowered to 6bit per channel, here is a pretty fast way that prevents you from decomposing the ARGB channels (here assuming 32bit ARGB):
如果速度是一个问题,如上所述,我建议采用 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);
Side effect of this alogrithm is, that if saved as PNG, the file size gets smaller.
This is how it looks like:
这种算法的副作用是,如果保存为 PNG,文件大小会变小。这是它的样子:
回答by Mark Summerfield
I tried to generalise Thilo K?hler's solution (but in Python):
我试图概括 Thilo K?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
This works fine for scaling by 2 (quarter size result), but doesn't work for scaling by 3 or 4 or other int values. Is it possible to generalise this?
这适用于按 2 缩放(四分之一大小的结果),但不适用于按 3 或 4 或其他 int 值缩放。是否可以概括这一点?
BTW for non-Pythonistas the for loop above is equivalent to this (except that the first version is scalable by changing the STRIDE):
顺便说一句,对于非 Pythonistas,上面的 for 循环与此等效(除了第一个版本可以通过更改 STRIDE 进行扩展):
for Δx, Δy in [(0, 0), (0, 1), (1, 0), (1, 1)]:
color += (get_pixel(x + Δx, y + Δy) // STRIDE) & MASK
I'm using 32-bit ARGB values.
我使用的是 32 位 ARGB 值。
回答by Nemo
The NetPBM suiteincludes a utility called pamscale, which provides a few options for downsampling. It is open source, so you can try the various options and then copy the algorithm you like best (or just use libnetpbm).
该NetPBM的套件包括一个名为实用pamscale,它提供了一个采样几个选项。它是开源的,因此您可以尝试各种选项,然后复制您最喜欢的算法(或仅使用 libnetpbm)。
回答by Seth Robertson
http://www.cs.ubc.ca/nest/imager/tr/2011/BlurAwareDownsize/ap-resizing-validation/index.html
http://www.cs.ubc.ca/nest/imager/tr/2011/BlurAwareDownsize/ap-resizing-validation/index.html
http://www.cs.ubc.ca/nest/imager/tr/2011/BlurAwareDownsize/