遍历 4-Dimensional Array 中的前两个索引?

Looping over first two indices in 4-Dimensional Array?

提问人:d.nikolai 提问时间:11/3/2023 最后编辑:d.nikolai 更新时间:11/4/2023 访问量:45

问:

我有一个尺寸为 478,533,3,3 的 np.array(变量标题为“window”,使用 NumPy stride tricks 从更大的 2D 数组滑动窗口生成)。数组的 478x535 部分基本上是 3x3 数组的数组。 我有兴趣遍历所有 3x3 数组以获取每个数组的 [1,1] 索引点的值(并执行一些条件操作)。我尝试了各种循环组合,但似乎无法找出用于遍历每个 3x3 数组的“for”循环。

window = np.lib.stride_tricks.sliding_window_view(tiff_array, (3,3))
P11 = np.zeros([3,3])

for i,j in window:
    block = window[i,j,:,:]
    if block[1,1]==1:
        if block[1,1]-1==1 and block[1,1]-1==1:
            P11[0,0]=P11[0,0]+1

这是我在各种尝试中尝试过的一些快速代码。我继续收到错误,即“有太多的值需要解压缩”,并且预计有两个(我想是 i,j)。我知道有两个以上的值,这就是我尝试遍历每个 3x3 数组块的原因。我想我错过了一些明显的东西,但希望得到一些帮助。 TIA!

数组 numpy for 循环 条件语句

评论

0赞 Learning is a mess 11/3/2023
循环中的条件是排他性的,不可能同时正确。其他方面,我建议将最后两个轴展平并使用 .请告诉我们您想在 3x3 积木上运行什么,我们可以提供帮助。block[1,1]==1block[1,1]-1==1np.apply_along_axis
0赞 hpaulj 11/3/2023
for i,j in window不是你如何获得你使用的索引值,比如你需要一个和循环。然而,这种迭代感觉完全不对。window[i,j,]for i in range(478)for jsliding window
0赞 d.nikolai 11/3/2023
@Learningisamess感谢您的评论。我基本上是在尝试从我的原始 2D 数组 (480x535) 计算 2 点相关性。原始数组中的值为 1、2 或 3。因此,我正在尝试获取数组的 3x3 块,如果块的中间是某个值,请弄清楚周围的值是什么,并在知道值后以 1 的增量进行步进以创建一个新的 3x3 块。因此,第一个块的中间是原始数组的 [1,1] 索引,下一个块是 [1,2] 索引,依此类推。如果还不够清楚,请告诉我,我可以再试一次。
0赞 d.nikolai 11/3/2023
@hpaulj我同意,我试图避免在此上使用太多嵌套循环,但我什至可能错误地使用滑动窗口。我上面的评论有点澄清了我的目标......图片往往能更好地代表我想要完成的任务,但我认为我不能在评论中添加图片。
1赞 hpaulj 11/4/2023
如果你必须单独处理每个 (3,3),那么你是使用 2 个嵌套循环还是一个扁平循环进行迭代都无关紧要。或者将 interations 隐藏在 .同样数量的内在大多数电话。478*533apply_along...

答:

0赞 aerobiomat 11/3/2023 #1

您的方法适用于以下更改:

window = np.lib.stride_tricks.sliding_window_view(tiff_array, (3,3))
P11 = np.zeros([3,3])

for block in window.reshape(-1, 3, 3):
    if block[1,1]==1:
        if block[1,1]-1==1 and block[1,1]-1==1:
            P11[0,0]=P11[0,0]+1

我不知道你真正需要做什么,但这种风格的矢量化方法通常更好:

t11 = tiff_array[1:-1, 1:-1]
ones = t11 == 1
P11[0, 0] = ones.sum()
...

t11只是原始数组的视图,因此它不会花费额外的内存。

评论

0赞 d.nikolai 11/4/2023
谢谢!我认为这就是我正在寻找的 - 将 3x3 块的视图转换为原始主“tiff_array”。我正在尝试确定数组中每个 3x3 块的中心值,在中心值和周长值之间执行一些条件计算,然后在整个数组中以蛇形方式从一个块移动到下一个 3x3 块。因此,第一个块的中心位于 [1,1],下一个块的中心位于 [1,2],一直到 [478,533] 的中心。
0赞 hpaulj 11/4/2023
在滑动窗口视图上执行操作时要小心。它往往会增加内存使用量。reshape
0赞 aerobiomat 11/4/2023
同意。我只是想展示它是如何工作的。我自己不是sliding_window_view的忠实粉丝。
0赞 hpaulj 11/4/2023 #2

对于较小的起始阵列:

In [17]: arr = np.random.randint(1,4,(6,6))    
In [18]: arr
Out[18]: 
array([[1, 1, 2, 2, 2, 1],
       [3, 2, 3, 2, 1, 1],
       [2, 2, 3, 3, 1, 1],
       [1, 2, 3, 3, 1, 1],
       [3, 2, 3, 2, 3, 1],
       [1, 3, 2, 1, 2, 1]])

In [19]: window = np.lib.stride_tricks.sliding_window_view(arr, (3,3))    
In [20]: window.shape
Out[20]: (4, 4, 3, 3)

中心:

In [21]: window[:,:,1,1]
Out[21]: 
array([[2, 3, 2, 1],
       [2, 3, 3, 1],
       [2, 3, 3, 1],
       [2, 3, 2, 3]])

计算它们很容易:

In [22]: (window[:,:,1,1]==1).sum()
Out[22]: 3

正如评论的那样,我不知道你在总结什么。

但是让我们猜一猜,至少看看迭代块应该如何工作:

In [26]: P=np.zeros((3,3),int)
In [27]: for i in range(window.shape[0]):
    ...:     for j in range(window.shape[1]):
    ...:         block = window[i,j]
    ...:         if block[1,1]==1:
    ...:             print(block[0,1],block[2,1])
    ...:             P += block
    ...:             
2 1
1 1
1 3

In [28]: P
Out[28]: 
array([[7, 4, 3],
       [8, 3, 3],
       [8, 5, 3]])

眯着眼睛侧头看,我几乎可以想象

 if block[1,1]==1:
    if block[1,1]-1==1 and block[1,1]-1==1:

只是意味着

block[1,1]==1 and block[1,0]==1 and block[1,2]==1
(block[1,:]==1).all()

也就是说,每个块的整行都是 1

In [66]: P=np.zeros((3,3),int)
    ...: for i in range(window.shape[0]):
    ...:     for j in range(window.shape[1]):
    ...:         block = window[i,j]
    ...:         if (block[1,:]==1).all():
    ...:             P[:] += block
    ...: P            
Out[66]: 
array([[0, 0, 0],
       [0, 0, 0],
       [0, 0, 0]])

在我的小样本中,没有任何大小为 3 的 1 序列。