Akjava's picture
iniit
81e69dc
"""
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}")