Numpy -将小数组放在大数组的坐标上?

cu6pst1q  于 12个月前  发布在  其他
关注(0)|答案(4)|浏览(131)

下面是一个2D-numpy数组:

matrix = np.zeros((250, 250))

字符串
现在,在不同的坐标上,我不仅要用一个更小的数组替换坐标值,还要用一个更小的数组替换它的局部邻域。作为示例性的替换,我们可以取一个菱形:

import skimage.morphology
star = skimage.morphology.diamond(3)  # small array / replacement

coords_r = np.random.randint(0, 250, 20)  # row coordinates
coords_c = np.random.randint(0, 250, 20)  # column coordinates


我想出了以下相当草率的方法,并想知道是否有一个更简单/更优雅的解决方案。此外,如果两个对象足够接近,此方法将覆盖:

max_r, max_c = matrix.shape
obj = star
half_obj = int((star.shape[0])/2)

for r, c in zip(coords_r, coords_c):
    
    curr_obj = obj
    start_r = r-half_obj-1
    end_r = r+half_obj
    start_c = c-half_obj-1
    end_c = c+half_obj
    
    # Check if on corners
    if r-half_obj-1 < 0:
        start_r = 0
        curr_obj = curr_obj[-r:, :]
    if r+half_obj > matrix.shape[0]:
        end_r = max_r
        curr_obj = curr_obj[:max_r-start_r, :]
    if c-half_obj-1 < 0:
        start_c = 0
        curr_obj = curr_obj[:, -c:]
    if c+half_obj > matrix.shape[1]:
        end_c = max_c
        curr_obj = curr_obj[:, :max_c-start_c]
        
    matrix[start_r:end_r, start_c:end_c] = curr_obj


先谢了。

kwvwclae

kwvwclae1#

你需要更好地利用numpy切片。据我所知,两个随机数组coords_r, coords_c是你想要放置星星的中心坐标。我会
1.将这些转换为矩形裁剪坐标列表
1.在坐标上循环并将星星放置在每个切片中

def center_to_bbox(coords, star_size):
    coords_x, coords_y = coords
    x1, y1, x2, y2 = coords_x - star_size, coords_y - star_size, coords_x + star_size + 1, 
    coords_y + star_size + 1,
    bboxes =(x1, y1, x2, y2)
    return bboxes
x_coords = np.random.randint(0, 250 - 3, 20)  
y_coords = np.random.randint(0, 250 - 3 , 20)
x1, y1, x2, y2 = bboxes
for x1_, y1_, x2_, y2_ in zip(x1, y1, x2, y2):
    matrix[y1_:y2_, x1_:x2_] = star

字符串
还请注意,您也可以减去星星的维度,这样就不必在以后的边界处进行补偿

n9vozmp4

n9vozmp42#

看起来你可能想使用scipy sparse matrices。只需定义小矩阵并将它们添加到更大的矩阵中。lil_matrix似乎是你正在寻找的合适格式。
编辑:@iantonuk我在想下面的方法,它在添加/组装矩阵时效果很好,但在替换条目时效果不好。

from scipy.sparse import coo_matrix
data1 = ((1.0,2.0,3.0),([0,1,2],[0,1,2]))
mat1  = coo_matrix(data1,shape=(3,3))
print(mat1.todense())
data2 = ((2.0,3.0),([1,2],[1,2]))
mat2  = coo_matrix(data2,shape=(3,3))
print(mat2.todense())
mat3  = mat1 + mat2
print(mat3.todense())

字符串

tp5buhyn

tp5buhyn3#

我问过类似的问题:Add small image to the canvas as numpy arrays
以下是我对你的问题的解决方案:

matrix_size = 250
star_size = 3

matrix = np.ones((matrix_size, matrix_size))
star = 1 - skimage.morphology.diamond(star_size)

coords_r = np.random.randint(0, matrix_size, 20)  # row coordinates
coords_c = np.random.randint(0, matrix_size, 20)  # column coordinates

for r, c in zip(coords_r, coords_c):
    matrix[max(r - star_size, 0):r + star_size + 1, max(c - star_size, 0):c + star_size + 1] *= star[max(star_size - r, 0):star_size + matrix_size - r, max(star_size - c, 0):star_size + matrix_size - c]
matrix = 1-matrix

字符串
这就是我得到的:

lo8azlld

lo8azlld4#

以下是你可以用矢量化的方式轻松做到这一点:

def put_rounds(image:np.array, ptsx, ptsy):
    xm1, x, xp1 = (ptsx-1,ptsx,ptsx+1)
    ym1, y, yp1 = (ptsy-1,ptsy,ptsy+1)

    #make a round, r=3 or diamond pattern or whatever you need
    ptsx3 = np.dstack((xm1, xm1, ptsx,xm1,ptsx, xp1, ptsx,xm1, xp1)).flatten()
    ptsy3 = np.dstack((ym1, yp1, ym1,ptsy,ptsy, ptsy,yp1, yp1, yp1)).flatten()

    #this at least 7.5-12 times faster then loops(at least 50+ times faster on torch)
    image[ptsy3, ptsx3] = np.array([255,255,0])

字符串

相关问题