I am writing a code to change the color of hair in the facial picture of a person. Doing this I made a model and was able to get a mask of the parts of the hair. But now I am stuck at a problem how to change the color of it.
Below is the output mask and input image passed.
Can you suggest me the method that could be used to change the color of the hair into different colors?
Go to the Image menu, then to Adjustments , and choose Replace Color . When the dialog box opens, the first step is to sample the color in the image you want to replace by clicking on it. Now go to the Hue , Saturation , and Lightness controls to set the color you want to use as a replacement.
Quick steps for creating a clipping mask: Select a text or graphic layer to fill with an image. Click Fill with image on the tool palette & choose an image. Select Edit image fill on the Text Tools panel. Adjust the image behind your text or shapes, then click Done.
Since they both have the same shape, you can mask the image of the face using mask image. We first need to perform binary thresholding on it, so it can be used as a b&w mask. Then we can perform boolean indexing based on whether a value is 0
or 255
, and assign a new color, such as green?
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))
Now we can combine the new image with the original using cv2.addWeighted
, which will return the weighted sum of both images, hence we'll only see a difference on the masked region:
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))
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')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With