""" create_no_mouth.py open_mouth.pyの一部 口のない画像を作ります。 口の部分のをlandpointを取って、その部分を消して、inpaintします。 inpaint部分をぼかして、元の画像の上にはりつけ、ぼかします。 著者: Akihito Miyazaki 作成日: 2024-04-23 更新履歴: - 2024-04-23: 最初のリリース """ 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_image def process_create_no_mouth_image(img,landmarks_list): img_h, img_w = lip_utils.get_image_size(img) ## 口の範囲をInpaintで消す。 (bottom_width,bottom_height)=lip_utils.get_bottom_lip_width_height(landmarks_list) lip_points = lip_utils.get_lip_mask_points(landmarks_list) # 選択範囲を丸めてみたけど、それほどメリットが感じなかった。 #lip_points = lip_utils.bulge_polygon(lip_points,0.1) # 唇のマスク範囲を検証 if lip_utils.DEBUG: img_lined = np.copy(img) cv2.polylines(img_lined, [np.array(lip_points)], isClosed=True, color=(0,255,0), thickness=1) cv2.imwrite("create_no_mouth_image_polyline.jpg",img_lined) # 唇のエッジ部分は、影やら、ピンクなどあるので、それを削るのに、下唇の高さを元にしている。0.5は根拠ない。 dilation_size = int(bottom_height*0.5) lip_mask = lip_utils.create_mask_from_points(img,lip_points,dilation_size,0) # inpaintで使うので、ぼかしは不要 if lip_utils.DEBUG: lip_utils.print_numpy(lip_mask,"lip mask") if lip_utils.DEBUG: cv2.imwrite("create_no_mouth_image_mask.jpg",lip_mask) img_inpainted = cv2.inpaint(img, lip_mask,3, cv2.INPAINT_TELEA) if lip_utils.DEBUG: cv2.imwrite("create_no_mouth_image_inpaint.jpg",img_inpainted) ## Inpaintした部分をぼかしている。 blurred_image = cv2.GaussianBlur(img_inpainted, (29, 29), 0) #場合によっては奇数じゃないとエラーが出ることがある if lip_utils.DEBUG: cv2.imwrite("create_no_mouth_image_blurred.jpg",blurred_image) apply_binary_mask_to_image(img_inpainted,blurred_image,lip_mask) if lip_utils.DEBUG: cv2.imwrite("create_no_mouth_image_blurred1_applied.jpg",blurred_image) # 全体を少しぼかす blurred_image2 = cv2.GaussianBlur(img_inpainted, (9, 9), 0) if lip_utils.DEBUG: cv2.imwrite("create_no_mouth_image_blurred2.jpg",blurred_image2) # Inpaintの境界線から少し広げている kernel = np.ones((8, 8), np.uint8) lip_mask = cv2.dilate(lip_mask, kernel, iterations=1) # 全体を少しぼかす blurred_mask = cv2.GaussianBlur(lip_mask, (19, 19), 0) if lip_utils.DEBUG: cv2.imwrite("create_no_mouth_image_blurred_mask.jpg",blurred_mask) # https://github.com/akjava/lip_recognition_tools/issues/12 #cv2_utils.apply_binary_mask_to_image(img_inpainted,blurred_image2,lip_mask) img_inpainted = blend_rgb_images(img_inpainted,blurred_image2,lip_mask) if lip_utils.DEBUG: cv2.imwrite("create_no_mouth_image_merged.jpg",img_inpainted) return img_inpainted if __name__ == "__main__": # 画像ファイルのパス img_path = "straight.jpg" img = cv2.imread(img_path) landmarks_list = lip_utils.image_to_landmarks_list(img) process_create_no_mouth_image(img,landmarks_list)