0

I have to write a make-up program for my university project. How can I change the color of the area I want without losing skin texture? I used Media Pipe to get landmarks cheeks and lip

Like this natural mode image!!!!!!!!!!!

enter image description here

  • since you have the lip region, you can vary the values in HSV color space and view the result – Jeru Luke Apr 13 '22 at 15:46
  • If you can make a mask of the lip area, then process the whole image to modify the color of the lips. Then use the mask to merge the original image with the modified image so that the white area of the mask uses the modified image and the black area of the mask (invert the mask and use that) to use the original image (i.e. outside the lip area). See an example at https://stackoverflow.com/questions/67237755/how-can-i-change-the-skin-color-of-a-human-body-image/67238905#67238905 – fmw42 Apr 13 '22 at 16:52
  • Change hue and saturation only in HSV color space. – Micka Apr 13 '22 at 19:02

1 Answers1

4

Here are the details for one way to do that in Python/OpenCV.

Basically, we get the average color of the lips after creating a mask for the lips. Then get the difference color (in each channel) between that and the desired color. Then we add the difference to the input image. Then we use the mask to combine the original and new image.

Input:

enter image description here

import cv2
import numpy as np
import skimage.exposure

# specify desired bgr color for lips and make into array
desired_color = (170, 130, 255)
desired_color = np.asarray(desired_color, dtype=np.float64)

# create swatch
swatch = np.full((200,200,3), desired_color, dtype=np.uint8)

# read image
img = cv2.imread("lady.jpg")

# threshold on lip color
lower = (0,0,200)
upper = (140,140,255)
mask = cv2.inRange(img, lower, upper)

# apply morphology open and close
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

# get average bgr color of lips
ave_color = cv2.mean(img, mask=mask)[:3]
print(ave_color)

# compute difference colors and make into an image the same size as input
diff_color = desired_color - ave_color
diff_color = np.full_like(img, diff_color, dtype=np.uint8)

# shift input image color
# cv2.add clips automatically
new_img = cv2.add(img, diff_color)

# antialias mask, convert to float in range 0 to 1 and make 3-channels
mask = cv2.GaussianBlur(mask, (0,0), sigmaX=3, sigmaY=3, borderType = cv2.BORDER_DEFAULT)
mask = skimage.exposure.rescale_intensity(mask, in_range=(128,255), out_range=(0,1)).astype(np.float32)
mask = cv2.merge([mask,mask,mask])

# combine img and new_img using mask
result = (img * (1 - mask) + new_img * mask)
result = result.clip(0,255).astype(np.uint8)

# save result
cv2.imwrite('lady_swatch.png', swatch)
cv2.imwrite('lady_mask.png', (255*mask).clip(0,255).astype(np.uint8))
cv2.imwrite('lady_recolor.jpg', result)

cv2.imshow('swatch', swatch)
cv2.imshow('mask', mask)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Final Mask Image:

enter image description here

New Color Swatch:

enter image description here

Result:

enter image description here

fmw42
  • 46,825
  • 10
  • 62
  • 80