I am trying to extract patches of fixed size centered at some given position (x,y). The code is given below-
for i,j in zip(indices[0],indices[1]):
patch
Assuming you are dealing with near-boundary indices separately, as otherwise you would have different shaped patches, let us suggest ourselves a vectorized approach making use broadcasting together with some knowledge about linear-indexing
. Posted below is an implementation to go with that philosophy to give us a 3D
array of such patches -
m,n = x.shape
K = int(np.floor(patch_size/2.0))
R = np.arange(-K,K+1)
out = np.take(x,R[:,None]*n + R + (indices[0]*n+indices[1])[:,None,None])
Let's do a sample run on a minimal input case with input image x
of (8,10)
and indices are such that the desired patches don't extend beyond the boundaries of the input image. Then, run the original and proposed approaches for verification. Here we go -
1] Inputs :
In [105]: # Inputs
...: x = np.random.randint(0,99,(8,10))
...: indices = np.array([[4,2,3],[6,3,7]])
...:
3] Original approach with output :
In [106]: # Posted code in the question ...
In [107]: patches[0]
Out[107]:
array([[[92, 21, 84],
[10, 52, 36],
[ 5, 62, 61]]])
In [108]: patches[1]
Out[108]:
array([[[71, 76, 75],
[80, 32, 55],
[77, 62, 42]]])
In [109]: patches[2]
Out[109]:
array([[[16, 88, 31],
[21, 84, 51],
[52, 36, 3]]])
3] Proposed approach with output :
In [110]: # Posted code in the solution earlier ...
In [111]: out
Out[111]:
array([[[92, 21, 84],
[10, 52, 36],
[ 5, 62, 61]],
[[71, 76, 75],
[80, 32, 55],
[77, 62, 42]],
[[16, 88, 31],
[21, 84, 51],
[52, 36, 3]]])
Using scikit-learn:
from sklearn.feature_extraction.image import extract_patches
all_patches = extract_patches(x, patch_size)
upper_left = indices - patch_size // 2
patches = all_patches[upper_left[0], upper_left[1]]
A similar function can be found in scikit-image: view_as_windows.