首页 > 解决方案 > 如何使用步幅从单个图像创建多个图像?

问题描述

我有一个图像,我想像滑动窗口一样使用垂直和水平跨度将其拆分为多个图像,并且生成的图像都将具有相同的分辨率。我怎样才能在 Python 中有效地做到这一点?我做了这么多:

from PIL import Image

def sliding_window(image, stride, imgSize):
    width, height = image.size
    img = []
    for y in range(0, height-imgSize, stride):
        for x in range(0, width-imgSize, stride):
            # Setting the points for cropped image
            left = x
            top = y
            right = x + imgSize
            bottom = y + imgSize
            im1 = image.crop((left, top, right, bottom))
            img.append(im1)
    return img
file = "/home/xxxxxx/yyyyyy.png"
im = Image.open(file)
img = sliding_window(im, 1, 838) # Strides of 1 takes too much time

但是这段代码需要太多的 RAM 并且太耗时。请帮忙。

例子 :

示例代码:img = sliding_window(im, 200, 300)

下图为 800*800 尺寸。

原始图像

输出 :

样本输出

标签: pythonimage-processingsliding-window

解决方案


正如您正确推测的那样,有一种方法可以使用无需复制即可查看原始数据的窗口来执行此操作。最简单的方法可能是使用相对较新的sliding_window_view功能:

from numpy.lib.stride_tricks import sliding_window_view

window = sliding_window_view(image, (838, 838), axis=(0, 1))

您不需要明确axis的 2D 图像,但它不会伤害您,并且在 3D 情况下可以为您节省一些麻烦。如果你想调整步幅,你可以只对结果进行子集化。例如,对于 的步幅(3, 4)

window = window[::3, ::4]

由于窗口轴必须(应该)按 C 顺序排在最后,因此 3D 图像将通道移动到中间轴。要访问正确的形状,您可以使用类似的东西np.moveaxisor transpose

np.moveaxis(window[80, 70], 0, -1)

或者

window[80, 70].transpose(1, 2, 0).shape

推荐阅读