如何从一堆图像中裁剪不同位置的相同大小图像块?

5 投票
1 回答
1738 浏览
提问于 2025-04-18 13:22

假设我有一个叫做 imgs 的数组,它的形状是 ( num_images, 3, width, height ),这个数组存储了一堆数量为 num_images 的RGB图片,而且它们的大小都是一样的。
我想从每张图片中切出一个形状为 ( 3, pw, ph ) 的小块,但每张图片的小块中心位置都不一样,这些中心位置存储在一个叫 centers 的数组里,形状是 (num_images, 2)

有没有一种简单又优雅的方法来从 imgs 中切出这些小块 patches(形状是 (num_images, 3, pw, ph)),每个小块的中心都围绕着对应的 centers 呢?

为了简化问题,可以假设所有的小块都在图片的边界内。

1 个回答

3

正确的切片方法不适用,因为你需要在不规则的间隔中访问底层数据。你可以通过一次“花式索引”操作来获取所需的数据,但这需要一个(非常)大的索引数组。因此,我认为使用循环会更简单也更快。

对比下面的两个函数:

def fancy_indexing(imgs, centers, pw, ph):
    n = imgs.shape[0]
    img_i, RGB, x, y = np.ogrid[:n, :3, :pw, :ph]
    corners = centers - [pw//2, ph//2]
    x_i = x + corners[:,0,None,None,None]
    y_i = y + corners[:,1,None,None,None]
    return imgs[img_i, RGB, x_i, y_i]

def just_a_loop(imgs, centers, pw, ph):
    crops = np.empty(imgs.shape[:2]+(pw,ph), imgs.dtype)
    for i, (x,y) in enumerate(centers):
        crops[i] = imgs[i,:,x-pw//2:x+pw//2,y-ph//2:y+ph//2]
    return crops

撰写回答