哪种插值最适合调整图像大小?

Roe*_*e E 11 python interpolation opencv numpy

我有一个numpy数组,我希望使用opencv调整大小.它的值范围从0到255.如果我选择使用cv2.INTER_CUBIC,我可能会得到超出此范围的值.这是不希望的,因为调整大小的数组应该仍然代表图像.一种解决方案是将结果剪辑为[0,255].另一种是使用不同的插值方法.我的理解是,使用INTER_AREA对于对图像进行下采样是有效的,但是对于对其进行上采样的工作类似于最近邻居,使其对于我的目的而言不是最佳的.

我应该使用INTER_CUBIC(和剪辑),INTER_AREA还是INTER_LINEAR?

使用INTER_CUBIC的范围之外的值的示例:

a = np.array( [ 0, 10, 20, 0, 5, 2, 255, 0, 255 ] ).reshape( ( 3, 3 ) )
[[  0  10  20]
 [  0   5   2]
 [255   0 255]]

b = cv2.resize( a.astype('float'), ( 4, 4 ), interpolation = cv2.INTER_CUBIC )
[[   0.            5.42489886   15.43670964   21.29199219]
 [ -28.01513672   -2.46422291    1.62949324  -19.30908203]
 [  91.88964844   25.07939219   24.75106835   91.19140625]
 [ 273.30322266   68.20603609   68.13853455  273.15966797]]
Run Code Online (Sandbox Code Playgroud)

编辑:正如berak指出的那样,将类型转换为float(来自int64)允许超出原始范围的值.cv2.resize()函数不能使用默认的'int64'类型.但是,转换为'uint8'会自动将值饱和为[0..255].

此外,正如SaulloCastro所指出的,另一个相关的答案证明了scipy的插值,并且defualt方法是三次插值(具有饱和度).

Shi*_*aha 11

如果要放大图像,则应首选使用INTER_LINEARINTER_CUBIC插值。如果要缩小图像,则应首选使用INTER_AREA插值。

三次插值在计算上更复杂,因此比线性插值要慢。但是,最终图像的质量会更高。

  • 您有任何证据支持您的主张吗? (17认同)
  • @jdhao来自[docs](https://docs.opencv.org/3.4/da/d54/group__imgproc__transform.html#ga47a974309e9102f5f08231edc7e7529d):要缩小图像,通常使用“INTER_AREA”插值看起来效果最好,而放大图像对于图像,通常使用“INTER_CUBIC”(慢)或“INTER_LINEAR”(更快,但看起来仍然不错)看起来最好。 (6认同)
  • 对于缩小,INTER_AREA 插值究竟是如何工作的? (2认同)

sus*_*097 11

为了克服这样的问题,您应该找出可以进行插值的给定图像的新尺寸。并在目标图像上复制内插采样图像,例如:

# create target image and copy sample image into it
(wt, ht) = imgSize # target image size
(h, w) = img.shape # given image size
fx = w / wt
fy = h / ht
f = max(fx, fy)
newSize = (max(min(wt, int(w / f)), 1),
           max(min(ht, int(h / f)), 1))  # scale according to f (result at least 1 and at most wt or ht)
img = cv2.resize(img, newSize, interpolation=cv2.INTER_CUBIC) #INTER_CUBIC interpolation
target = np.ones([ht, wt]) * 255  # shape=(64,800)
target[0:newSize[1], 0:newSize[0]] = img
Run Code Online (Sandbox Code Playgroud)

openCV 中的一些可能的插值是:

  • INTER_NEAREST – 最近邻插值
  • INTER_LINEAR – 双线性插值(默认使用)
  • INTER_AREA – 使用像素区域关系重新采样。它可能是图像抽取的首选方法,因为它提供无摩尔纹的结果。但是当图像放大时,它类似于 INTER_NEAREST 方法。
  • INTER_CUBIC – 4×4 像素邻域上的双三次插值
  • INTER_LANCZOS4 – 8×8 像素邻域上的 Lanczos 插值

有关每个插值的结果,请参见此处


小智 6

我的这个答案是基于测试的。最后它支持@shivam的答案。我测试了这些插值方法,包括组合、缩小和放大。放大后我用原始图像计算了 psnr。

[cv2.INTER_AREA,
cv2.INTER_BITS,
cv2.INTER_BITS2,
cv2.INTER_CUBIC,
cv2.INTER_LANCZOS4,
cv2.INTER_LINEAR,
cv2.INTER_LINEAR_EXACT,
cv2.INTER_NEAREST]

shirking=0.25
enlarge=4
Run Code Online (Sandbox Code Playgroud)

在 165 张不同形状的图像上进行了测试。对于结果,我选择了最大和第二最大 psnr 并计算了计数。对于最大值,插值计数如下图所示。 最大峰值信噪比

从这个测试中,最大 psnr 由AREALANCZOS4的组合给出,它给出了 141/204 图像的最大 psnr。

我还想包括第二个最大值。所以这里只是第二个最大值的结果。 第二最大峰值信噪比

这里 AREA 和 CUBIC 给出了第二好的结果。使用 AREA + CUBIC 时,19/204 具有最高的 psnr,158/347 具有第二高的 psnr。

这个结果很模糊,所以我打开了 CUBIC 给出最高 psnr 的文件。事实证明,使用 CUBIC 时,具有大量纹理/抽象的图像给出了最高的 psnr。

所以我只对 AREA+CUBIC 和 AREA+LANCZOS4 做了进一步的测试。我得出的结论是,如果您将图像缩小 <10 倍,那么请选择 LANCZOS4。它将为您提供小于 10 倍变焦的更好结果,并且如果图像较大,它会比 CUBIC 更好。

至于我的程序,我回避了图像 4 次,所以对我来说 AREA+LANCZOS4 效果更好。

脚本和图像:https ://github.com/crackaf/triple-recovery/tree/main/tests


Mic*_*nov 5

我认为你应该从 INTER_LINEAR 开始,这是 resize() 函数的默认选项。它结合了足够好的视觉结果和足够好的时间性能(尽管它不如 INTER_NEAREST 快)。它不会创建那些超出范围的值。