从矩阵中高效提取重叠补丁
Memory efficient extraction of overlapping patches from matrix
短篇小说:
这是以下问题的后续问题:Fast Way to slice image into overlapping patches and merge patches to image
我必须如何调整答案中提供的代码,使其不仅适用于大小为 x、y 的图像,其中像素由浮点数描述,而且还适用于大小为 3,3 的矩阵?
此外,如何调整代码,使其 returns 生成器允许我迭代所有补丁,而不必将它们全部保存在内存中?
长话短说:
给定一个形状为 (x,y) 的图像,其中每个像素由 (3,3) 矩阵描述。这可以描述为形状为 (x,y,3,3) 的矩阵。
进一步给定一个目标补丁大小,例如 (11,11),我想从图像 (x,y) 中提取所有重叠的补丁。
请注意,我不想从矩阵 x、y、3、3 中获取所有补丁,而是从图像 x、y 中获取所有补丁,其中每个像素都是一个矩阵。
我想将这些补丁用于补丁分类算法,有效地迭代所有补丁,提取特征并学习分类器。然而,给定一个巨大的图像和大的 patchsize,没有办法在不损害内存限制的情况下执行此操作。
可能的解决方案:
- sklearn.feature_extraction.image.extract_patches_2d 提供目标函数,但由于内存限制而失败,因此不适用。 (但对于具有小补丁大小的给定图像效果很好)
- Fast Way to slice image into overlapping patches and merge patches to image。一个很好的答案似乎引领了潮流,使用大步走而不是实际创建输入图像的副本。但是我无法调整答案以满足我的需要。
因此问题是:如何调整此代码以适应新的输入数据?
def patchify(img, patch_shape):
img = np.ascontiguousarray(img) # won't make a copy if not needed
X, Y = img.shape
x, y = patch_shape
shape = ((X-x+1), (Y-y+1), x, y) # number of patches, patch_shape
# The right strides can be thought by:
# 1) Thinking of `img` as a chunk of memory in C order
# 2) Asking how many items through that chunk of memory are needed when indices
# i,j,k,l are incremented by one
strides = img.itemsize*np.array([Y, 1, Y, 1])
return np.lib.stride_tricks.as_strided(img, shape=shape, strides=strides)
虽然您 link 的答案并没有错,但我认为最好不要对数组的步幅做出假设,而是简单地重复使用它已有的步幅。它有一个额外的好处,即从不需要原始数组的副本,即使它不是连续的。对于你的扩展图像形状,你会这样做:
def patchify(img, patch_shape):
X, Y, a, b = img.shape
x, y = patch_shape
shape = (X - x + 1, Y - y + 1, x, y, a, b)
X_str, Y_str, a_str, b_str = img.strides
strides = (X_str, Y_str, X_str, Y_str, a_str, b_str)
return np.lib.stride_tricks.as_strided(img, shape=shape, strides=strides)
很容易忘乎所以,想要编写一些更通用的函数,不需要对特定数组维度进行专门化。如果你觉得有必要去那里,你可能会在 this gist.
中找到一些灵感
短篇小说:
这是以下问题的后续问题:Fast Way to slice image into overlapping patches and merge patches to image
我必须如何调整答案中提供的代码,使其不仅适用于大小为 x、y 的图像,其中像素由浮点数描述,而且还适用于大小为 3,3 的矩阵?
此外,如何调整代码,使其 returns 生成器允许我迭代所有补丁,而不必将它们全部保存在内存中?
长话短说:
给定一个形状为 (x,y) 的图像,其中每个像素由 (3,3) 矩阵描述。这可以描述为形状为 (x,y,3,3) 的矩阵。 进一步给定一个目标补丁大小,例如 (11,11),我想从图像 (x,y) 中提取所有重叠的补丁。
请注意,我不想从矩阵 x、y、3、3 中获取所有补丁,而是从图像 x、y 中获取所有补丁,其中每个像素都是一个矩阵。
我想将这些补丁用于补丁分类算法,有效地迭代所有补丁,提取特征并学习分类器。然而,给定一个巨大的图像和大的 patchsize,没有办法在不损害内存限制的情况下执行此操作。
可能的解决方案:
- sklearn.feature_extraction.image.extract_patches_2d 提供目标函数,但由于内存限制而失败,因此不适用。 (但对于具有小补丁大小的给定图像效果很好)
- Fast Way to slice image into overlapping patches and merge patches to image。一个很好的答案似乎引领了潮流,使用大步走而不是实际创建输入图像的副本。但是我无法调整答案以满足我的需要。
因此问题是:如何调整此代码以适应新的输入数据?
def patchify(img, patch_shape):
img = np.ascontiguousarray(img) # won't make a copy if not needed
X, Y = img.shape
x, y = patch_shape
shape = ((X-x+1), (Y-y+1), x, y) # number of patches, patch_shape
# The right strides can be thought by:
# 1) Thinking of `img` as a chunk of memory in C order
# 2) Asking how many items through that chunk of memory are needed when indices
# i,j,k,l are incremented by one
strides = img.itemsize*np.array([Y, 1, Y, 1])
return np.lib.stride_tricks.as_strided(img, shape=shape, strides=strides)
虽然您 link 的答案并没有错,但我认为最好不要对数组的步幅做出假设,而是简单地重复使用它已有的步幅。它有一个额外的好处,即从不需要原始数组的副本,即使它不是连续的。对于你的扩展图像形状,你会这样做:
def patchify(img, patch_shape):
X, Y, a, b = img.shape
x, y = patch_shape
shape = (X - x + 1, Y - y + 1, x, y, a, b)
X_str, Y_str, a_str, b_str = img.strides
strides = (X_str, Y_str, X_str, Y_str, a_str, b_str)
return np.lib.stride_tricks.as_strided(img, shape=shape, strides=strides)
很容易忘乎所以,想要编写一些更通用的函数,不需要对特定数组维度进行专门化。如果你觉得有必要去那里,你可能会在 this gist.
中找到一些灵感