Как изменить цвет изображения с помощью маски? - PullRequest
2 голосов
/ 14 июля 2020

Я пишу код для изменения цвета волос на изображении лица человека. Так я сделал модель и смог получить маску из частей волос. Но теперь я столкнулся с проблемой, как изменить его цвет.

Ниже показаны маска вывода и переданное входное изображение.

enter image description here введите описание изображения здесь

Не могли бы вы предложить мне метод, с помощью которого можно было бы изменить цвет волос на разные цвета?

1 Ответ

4 голосов
/ 14 июля 2020

Поскольку они оба имеют одинаковую форму, вы можете замаскировать изображение лица с помощью маски изображения. Сначала нам нужно выполнить для него бинарную пороговую обработку, чтобы его можно было использовать в качестве черно-белой маски. Затем мы можем выполнить логическое индексирование в зависимости от того, является ли значение 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))

enter image description here

Now we can combine the new image with the original using 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))

enter image description here

Note that you can set the weights in the weighted sum via the alpha and beta parameters, depending on how much you want the new colour to predominate. Note that, as mentioned earlier the new image will be obtained from the weighted sum dst = src1*alpha + src2*beta + gamma. Let's try with another colour and setting the weights as a convex combination with alpha values ranging from say 0.5 and 0.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')

введите описание изображения здесь

...