Reputation: 35
Suppose I have an np.array(image)
img = [[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]]
How can I divide this in to 4 crops?
[[1,2], [[3,4], [[9,10], [[11,12],
[5,6]] [7,8]] [13,14]] [15,16]]
The only way I know is to use loop to specify the img[x_start:x_end,y_start:y_end]
.
But this is very time-consuming when it comes to a large 3D Volume.
NumPy library seems to perform better by itself than the loop in some algorithms.
Btw, if I use img.reshape(-1,2,2)
, I get the following matrix, which is not what I want:
[[1,2], [[5,6], [[9,10], [[13,14],
[3,4]] [7,8]] [11,12]] [15,16]]
Of course, it doesn't have to be Numpy library but can also cv2 or something like that which I can use in python
Upvotes: 3
Views: 233
Reputation: 1623
What you want to have is called a sliding window view. NumPy
already has a function to do this: numpy.lib.stride_tricks.sliding_window_view
, but the function does not take custom strides (step size of your sliding window). I have implemented my own function which gives such a view (requiring minimal memory overhead):
import numpy as np
from numpy.lib.stride_tricks import as_strided
from typing import Tuple
def get_sliding_window_2d(x: np.ndarray, width: int, height: int, rowstride: int, colstride: int):
"""
x: np.array
width: width of window
height: height of window
rowstride: horizontal window step size
colstride: vertical window step size
"""
imgRows, imgCols = x.shape
u = np.array(x.itemsize)
return as_strided(x,
shape=((imgRows-width)//rowstride+1, (imgCols-height)//colstride+1, width, height),
strides=u*(imgCols*rowstride, colstride, imgCols, 1)
)
a = np.arange(4*4).reshape(4,4)+1
for windows in get_sliding_window_2d(a, 2, 2, 2, 2):
for window in windows:
print(window, end="\n\n")
#[[1 2]
# [5 6]]
#
#[[3 4]
# [7 8]]
#
#[[ 9 10]
# [13 14]]
#
#[[11 12]
# [15 16]]
On a related note, if you plan to use said sliding windows to blur images using a mean kernel or do edge detection or something, you can use scipy.signal.convolve2d
(and many other similar functions) to do it.
Upvotes: 0
Reputation: 191
To solve your problem you can play with axis using np.transpose
or np.moveaxis
for example.
The following solution is probably not the fastest but it illustrates what you can do with these tools.
img = np.array([[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]])
img = img.reshape(-1,2,2)
img = np.moveaxis(img, 0, 1)
img = img.reshape(-1,2,2)
Output:
>>> print(img)
[[[ 1 2]
[ 5 6]]
[[ 9 10]
[13 14]]
[[ 3 4]
[ 7 8]]
[[11 12]
[15 16]]]
Upvotes: 0
Reputation: 195448
I hope I've undersdoot your question right:
img = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
out = [np.vsplit(x, 2) for x in np.hsplit(img, 2)]
for arr1 in out:
for arr2 in arr1:
print(arr2)
print()
Prints:
[[1 2]
[5 6]]
[[ 9 10]
[13 14]]
[[3 4]
[7 8]]
[[11 12]
[15 16]]
Upvotes: 1