如何使用 openCV python 将图像的蒙版部分替换为另一幅图像?

How to replace a masked part of an image with another image using openCV python?

objective是将一张图片的一部分替换成另一张图片。我打算做的是获取原图的segment map,将原图选中的部分替换为另一张图片

例如,这是一张原图的分段图:

我想用另一个男模特(不同的人)替换那个粉红色的分段面具:

我应该怎么做呢?我正在考虑根据粉红色 (RGB 值为 192,128,128)bitwise_and 这两个图像来选择 ROI?但我不太确定该怎么做,或者这是否是最好的方法。

我知道粉红色面具和样本人物并不完全吻合,但我只是希望能够先将模型拟合到粉红色部分,然后再缩放或变换它。

任何建议都会很棒!谢谢!

首先,在继续实施之前,您需要考虑一些事项。

  • 遮罩图像的背景是否一致?蒙面斑点的颜色一致?
  • 蒙版的大小和要添加图像的对象。

我建议你先在粉色分割图上找到ROI的大小、颜色和位置。根据遮罩图像缩放物体(男孩图像)的尺寸,这样更容易将物体图像遮罩到粉红色部分。

然后您可以创建一个尺寸与蒙版图像相似的图像(让我们称之为第一步图像)。将缩放的对象图像添加到从粉红色斑点分析获得的位置。这样你就会有两个尺寸和比例相似的图像。

第一步图像和粉色 ROI 在视觉上应该很容易重叠。

如果您想要精确的粉红色,那么如果蒙版图像上的相同位置像素为黑色,则将第一步图像上的所有像素替换为黑色像素。否则就让它成为现实吧。

if(mask[i][j] == black){ step_one[i][j] = black }

这使得对象图像中的粉红色部分被掩盖了。

加载库和读取图像

from __future__ import division
import cv2
import numpy as np

guy_img = cv2.imread('path')
target_img = cv2.imread('path')

获取人物(每个非零像素)和目标蒙版(粉红色区域)的边界框。

a = np.where(guy_img > 0)
b = np.where(target_img == 129)  # picked one of the channels in your image
bbox_guy = np.min(a[0]), np.max(a[0]), np.min(a[1]), np.max(a[1])
bbox_mask = np.min(b[0]), np.max(b[0]), np.min(b[1]), np.max(b[1])

注意当我加载目标图像时,值与您提供的值不同。图像边缘也有一些白色像素。这可能只是由于图像被上传到 imgur 并被下载。如果你的值是正确的并且你的图像的其余部分除了粉红色区域之外完全是黑色的,你可以像我用 np.where(target_img > 0).

为男人图像所做的一样获得所有非零像素

现在只获取人物和蒙版区域的值

guy = guy_img[bbox_guy[0]:bbox_guy[1], bbox_guy[2]:bbox_guy[3],:]
target = target_img[bbox_mask[0]:bbox_mask[1], bbox_mask[2]:bbox_mask[3],:]

将人物调整为与面具相同的比例/形状

guy_h, guy_w, _ = guy.shape
mask_h, mask_w, _ = target.shape
fy = mask_h / guy_h
fx = mask_w / guy_w
scaled_guy = cv2.resize(guy, (0,0), fx=fx,fy=fy)

用人物图像值重新分配目标图像的蒙版区域

for i, row in enumerate(range(bbox_mask[0], bbox_mask[1])):
    for j, col in enumerate(range(bbox_mask[2], bbox_mask[3])):
        target_img[row,col,:] = scaled_guy[i,j,:]

cv2.imshow('', target_img)
cv2.waitKey(0)