如何在没有循环的情况下均匀裁剪图像
how crop an image evenly without loop
假设我有一个 np.array(image)
img = [[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]]
如何将其分成 4 份作物?
[[1,2], [[3,4], [[9,10], [[11,12],
[5,6]] [7,8]] [13,14]] [15,16]]
我知道的唯一方法是使用循环来指定img[x_start:x_end,y_start:y_end]
。
但是当涉及到大的 3D 体积时,这是非常耗时的。
NumPy 库本身似乎比某些算法中的循环表现更好。
顺便说一句,如果我使用 img.reshape(-1,2,2)
,我会得到以下矩阵,这不是我想要的:
[[1,2], [[5,6], [[9,10], [[13,14],
[3,4]] [7,8]] [11,12]] [15,16]]
当然,它不一定是 Numpy 库,也可以是 cv2 或我可以在 python
中使用的类似库
希望我已经理解你的问题了:
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()
打印:
[[1 2]
[5 6]]
[[ 9 10]
[13 14]]
[[3 4]
[7 8]]
[[11 12]
[15 16]]
要解决您的问题,您可以使用 np.transpose
或 np.moveaxis
来玩轴。
以下解决方案可能不是最快的,但它说明了您可以使用这些工具做什么。
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)
输出:
>>> print(img)
[[[ 1 2]
[ 5 6]]
[[ 9 10]
[13 14]]
[[ 3 4]
[ 7 8]]
[[11 12]
[15 16]]]
你想要的是滑动window视图。 NumPy
已经有一个函数可以做到这一点:numpy.lib.stride_tricks.sliding_window_view
,但该函数不采用自定义步幅(滑动步长 window)。我已经实现了自己的函数,它提供了这样一个 view(需要最少的内存开销):
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]]
相关说明,如果您打算使用上述滑动 windows 来使用均值内核模糊图像或进行边缘检测或其他操作,您可以使用 scipy.signal.convolve2d
(以及许多其他类似功能) 去做。
假设我有一个 np.array(image)
img = [[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]]
如何将其分成 4 份作物?
[[1,2], [[3,4], [[9,10], [[11,12],
[5,6]] [7,8]] [13,14]] [15,16]]
我知道的唯一方法是使用循环来指定img[x_start:x_end,y_start:y_end]
。
但是当涉及到大的 3D 体积时,这是非常耗时的。
NumPy 库本身似乎比某些算法中的循环表现更好。
顺便说一句,如果我使用 img.reshape(-1,2,2)
,我会得到以下矩阵,这不是我想要的:
[[1,2], [[5,6], [[9,10], [[13,14],
[3,4]] [7,8]] [11,12]] [15,16]]
当然,它不一定是 Numpy 库,也可以是 cv2 或我可以在 python
中使用的类似库希望我已经理解你的问题了:
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()
打印:
[[1 2]
[5 6]]
[[ 9 10]
[13 14]]
[[3 4]
[7 8]]
[[11 12]
[15 16]]
要解决您的问题,您可以使用 np.transpose
或 np.moveaxis
来玩轴。
以下解决方案可能不是最快的,但它说明了您可以使用这些工具做什么。
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)
输出:
>>> print(img)
[[[ 1 2]
[ 5 6]]
[[ 9 10]
[13 14]]
[[ 3 4]
[ 7 8]]
[[11 12]
[15 16]]]
你想要的是滑动window视图。 NumPy
已经有一个函数可以做到这一点:numpy.lib.stride_tricks.sliding_window_view
,但该函数不采用自定义步幅(滑动步长 window)。我已经实现了自己的函数,它提供了这样一个 view(需要最少的内存开销):
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]]
相关说明,如果您打算使用上述滑动 windows 来使用均值内核模糊图像或进行边缘检测或其他操作,您可以使用 scipy.signal.convolve2d
(以及许多其他类似功能) 去做。