numpy 用另一个图像掩蔽RGBA图像

lyr7nygr  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(80)

假设有两个不同形状的opencv images / numpy数组。较小的一个称为small,是(150,150,4),较大的一个称为big,是(300,300,4),都是RGBA图像。我试图让较小的一个在较大的一个的“上面”,正好在中间(这已经完成,工作正常),但我只需要较小的一个的像素,这是不透明的(他们的alpha通道不等于0,或者确切地说是等于255),否则我想保留较大的一个的像素(这是问题)。类似于三元运算符,但在numpy/opencv中有广播功能。我想到了np.where和masking,但是卡住了。我知道如何获得我的较小形状的mask,但我不知道如何正确分配/广播到较大的形状。
我的方法是:

  • 获取应该进行赋值的矩形(偏移量)
  • 得到较小的一个面具,只有形状的坐标
    *assign / broadcast the pixels-问题是我需要的是较大图像对应坐标的像素值,而不是单个值。我遗漏的部分,当前使用一些虚拟值
  • 将修改后的较小值赋值到较大值的坐标中
BACKGROUND_SIZE = 300, 300
LOGO_SIZE = 150, 150

def get_offset(bigger_shape, smaller_shape):
    logo_x_offset = int((bigger_shape[0] - smaller_shape[0]) / 2)
    logo_y_offset = int((bigger_shape[1] - smaller_shape[1]) / 2)
    return (
        logo_y_offset,
        logo_y_offset + smaller_shape[1],
        logo_x_offset,
        logo_x_offset + smaller_shape[0],
    )

small = cv2.imread(f"./small.png", flags=cv2.IMREAD_UNCHANGED)
big =  cv2.imread(f"./big.png", flags=cv2.IMREAD_UNCHANGED)
offset = get_offset(BACKGROUND_SIZE, LOGO_SIZE)
y0, y1, x0, x1 = offset

DUMMY_BLUE = (255,0,0,255)
mask = np.where(small[:, :, 3] != 255) # this is a proper mask
small[mask] = DUMMY_BLUE # Here instead of the dummy blue I need the "bigger" image pixels 
bigger[y0:y1, x0:x1] = smaller

尝试:

small[mask] = big[y0:y1, x0:x1]

但这失败了(请忽略第二个形状,big实际上可能更大):

ValueError: shape mismatch: value array of shape (150,150,4) could not be broadcast to indexing result of shape (14899,4)
ukdjmx9f

ukdjmx9f1#

您可以通过将小图像乘以遮罩,然后添加:

mask = small[:, :, 3] == 255
small *= mask[:, :, None]
big[y0:y1, x0:x1] *= 1 - mask[:, :, None]
big[y0:y1, x0:x1] += small

相关问题