如何使用遮罩更改图像的颜色?

11

我正在编写一段代码来改变人脸图片中头发的颜色。我已经建立了一个模型并成功得到了头发部分的掩码,但现在遇到了如何改变其颜色的问题。

以下是输出的掩码和输入的图片:

enter image description here enter image description here

你能给我建议,提供可用于将头发颜色改变为不同颜色的方法吗?

1个回答

28

由于两者具有相同的形状,因此可以使用掩模图像来屏蔽面部图像。我们首先需要对其执行二进制阈值处理,以便将其用作黑白掩模。然后,我们可以根据一个值是 0 还是 255 进行布尔索引,并分配一个新颜色,例如绿色?

import cv2
mask = cv2.imread('eBB2Q.jpg')
face = cv2.imread('luraB.jpg')

_, mask = cv2.threshold(mask, thresh=180, maxval=255, type=cv2.THRESH_BINARY)
# copy where we'll assign the new values
green_hair = np.copy(face)
# boolean indexing and assignment based on mask
green_hair[(mask==255).all(-1)] = [0,255,0]

fig, ax = plt.subplots(1,2,figsize=(12,6))
ax[0].imshow(cv2.cvtColor(face, cv2.COLOR_BGR2RGB))
ax[1].imshow(cv2.cvtColor(green_hair, cv2.COLOR_BGR2RGB))

输入图像描述

现在,我们可以使用cv2.addWeighted将新图像与原始图像结合起来,它将返回两个图像的加权和,因此我们只会在掩膜区域看到差异:

green_hair_w = cv2.addWeighted(green_hair, 0.3, face, 0.7, 0, green_hair)

fig, ax = plt.subplots(1,2,figsize=(12,6))
ax[0].imshow(cv2.cvtColor(face, cv2.COLOR_BGR2RGB))
ax[1].imshow(cv2.cvtColor(green_hair_w, cv2.COLOR_BGR2RGB))

输入图像描述

请注意,您可以通过alphabeta参数设置加权和中的权重,具体取决于您希望新颜色占主导地位的程度。请注意,如前所述,新图像将从加权和dst = src1*alpha + src2*beta + gamma中获得。让我们尝试另一种颜色,并将权重设置为凸组合,其中alpha值范围从0.50.9

green_hair = np.copy(face)
# boolean indexing and assignment based on mask
green_hair[(mask==255).all(-1)] = [0,0,255]
fig, axes = plt.subplots(2,2,figsize=(8,8))
for ax, alpha in zip(axes.flatten(), np.linspace(.6, .95, 4)):
    green_hair_w = cv2.addWeighted(green_hair, 1-alpha, face, alpha, 0, green_hair_w)
    ax.imshow(cv2.cvtColor(green_hair_w, cv2.COLOR_BGR2RGB))
    ax.axis('off')

在此输入图片描述


7
嗯...时尚! - Mark Setchell
我相信 OP 想要改变她头发的颜色,而不是将其去除并用绿色背景代替。您应该能够通过将颜色与她的头发结合来使头发变成绿色。您可以使用 cv2.addWeighted 来实现这一点。 - Tyson
2
是的,考虑到了这一点,已经更新了。尽管当前掩码的限制很明显 @Tyson - yatu
2
哇,看起来很不错!比我预期的要好得多。另一个想法是将她的头发转换到HSV颜色空间,稍微改变色调,然后在遮罩之前将其转换回BGR。这可能会提高她头发中暗区域成为过于亮绿色的问题。 - Tyson
2
好像是个不错的主意。我会在有更多时间的时候试一试 :) 再次感谢 @Tyson - yatu
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接