使用 PIL 对图像进行矢量化重塑和裁剪

Vectorizing the reshaping and cropping of images using PIL

我有很多图像要裁剪,然后再整形。为了帮助我解决这个问题,我编写了两个辅助函数:

def crop_images(images_data):
    cropped_images = []
    for image_data in images_data:
        image = Image.fromarray(image_data)
        cropped_image = np.asarray(image.crop((25,40,275,120)))
        cropped_images.append(cropped_image)
    return(np.array(cropped_images))

def resize_images(images_data):
    resized_images = []
    width, height = images_data.shape[2], images_data.shape[1]
    resized_width, resized_height = int(width/2), int(height/2)
    for image_data in images_data:
        image = Image.fromarray(image_data)
        image = image.resize((resized_width, resized_height), Image.ANTIALIAS)
        resized_images.append(np.asarray(image))
    return(np.array(resized_images))

然后我会将这两个函数链接在一起来处理我的图像,例如: resize_images(crop_images(images_data))

但我想知道是否有一种方法可以将这些操作矢量化,因为我知道 numpy 理想情况下应该是矢量化操作,因为它更快。

对于裁剪,如果将所有图像放入一个三维数组中,则可以一次将它们全部裁剪(三维是图像轴):

cropped = images[top:bottom, left:right, :]

但不确定这是否会更快 - 将所有图像存储在内存中两次的内存成本可能会减慢它的速度。

这是更高级别的迭代 - 在图像数组上 - 通常所说的 'vectorizing' 并不适用。

图像数组的大小往往类似于 (400,400,3) 或更大。如果不需要,您不想迭代这 400 个边中的一个。所以 'vectorizing' 对图像数组的操作很有意义。

但如果处理 100 张这样的图像,图像循环也不错。 'vectorize' 的唯一方法是将它们 assemble 放入更大的数组 (N, 400, 400, 3) 并找到适用于 4d 或那个大数组的切片的表达式。如果 N 为 1000 或更大,则很容易走这条路,但对于像这样的大阵列,内存管理问题开始影响任何速度提升。

对于迭代,我认为附加到列表和插入到预分配数组中都是有用的。我还没有看到明确的证据表明一个在所有情况下都比另一个快。

alist = []
for arr in source:
    <process arr>
    alist.append(arr)
bigarr = np.array(alist)

对比

bigarr = np.zeros((N,..)
for i in range(N):
    arr = source[i,...]
    <process arr>
    bigarr[i,...] = arr

尝试 'vectorize' 批处理操作时,代码清晰度也会受到影响。