Numpy select 跳棋图案到新数组

Numpy select checkers pattern to new array

我有一个具有奇数行和列的二维正方形矩阵。例如

11 12 13 14 15
21 22 23 24 25
31 32 33 34 35
41 42 43 44 45
51 52 53 54 55

我需要将它顺时针旋转 45 度,select 最大方阵。在这种情况下:

13 24 35
22 33 44
31 42 53

我可以在两个周期内完成:

new_arr = np.zeros(((orig_range+1)//2, (orig_range+1)//2)
for new_h in range((orig_range+1)//2):
    for new_w in range((orig_range+1)//2):
        old_h = new_h + new_w
        old_w = ((orig_range+1)//2) - new_h + new_w  
        new_arr[new_h, new_w] = orig_arr[old_h, old_w] 

但是这种方法很慢。 cv2 中的旋转相当快,但“像素”对齐不佳。由于舍入误差,使用 sqrt(2) 缩放正向旋转然后使用 sqrt(2) 缩放反向旋转会导致图像中心区域像素的颜色发生变化。

旋转这样一个矩阵的有效方法是什么?

您可以使用 Numba 的 JIT 来显着加快操作速度,尤其是通过 运行 并行和本机操作。此外,请注意数组不需要用零填充。这是一个未经测试的例子:

import numba as nb

@nb.njit(parallel=True)
def compute(orig_range, orig_arr):
    new_arr = np.empty(((orig_range+1)//2, (orig_range+1)//2)
    for new_h in nb.prange((orig_range+1)//2):
        for new_w in range((orig_range+1)//2):
            old_h = new_h + new_w
            old_w = ((orig_range+1)//2) - new_h + new_w  
            new_arr[new_h, new_w] = orig_arr[old_h, old_w]
    return new_arr

您可以指定输入的类型来提前编译函数,从而避免第一次调用明显变慢。此操作在缓存中适合数组时应该非常快。对于大数组,可以使用 tiling 和不同的 read/write 排序来加快操作速度。