大小调整/缩放图像


95

我想拍摄一张图像并更改图像的比例,虽然它是一个numpy数组。

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

转换为一个numpy的形状数组,(528, 203, 3)我想调整其大小以表示第二个图像的大小: bottle-2

形状为(140, 54, 3)

如何在保持原始图像的同时将图像尺寸更改为特定形状?其他答案建议将每两行或第三行剥离掉,但是我想要做的基本上是像通过图像编辑器那样缩小图像,但是使用python代码。是否有任何库可以在numpy / SciPy中执行此操作?


您可以显示numpy数组的代码吗?
ShpielMeister


2
@sascha已淘汰,根据您链接的页面而定。
保罗·潘泽

@ShpielMeister我无法让IntelliJ完全打印出numpy数组,由于某种原因,当输出很大时,它总是会出现...,所以我只能在控制台中看到数组输出的一部分
Brian Hamill

Answers:


117

是的,您可以安装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)

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

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

与大多数选项一样,就每种调整大小模式而言,也没有“最佳”选项,在某些情况下,一种策略可能比另一种策略更可取。


5
我刚刚尝试了这段代码,它起作用了!只是一个的变化是,dsize应该是dsize=(54, 140)因为它需要X,则y,其中作为numpy的阵列示出了形状为y,则x(y为行数,x是列数)
布赖恩哈米尔

5
我尝试避免使用cv2,它会以BGR通道格式交换尺寸和负载。我更喜欢skimage.io.imread('image.jpg')skimage.transform.resize(img)scikit-image.org/docs/dev/install.html
Eduardo Pignatelli,

1
@EduardoPignatelli我避免使用skimage.transform.resize,因为您无法控制它使用的插值算法。但是,这可能并不重要,具体取决于人们的用例。
Decker

1
@Decker skimage.transform.resize通过'order'参数提供一些控制。order = 0是最近的邻居,1 =双线性,2 =双二次,3 =双三次等。但是,没有面积均值或兰科斯插值。
Tapio Friberg

1
@TapioFriberg啊,是的,我已经纠正了;我看到了在文档下为skimage.transform.warp的“ order”参数定义的算法。在某些时候更新文档以包括对类型的引用可能会有所帮助,例如,文档中其他地方都未定义“ Bi-quartic”类型(截至2019年12月10日)-单线可能对未来的用户有利。
Decker

64

尽管可以单独使用numpy来执行此操作,但该操作不是内置的。也就是说,您可以使用scikit-image(基于numpy构建)执行这种图像处理。

Scikit-Image重缩放文档在此处

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

from skimage.transform import resize
bottle_resized = resize(bottle, (140, 54))

这将为您处理插值,抗锯齿等问题。


2
谢谢!这个答案也有效!尽管我对该anti_aliasing标志有疑问,但它似乎已从最新版本的0.13.1中删除
Brian Hamill

8
即使您的原始图像是uint8,这也会将图像返回为float ndarray
sziraqui

3
这是一种很好的技术,因为它可与任意数量的通道一起使用。我尝试了将rgb数据与深度点云数据结合使用,并按我的意愿保留了这种关系。
Darth Egregious

@DarthEgregious,jakevdp->当我按照您所描述的方法将(137,236,3)数组的大小调整为(64,64)时,它使我的随机噪声数据变为单色。这是正常现象,因为它似乎丢失了所有信息吗?
Deshwal

1
(64,64,3)
Darth Egregious

14

对于来自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)

渠道第一订购

# 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)

对于灰度图像,只需将更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)

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


4
large_image [:, :: 2,:: 2]返回分辨率减半的图像。
L.Kärkkäinen19年

1
@LasseKärkkäinen,但不会降采样,它只会选择其他所有像素。不同之处在于,可以更改最终函数“ max”以更好地选择或计算像素(例如,使用“ min”或“ mean”)。如果没关系,您的方法很有用(而且更快)。
韦隆·弗林

@L.Kärkkäinen与双分辨率有何相反?
rayzinnz

2
@rayzinnznp.repeat(np.repeat(a, 2, axis=0), 2, axis=1)
L.Kärkkäinen

8

如果有人来这里寻找一种简单的方法来在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)]

用法示例:将(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))

输出: 缩放图像

这可以缩小/缩放图像,并且可以与numpy数组一起使用。


4

SciPy的imresize()方法是另一种调整大小的方法,但是将从SciPy v 1.3.0开始将其删除。SciPy指的是PIL图像调整大小方法:Image.resize(size, resample=0)

size –请求的大小(以像素为单位),为2元组:(宽度,高度)。
重采样 –可选的重采样过滤器。这可以是PIL.Image.NEAREST(使用最近的邻居),PIL.Image.BILINEAR(线性插值),PIL.Image.BICUBIC(三次样条插值)或PIL.Image.LANCZOS(高质量的下采样滤波器)之一)。如果省略,或者图像的模式为“ 1”或“ P”,则将其设置为PIL.Image.NEAREST。

链接到这里:https : //pillow.readthedocs.io/en/3.1.x/reference/Image.html#PIL.Image.Image.resize


3
不幸的是,不建议使用imresize(),它将在SciPy 1.3.0
MiniQuark中

1

是否有任何库可以在numpy / SciPy中执行此操作

当然。您可以在没有OpenCV,scikit-image或PIL的情况下执行此操作。

图像调整大小基本上是将每个像素的坐标从原始图像映射到其调整大小的位置。

由于图像的坐标必须是整数(将其视为矩阵),因此,如果映射的坐标具有十进制值,则应插值像素值以使其接近整数位置(例如,已知最接近该位置的像素)作为最近邻插值)。

您所需要做的就是为您执行此插值的功能。SciPy有interpolate.interp2d

您可以使用它来调整numpy数组中图像的大小,例如arr,如下所示:

W, H = arr.shape[:2]
new_W, new_H = (600,300)
xrange = lambda x: np.linspace(0, 1, x)

f = interp2d(xrange(W), xrange(H), arr, kind="linear")
new_arr = f(xrange(new_W), xrange(new_H))

当然,如果您的图像是RGB,则必须对每个通道执行插值。

如果您想了解更多信息,建议您观看“ 调整图像大小-Computerphile”


可能无法正常工作基于这样的回答:stackoverflow.com/questions/37872171/...
random_dsp_guy

0
import cv2
import numpy as np

image_read = cv2.imread('filename.jpg',0) 
original_image = np.asarray(image_read)
width , height = 452,452
resize_image = np.zeros(shape=(width,height))

for W in range(width):
    for H in range(height):
        new_width = int( W * original_image.shape[0] / width )
        new_height = int( H * original_image.shape[1] / height )
        resize_image[W][H] = original_image[new_width][new_height]

print("Resized image size : " , resize_image.shape)

cv2.imshow(resize_image)
cv2.waitKey(0)

4
欢迎使用StackOverflow。很高兴您希望通过回答其他人的问题来帮助他们。但是,我看不出您的答案与已经使用cv2并使用适当大小调整功能的现有答案相比如何增加价值,而不是重新实现比最近邻插值更糟糕的“次优”大小调整功能。
NOhs
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.