File size: 4,937 Bytes
81e69dc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

"""
close_lip.py


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

唇の開いている範囲をinpaintします。
そこに、hole部分を影として戻します。



著者: Akihito Miyazaki
作成日: 2024-04-23
更新履歴:
  - 2024-04-23: 最初のリリース
  - 1024-11-16:coverted to huggingface-space (but args broken)
"""
import os
import cv2
import numpy as np
from PIL import Image
import lip_utils


from glibvision.cv2_utils import blend_rgb_images
from glibvision.numpy_utils import apply_binary_mask_to_color,create_2d_image

import argparse





def create_top_lip_low_mask(image,face_landmarks_list,line_thick = 1):
    black = create_2d_image(image.shape)
    lip_utils.fill_top_lower(black,face_landmarks_list,line_thick,lip_utils.COLOR_WHITE)
    return  black

def create_lip_hole_mask(image,face_landmarks_list,line_thick = 1):
    black = create_2d_image(image.shape)
    lip_utils.fill_lip_hole(black,face_landmarks_list,line_thick,lip_utils.COLOR_WHITE)

    return  black

def process_close_lip_image(img,landmarks_list):
    img_h, img_w = lip_utils.get_image_size(img)

    hole_mask = create_lip_hole_mask(img,landmarks_list,0)

    lower_lip_mask = create_top_lip_low_mask(img,landmarks_list)

    #these make dirty
    #kernel = np.ones((3, 3), np.uint8)
    #lower_lip_mask = cv2.erode(lower_lip_mask, kernel, iterations=1)


    if lip_utils.DEBUG:
        cv2.imwrite("close_lip_01_mask.jpg",lower_lip_mask)
    
    mixed_mask = cv2.bitwise_or(hole_mask,lower_lip_mask)
    if lip_utils.DEBUG:
        cv2.imwrite("close_lip_01_mask_mixed.jpg",mixed_mask)

    img_inpainted = cv2.inpaint(img, mixed_mask,3, cv2.INPAINT_NS)
    if lip_utils.DEBUG:
        cv2.imwrite("close_lip_02_inpaint.jpg",img_inpainted)
   

    copy_impainted=img_inpainted.copy()
    apply_binary_mask_to_color(copy_impainted,(0,8,50),hole_mask)
    #lip_utils.fill_lip_hole(img_inpainted,landmarks_list,0,(0,8,50)) # BGR
    if lip_utils.DEBUG:
        cv2.imwrite("close_lip_03_hole.jpg",copy_impainted)
   

    

    ## Inpaintした画像をぼかす。
    blurred_image = cv2.GaussianBlur(copy_impainted, (9, 9), 0) #場合によっては奇数じゃないとエラーが出ることがある
    if lip_utils.DEBUG:
        cv2.imwrite("close_lip_04_burred.jpg",blurred_image)


     # Inpaintの境界線から少し広げている
    kernel = np.ones((3, 3), np.uint8)
    shrink_mask = cv2.erode(hole_mask, kernel, iterations=1)


    shrink_burred_mask = cv2.GaussianBlur(shrink_mask, (3, 3), 0)
    if lip_utils.DEBUG:
        cv2.imwrite("close_lip_05_final_hole_mask.jpg",shrink_burred_mask)

    img_inpainted = blend_rgb_images(img_inpainted,blurred_image,shrink_burred_mask)
    if lip_utils.DEBUG:
        cv2.imwrite("close_lip_05_final_hole.jpg",img_inpainted)
    # Inpaintの境界線から少し広げている
    kernel = np.ones((3, 3), np.uint8)
    extend_mask = cv2.dilate(lower_lip_mask, kernel, iterations=1)


    extend_burred_mask = cv2.GaussianBlur(extend_mask, (3, 3), 0)
    if lip_utils.DEBUG:
        cv2.imwrite("close_lip_05_final_lip_mask.jpg",extend_burred_mask)
    img_inpainted = blend_rgb_images(img_inpainted,blurred_image,extend_burred_mask)
    
    if lip_utils.DEBUG:
        cv2.imwrite("close_lip_05_final_lip.jpg",img_inpainted)

    mixed_mask = cv2.bitwise_or(shrink_burred_mask,extend_burred_mask)
    mixed_mask[mixed_mask>0] = 255
    mixed_mask = cv2.dilate(mixed_mask, (1,1), iterations=1)
    #    mixed_mask = cv2.GaussianBlur(mixed_mask, (3, 3), 0)

    if lip_utils.DEBUG:
        cv2.imwrite("close_lip_05_final_mixed_mask.jpg",mixed_mask)

    return img_inpainted,mixed_mask

if __name__ == "__main__":
  parser = argparse.ArgumentParser(description='Open Mouth')
  parser.add_argument('--input',"-i",help='変換する画像の元(必須) 口を閉じていること',required=True)
  parser.add_argument('--output',"-o",help='画像の保存先(別途一時的なレイヤーファイルも作られる)')
  parser.add_argument('--landmark',"-l",help='landmarkdata')
  parser.add_argument('--scale',"-sc",help='スケール精度が上がる',default=4,type=int)

  args = parser.parse_args()
  # 画像ファイルのパス
  img_path = args.input
  img = cv2.imread(img_path)
  #landmarks_list = landmark_utils.load_landmarks(img,args.scale,args.landmark)
  landmarks_list = None
  eye_closed_image,mask = process_close_lip_image(img,landmarks_list)

  output_path = args.output
  if output_path == None:
    parent_path,file = os.path.split(img_path)
    name,ext = os.path.splitext(file)
    output_path = os.path.join(parent_path,f"{name}_lipclose{ext}")
      

  

  parent_path,file = os.path.split(output_path)
  name,ext = os.path.splitext(file)

  mask_path = os.path.join(parent_path,f"{name}_mask{ext}")
  cv2.imwrite(mask_path,mask)
  cv2.imwrite(output_path,eye_closed_image)
  print(f"complete image {output_path} and mask {mask_path}")