Numpy调整大小/重新缩放图像

Bri*_*ill 64 python resize numpy image scipy

我想拍摄图像并改变图像的比例,而它是一个numpy数组.

例如,我有一个可口可乐瓶的图像: 瓶-1

这转换为一个numpy形状的形状(528, 203, 3),我想调整大小来说明第二个图像的大小: bottle-2

其中有一个形状(140, 54, 3).

如何在保持原始图像的同时将图像大小更改为特定形状?其他答案建议剥离所有其他或第三行,但我想要做的是基本上缩小图像如何通过图像编辑器,但在python代码.在numpy/SciPy中有没有任何库可以做到这一点?

Wil*_*sem 76

是的,你可以安装opencv(这是一个用于图像处理和计算机视觉的库),并使用该cv2.resize功能.例如使用:

import cv2
import numpy as np

img = cv2.imread('your_image.jpg')
res = cv2.resize(img, dsize=(54, 140), interpolation=cv2.INTER_CUBIC)
Run Code Online (Sandbox Code Playgroud)

img因此,这是包含原始图像res的numpy数组,而是包含调整大小的图像的numpy数组.一个重要的方面是interpolation参数:有几种方法可以调整图像大小.特别是因为你缩小图像,而原图像的大小是不是调整后的图像的大小的倍数.可能的插值模式是:

  • INTER_NEAREST - 最近邻插值
  • INTER_LINEAR - 双线性插值(默认使用)
  • INTER_AREA - 使用像素区域关系重新采样.它可能是图像抽取的首选方法,因为它可以提供无莫尔条纹的结果.但是当图像被缩放时,它与INTER_NEAREST方法类似 .
  • INTER_CUBIC - 在4x4像素邻域上的双三次插值
  • INTER_LANCZOS4 - 在8x8像素邻域上的Lanczos插值

与大多数选项一样,没有"最佳"选项,因为对于每个调整大小架构,有一种策略可以优先于另一种策略.

  • 我尽量避免使用 cv2,它以 BGR 通道格式交换尺寸和负载。我更喜欢 `skimage.io.imread('image.jpg')` 和 `skimage.transform.resize(img)`。https://scikit-image.org/docs/dev/install.html (7认同)
  • 我刚刚尝试了这段代码,它就可以了!仅有的一个变化是,`dsize`应该为`dsize =(54,140)`,因为它先是x然后是y,其中一个numpy数组将形状显示为y然后是x(y是行数,x是列数) (3认同)
  • @Decker skimage.transform.resize 通过“order”参数提供一些控制。order=0 是最近邻,1=双线性,2=双二次,3=双三次等。但是没有面积均值或 lanczos 插值。 (3认同)
  • @EduardoPignatelli 我避免使用 skimage.transform.resize 因为您无法控制它使用的插值算法。但是,这可能并不重要,这取决于人们的用例。 (2认同)

jak*_*vdp 44

虽然可以单独使用numpy来执行此操作,但操作不是内置的.也就是说,你可以使用scikit-image(建立在numpy上)来进行这种图像处理.

Scikit-Image重新缩放文档就在这里.

例如,您可以对图像执行以下操作:

from skimage.transform import resize
bottle_resized = resize(bottle, (140, 54))
Run Code Online (Sandbox Code Playgroud)

这将为您处理内插,消除锯齿等问题.

  • 即使原始图像是** uint8 **,这也会将图像返回为** float ** ndarray。 (3认同)
  • 这是一种很好的技术,因为它适用于任意数量的通道。我尝试将 rgb 数据与深度点云数据相结合,并保留了我想要的关系。 (3认同)
  • 谢谢!这个答案也有效!尽管我在使用`anti_aliasing`标志时遇到了一些问题,但它似乎已从[0.13.1]的最新版本中删除(http://scikit-image.org/docs/0.13.x/api /skimage.transform.html?highlight=resize#skimage.transform.resize) (2认同)

Rom*_*ell 16

如果有人来这里寻找一种在 Python 中缩放/调整图像大小的简单方法,而不使用其他库,这里有一个非常简单的图像调整大小函数:

#simple image scaling to (nR x nC) size
def scale(im, nR, nC):
  nR0 = len(im)     # source number of rows 
  nC0 = len(im[0])  # source number of columns 
  return [[ im[int(nR0 * r / nR)][int(nC0 * c / nC)]  
             for c in range(nC)] for r in range(nR)]
Run Code Online (Sandbox Code Playgroud)

用法示例:将 (30 x 30) 图像调整为 (100 x 200):

import matplotlib.pyplot as plt

def sqr(x):
  return x*x

def f(r, c, nR, nC):
  return 1.0 if sqr(c - nC/2) + sqr(r - nR/2) < sqr(nC/4) else 0.0

# a red circle on a canvas of size (nR x nC)
def circ(nR, nC):
  return [[ [f(r, c, nR, nC), 0, 0] 
             for c in range(nC)] for r in range(nR)]

plt.imshow(scale(circ(30, 30), 100, 200))
Run Code Online (Sandbox Code Playgroud)

输出: 缩放图像

这适用于缩小/缩放图像,并且适用于 numpy 数组。


mat*_*lso 10

用于下采样的单行 numpy 解决方案(乘以 2):

smaller_img = bigger_img[::2, ::2]
Run Code Online (Sandbox Code Playgroud)

上采样(2):

bigger_img = smaller_img.repeat(2, axis=0).repeat(2, axis=1)
Run Code Online (Sandbox Code Playgroud)

(这假设 HxWxC 形状的图像。h/t 到 L.Kärkkäinen 在上面的评论中。注意这种方法只允许整个整数调整大小(例如,2x 但不是 1.5x))

  • 操纵分段标签掩码的绝佳解决方案,您确实不需要/不希望在 skimage 中进行到 float64 的转换。 (2认同)

Way*_*inn 7

对于来自Google来这里的人们,他们正在寻找一种快速降序对numpy数组图像进行下采样以供机器学习应用程序使用的方法,这是一种超快速方法(从此处改编)。仅当输入尺寸为输出尺寸的倍数时,此方法才有效。

以下示例将采样率从128x128降采样为64x64(可以轻松更改)。

频道最后订购

# large image is shape (128, 128, 3)
# small image is shape (64, 64, 3)
input_size = 128
output_size = 64
bin_size = input_size // output_size
small_image = large_image.reshape((output_size, bin_size, 
                                   output_size, bin_size, 3)).max(3).max(1)
Run Code Online (Sandbox Code Playgroud)

渠道第一订购

# large image is shape (3, 128, 128)
# small image is shape (3, 64, 64)
input_size = 128
output_size = 64
bin_size = input_size // output_size
small_image = large_image.reshape((3, output_size, bin_size, 
                                      output_size, bin_size)).max(4).max(2)
Run Code Online (Sandbox Code Playgroud)

对于灰度图像,只需将更3改为1如下所示:

渠道第一订购

# large image is shape (1, 128, 128)
# small image is shape (1, 64, 64)
input_size = 128
output_size = 64
bin_size = input_size // output_size
small_image = large_image.reshape((1, output_size, bin_size,
                                      output_size, bin_size)).max(4).max(2)
Run Code Online (Sandbox Code Playgroud)

此方法使用的是最大池化。我发现这是最快的方法。

  • large_image[:, ::2, ::2] 返回分辨率减半的图像。 (7认同)
  • @rayzinnz `np.repeat(np.repeat(a, 2, axis=0), 2, axis=1) ` (3认同)
  • @LasseKärkkäinen 但它不会下采样,它只是选择每隔一个像素。不同之处在于最终函数“max”可以更改为以更好的方式选择或计算像素(例如使用“min”或“mean”)。如果这无关紧要,您的方法很有用(而且速度更快)。 (2认同)
  • 用“.mean(4).mean(2)”替换“.max(4).max(2)”是否可以作为线性插值下采样的快速方法? (2认同)

小智 6

对于想要调整(插值)一批 numpy 数组大小的人,pytorch 提供了一个更快的函数名称torch.nn.function.interpolate,只需记住首先使用 np.transpose 将通道从batchxWxHx3更改为batchx3xWxH。