"""
close_eye.py


目を閉じた画像を作ります。

目と上まつ毛の部分をポイントとしており、そこをinpaintします。
inpaint部分をぼかして、元の画像の上にはりつけ、ぼかします。



著者: Akihito Miyazaki
作成日: 2024-04-23
更新履歴:
  - 2024-04-23: 最初のリリース
  - 2024-09-24: name suffixを追加
  - 2034-11-15: changed for huggingface
"""
import os
import cv2
import numpy as np


from glibvision.numpy_utils import bulge_polygon

from glibvision.cv2_utils import fill_points,get_image_size,gray3d_to_2d,blend_rgb_images,create_color_image
from landmarks68_utils import get_left_upper_eyelid_points,get_right_upper_eyelid_points,get_bulged_eyes,get_close_eyelid_point


def create_eyelid_mask(image,face_landmarks_list,thick = 1,bulge=0.2):
    black = create_color_image(image,(0,0,0))
    left_eyelid = get_left_upper_eyelid_points(face_landmarks_list)
    left_eyelid = bulge_polygon(left_eyelid,bulge)
    fill_points(black,left_eyelid)

    print("right")
    right_eyelid = get_right_upper_eyelid_points(face_landmarks_list)
    print(right_eyelid)    
    right_eyelid = bulge_polygon(right_eyelid,bulge)
    fill_points(black,right_eyelid)

    eyes_points = get_bulged_eyes(face_landmarks_list)
    for points in eyes_points:
        np_points = np.array(points,dtype=np.int32)
        cv2.fillPoly(image, [np_points], (255,255,255))
        if thick > 0:
            cv2.polylines(black, [np_points], isClosed=False, color=(255,255,255), thickness=thick)

    return  cv2.cvtColor(black,cv2.COLOR_BGR2GRAY)

DEBUG = False
def process_close_eyes_image(img,landmarks_list,eyelid_thick=1,eyelid_blur=9,inpaint_radius=10,inpaint_blur=30,mask_dilate=10,dilate_blur=10):
    img_h, img_w = get_image_size(img)

    eyelid_mask = create_eyelid_mask(img,landmarks_list)
    if DEBUG:
        cv2.imwrite("close_eye_mask.jpg",eyelid_mask)

    mask = gray3d_to_2d(eyelid_mask)
 

    img_inpainted = cv2.inpaint(img, mask,inpaint_radius, cv2.INPAINT_TELEA)
    if DEBUG:
        cv2.imwrite("close_eye_inpaint.jpg",img_inpainted)

    ## Inpaintした画像をぼかす。
    if inpaint_blur>0:
        if inpaint_blur%2==0:   #if even it would error
            inpaint_blur+=1
        blurred_image = cv2.GaussianBlur(img_inpainted, (inpaint_blur, inpaint_blur), 0)
        if DEBUG:
            cv2.imwrite("close_eye_inpaint_burred.jpg",blurred_image)
    else:
        blurred_image=img_inpainted
   

    # まつげを描く
    if eyelid_thick>0:
        left,right = get_close_eyelid_point(landmarks_list)
        for points in [left,right]:
            print("## draw eyelid")
            print(points)
            cv2.polylines(blurred_image, [np.array(points)], isClosed=False, color=(0,0,0), thickness=eyelid_thick,lineType=cv2.LINE_AA)
        if DEBUG:
            cv2.imwrite("close_eye_inpaint_burred_eyeline.jpg",blurred_image)




    if eyelid_thick>0 and eyelid_blur>0:
        if eyelid_blur%2==0:
            eyelid_blur+=1
        # blur-eyelid-line
        blurred_image = cv2.GaussianBlur(blurred_image, (eyelid_blur, eyelid_blur), 2)


    print(mask_dilate,dilate_blur)
    if mask_dilate>0:
        # Inpaintの境界線から少し広げている
        kernel = np.ones((mask_dilate, mask_dilate), np.uint8)
        extend_mask = cv2.dilate(mask, kernel, iterations=1)

        if dilate_blur>0:
            if dilate_blur%2==0:
                dilate_blur+=1

            extend_burred_mask = cv2.GaussianBlur(extend_mask, (dilate_blur, dilate_blur), 1)
        else:
            extend_burred_mask = extend_mask
    else:
        extend_burred_mask=mask

    
    img_inpainted = blend_rgb_images(img,blurred_image,extend_burred_mask)
    
    if DEBUG:
        cv2.imwrite("create_no_mouth_image_merged.jpg",img_inpainted)

    return img_inpainted,extend_burred_mask