【问题标题】:In Python, how can an image stored as a NumPy array be scaled in size?在 Python 中,如何对存储为 NumPy 数组的图像进行缩放?
【发布时间】:2015-09-01 16:53:49
【问题描述】:

我通过以下方式创建了一个 NumPy 数组:

data = numpy.zeros((1, 15, 3), dtype = numpy.uint8)

然后我用 RGB 像素值填充这个数组,生成一个小彩色图像,可以使用如下过程保存:

image = Image.fromarray(data)
image.save("image.png")

为了创建 600 x 300 像素的图像,我如何扩大 NumPy 数组的大小(没有插值)?

【问题讨论】:

  • 您能否详细说明“无插值”的含义?如果您只想将像素相乘,请在 SO 上使用there are already some answers for that。除非您按整数缩放,否则必须涉及一些插值。我会将其标记为重复,但如果您认为它不同,请告诉我。
  • 感谢您的建议。不,这似乎不是一个合适的答案,因为数组的尺寸变化很大。我正在处理的数组包含 RGB 值,它需要 3 的不变维度。
  • 你确定所有的解决方案?我现在没有要检查的电脑,但我认为repeat() 解决方案甚至适用于像图像这样的 ndim 数组。同样,如果您需要除整数比例因子之外的其他内容,您将需要插值。我不确定这一点对您来说有多重要,但澄清您是想要任意最终分辨率还是非插值整数缩放可能是个好主意。
  • @kobejohn 哦,你说得对。我只查看了涉及 Kronecker 产品的解决方案。重复方法首先应用于第一个轴,然后应用于第二个轴(而不是第三个轴)。谢谢!

标签: python image numpy scale shape


【解决方案1】:

您可以按照评论中的建议使用numpy.kron,也可以使用以下选项

1] 使用PILLOW保持纵横比

  • 如果你想保持图像的纵横比,那么你可以使用thumbnail()方法

    from PIL import Image
    
    def scale_image(input_image_path,
                output_image_path,
                width=None,
                height=None):
        original_image = Image.open(input_image_path)
        w, h = original_image.size
        print('The original image size is {wide} wide x {height} '
              'high'.format(wide=w, height=h))
    
        if width and height:
            max_size = (width, height)
        elif width:
            max_size = (width, h)
        elif height:
            max_size = (w, height)
        else:
            # No width or height specified
            raise RuntimeError('Width or height required!')
    
        original_image.thumbnail(max_size, Image.ANTIALIAS)
        original_image.save(output_image_path)
    
        scaled_image = Image.open(output_image_path)
        width, height = scaled_image.size
        print('The scaled image size is {wide} wide x {height} '
              'high'.format(wide=width, height=height))
    
    
    if __name__ == '__main__':
         scale_image(input_image_path='caterpillar.jpg',
                     output_image_path='caterpillar_scaled.jpg',
                     width=800)
    
  • 我使用了Image.ANTIALIAS 标志,它将应用高质量的下采样过滤器,从而产生更好的图像

2] 使用 OpenCV

  • OpenCV 有cv2.resize() 功能

    import cv2
    image = cv2.imread("image.jpg")   # when reading the image the image original size is 150x150
    print(image.shape)
    scaled_image = cv2.resize(image, (24, 24))  # when scaling we scale original image to 24x24 
    print(scaled_image.shape)
    
  • 输出

    (150, 150)
    (24, 24)
    
  • cv2.resize() 函数还具有插值作为参数,您可以通过它指定如何调整图像大小
  • 插值方法:

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

3] 使用 PILLOW

  • 使用Image.resize()

    from PIL import Image
    sourceimage= Image.open("image.jpg")   # original image of size 150x150
    resized_image = sourceimage.resize((24, 24), resample=NEAREST)  # resized image of size 24x24
    resized_image.show()
    

4] 使用 SK-IMAGE

  • 使用skimage.transform.resize()

    from skimage import io
    image = io.imread("image.jpg")
    print(image.shape)
    resized_image = skimage.transform.resize(image, (24, 24))
    print(resized_image.shape)
    
  • 输出

    (150, 150)
    (24, 24)
    

5] 使用 SciPy

  • 使用scipy.misc.imresize()函数

    import numpy as np
    import scipy.misc
    
    image = scipy.misc.imread("image.jpg")
    print(image.shape)
    resized_image = scipy.misc.imresize(x, (24, 24))
    resized_image
    print(resized_image.shape)
    
  • 输出

    (150, 150)
    (24, 24)
    

【讨论】:

  • 谢谢!使用 Sk-Image 和 SciPy 直接回答了这个问题——“缩放存储为 numpy 数组的图像,同时保持数据为 numpy 格式。”
【解决方案2】:

scikit-image,我们有transform

from skimage import transform as tf
import matplotlib.pyplot as plt
import numpy as np
data = np.random.random((1, 15, 3))*255
data = data.astype(np.uint8)
new_data = tf.resize(data, (600, 300, 3), order=0) # order=0, Nearest-neighbor interpolation
f, (ax1, ax2, ax3) = plt.subplots(1,3, figsize=(10, 10))
ax1.imshow(data)
ax2.imshow(new_data)
ax3.imshow(tf.resize(data, (600, 300, 3), order=1))

【讨论】:

    【解决方案3】:

    这是一个使用 PIL 调整存储在 numpy 数组中的图像大小的 sn-p 代码。在本例中,img 是一个二维 numpy 数组。

    from PIL import Image
    import numpy as np
    nr,nc = img.shape
    shrinkFactor = .5
    img_pil = Image.fromarray(img)
    img_pil = img_pil.resize((round(nc*shrinkFactor),round(nr*shrinkFactor)))
    img_resized = np.array(img_pil)
    

    【讨论】:

      猜你喜欢
      • 2021-11-12
      • 2017-05-05
      • 2019-07-17
      • 2010-11-16
      • 2018-05-15
      • 2010-12-06
      • 2019-06-24
      • 2010-09-26
      • 1970-01-01
      相关资源
      最近更新 更多