from re import U
import cv2
import math
from pylab import mean
from skimage import color
import mediapipe as mp
import imutils
from typing import List, Tuple, Union
from skimage.draw import line, polygon, polygon_perimeter
import numpy as np
from numpy import c_
mp_drawing = mp.solutions.drawing_utils
mp_face_mesh = mp.solutions.face_mesh
def _normalized_to_pixel_coordinates(
normalized_x: float, normalized_y: float, image_width: int,
image_height: int) -> Union[None, Tuple[int, int]]:
"""Converts normalized value pair to pixel coordinates."""
# Checks if the float value is between 0 and 1.
def is_valid_normalized_value(value: float) -> bool:
return (value > 0 or math.isclose(0, value)) and (value < 1 or
math.isclose(1, value))
if not (is_valid_normalized_value(normalized_x) and
is_valid_normalized_value(normalized_y)):
# TODO: Draw coordinates even if it's outside of the image bounds.
return None
x_px = min(math.floor(normalized_x * image_width), image_width - 1)
y_px = min(math.floor(normalized_y * image_height), image_height - 1)
return x_px, y_px
[docs]def apply_color(image, x, y, r, g, b, intensity):
"""
applies color to desired region
Args:
arg1 (image) : input image
arg2 (int array) : X cordinates of the desired region that is going be colored
arg3 (int array) : Y cordinates of the desired region that is going be colored
arg4 (int) : red value of rgb color
arg5 (int) : green value of rgb color
arg6 (int) : blue value of rgb color
arg7 (float) : intensity of the applied color
Returns:
the image with the applied color on the desire area
"""
im_copy = image.copy()
height, width = image.shape[:2]
# converting desired parts of the original image to LAB color space
lip_LAB = color.rgb2lab((im_copy[x, y] / 255.).reshape(len(x), 1, 3)).reshape(len(x), 3)
# calculating mean of each channel
L, A, B = mean(lip_LAB[:, 0]), mean(lip_LAB[:, 1]), mean(lip_LAB[:, 2])
# converting the color of the makeup to LAB
L1, A1, B1 = color.rgb2lab(np.array((r / 255., g / 255., b / 255.)).reshape(1, 1, 3)).reshape(
3, )
# applying the makeup color on image
# L1, A1, B1 = color.rgb2lab(np.array((self.r / 255., self.g / 255., self.b / 255.)).reshape(1, 1, 3)).reshape(3, )
G = L1 / L
lip_LAB = lip_LAB.reshape(len(x), 1, 3)
lip_LAB[:, :, 1:3] = intensity * np.array([A1, B1]) + (1 - intensity) * lip_LAB[:, :, 1:3]
lip_LAB[:, :, 0] = lip_LAB[:, :, 0] * (1 + intensity * (G - 1))
# converting back toRGB
im_copy[x, y] = color.lab2rgb(lip_LAB).reshape(len(x), 3) * 255
return im_copy
def moist(image, x,y, white):
""" finds all the points fillig the lips
Args:
param1 : if motion is detected this parameter is the X cordinate of the lower lip otherwise the X cordinates of the previous frame gloss parts must be passed
param2 : if motion is detected this parameter is the Y cordinate of the lower lip otherwise the Y cordinates of the previous frame gloss parts must be passed
param3 : whether motion is detected
param4 : red
param5 : green
param6 : blue
Returns:
42-element tuple containing
- (*array*): X cordinates of the pixels of the lips which must be glossy
- (*array*): Y cordinates of the pixels of the lips which must be glossy
Todo:
* needs major cleanup
"""
intensitymoist =0.5
val = color.rgb2lab((image[x, y] / 255.).reshape(len(x), 1, 3)).reshape(len(x), 3)
L= mean(val[:, 0])
L1, A1, B1 = color.rgb2lab(np.array((white / 255., white / 255., white / 255.)).reshape(1, 1, 3)).reshape(3, )
ll = L1 - L
length = int(len(x)/4)
Li = val[:, 0]
light_points = sorted(Li)[-length:]
# light_points = sorted(Li)[:length]
min_val = min(light_points)
max_val = max(light_points)
[docs]def apply_blur(image, image2, x, y, gussiankernel, erosionkernel):
"""
applies blur on the desired region
Args:
arg1 (image) : input image
arg2 (image) : input image with applied color on the desired region
arg3 (int array) : X cordinates of the desired region
arg4 (int array) : Y cordinates of the desired region
arg5 (int) : Gussian blur kernel
arg6 (int) : erosion kernel
arg7 (float) : intensity of the applied color
Returns:
the image with the applied blur on the desired region
"""
height, width = image.shape[:2]
filter = np.zeros((height, width))
filter[x,y] = 1
# Erosion to reduce blur size
filter = cv2.GaussianBlur(filter, (gussiankernel, gussiankernel), 0)
kernel = np.ones((erosionkernel, erosionkernel), np.uint8)
filter = cv2.erode(filter, kernel, iterations=1)
alpha = np.zeros([height, width, 3], dtype='float64')
alpha[:, :, 0] = filter
alpha[:, :, 1] = filter
alpha[:, :, 2] = filter
im_copy = (alpha * image2 + (1 - alpha) *image).astype('uint8')
return im_copy
[docs]def apply_blur_color(image, x, y, r, g, b, intensity, gussiankernel=51, erosionkernel=15):
"""
applies blur and color on the desired region
Args:
arg1 (image) : input image
arg2 (int array) : X cordinates of the desired region
arg3 (int array) : Y cordinates of the desired region
arg4 : red value of rgb color
arg5 : green value of rgb color
arg6 : blue value of rgb color
Returns:
the image with the applied clor and blur on the desired region
Note:
this function is used when we need the color to be more faded on the edges of the region, this will give us a more natural look which is used on blush, concelaer and foundation.
"""
# intensity = 0.8
# r = 51
# g = 36
# b = 87
# Create blush shape
height, width = image.shape[:2]
mask = np.zeros((height, width))
mask[x,y] = 1
mask = cv2.GaussianBlur(mask, (gussiankernel, gussiankernel), 0) * intensity
kernel = np.ones((erosionkernel, erosionkernel), np.uint8)
mask = cv2.erode(mask, kernel, iterations=1)
# print(np.array(c_[x_right, y_right])[:, 0])
val = cv2.cvtColor(image, cv2.COLOR_RGB2LAB).astype(float)
val[:, :, 0] = val[:, :, 0] / 255. * 100.
val[:, :, 1] = val[:, :, 1] - 128.
val[:, :, 2] = val[:, :, 2] - 128.
LAB = color.rgb2lab(np.array((float(r) / 255., float(g) / 255., float(b) / 255.)).reshape(1, 1, 3)).reshape(3, )
mean_val = np.mean(np.mean(val, axis=0), axis=0)
mask = np.array([mask, mask, mask])
mask = np.transpose(mask, (1, 2, 0))
lab = np.multiply((LAB - mean_val), mask)
val[:, :, 0] = np.clip(val[:, :, 0] + lab[:, :, 0], 0, 100)
val[:, :, 1] = np.clip(val[:, :, 1] + lab[:, :, 1], -127, 128)
val[:, :, 2] = np.clip(val[:, :, 2] + lab[:, :, 2], -127, 128)
image = (color.lab2rgb(val) * 255).astype(np.uint8)
return image
[docs]def moist(image, x,y, white):
"""
applies gloss texture on the lips
Args:
arg1 (image) : input image
arg2 (int array) : X cordinates of the lips
arg3 (int array) : Y cordinates of the lips
arg4 : a value betwwen 0 to 255 (the higher this value th more white glossy texture will be )
Returns:
the image with the applied gloss on the lips
"""
intensitymoist =0.2
val = color.rgb2lab((image[x, y] / 255.).reshape(len(x), 1, 3)).reshape(len(x), 3)
L= mean(val[:, 0])
L1, A1, B1 = color.rgb2lab(np.array((white / 255., white / 255., white / 255.)).reshape(1, 1, 3)).reshape(3, )
ll = L1 - L
length = int(len(x)/4)
Li = val[:, 0]
light_points = sorted(Li)[-length:]
# light_points = sorted(Li)[:length]
min_val = min(light_points)
max_val = max(light_points)
for i in range(len(val[:, 0])):
if (val[i, 0] <= max_val and val[i, 0] >=min_val):
val[i, 0]+= ll*intensitymoist
image2 = image.copy()
image2[x, y] = color.lab2rgb(val).reshape(len(x), 3) * 255
height, width = image.shape[:2]
filter = np.zeros((height, width))
filter[x,y] = 1
kernel = np.ones((12, 12), np.uint8)
filter = cv2.erode(filter, kernel, iterations=1)
alpha = np.zeros([height, width, 3], dtype='float64')
alpha[:, :, 0] = filter
alpha[:, :, 1] = filter
alpha[:, :, 2] = filter
im_copy = (alpha * image2 + (1 - alpha) *image).astype('uint8')
return im_copy