""" create_hole_image.py open_mouth.pyの一部 著者: Akihito Miyazaki 作成日: 2024-04-23 更新履歴: - 2024-04-23: 最初のリリース - 2024-09-15:slide_amountを追加 """ import cv2 import numpy as np from PIL import Image import lip_utils def vertical_slide(image, slide_amount): height, width = image.shape[:2] # スライド量が画像の高さより大きい場合、画像の高さに制限する slide_amount = min(slide_amount, height) slide_amount = max(slide_amount, -height) slide_image = np.zeros_like(image) # 入力画像と同じサイズと型の画像を作成 if slide_amount > 0: # 下にスライド slide_image[slide_amount:, :] = image[:height - slide_amount, :] elif slide_amount < 0: # 上にスライド slide_image[:height + slide_amount, :] = image[-slide_amount:, :] else: slide_image = image.copy() return slide_image def file_name_check(path): max_name_limit = 50 check = True if path.find("..")!=-1: check = False if path.find("/")!=-1: check = False if path.find("\\")!=-1: check = False if path.find(":")!=-1: check = False if len(path)>max_name_limit: print(f"name is limited {max_name_limit}") check = False if not check: ValueError(f"Invalid Name {path}") def process_create_hole_image(img,landmarks_list,open_size_y = 0,open_size_x=0,hole_offset=0,hole_image_name="dark01.jpg"): file_name_check(hole_image_name) img_h, img_w = lip_utils.get_image_size(img) # 画像を複製して、アラインポイントを描画する。アラインは、傾きも考慮した唇の範囲 img_lined = np.copy(img) points = lip_utils.get_top_lip_align_points(landmarks_list) img_lined1 = np.copy(img) print(points) cv2.polylines(img_lined1, [np.array(points)], isClosed=True, color=(0,255,0), thickness=1) if lip_utils.DEBUG: cv2.imwrite("create_hole_top_lip_align_line.jpg",img_lined1) print(f"align point = {points}") diff_align_x = points[0][0]-points[2][0] print(f"diff_align_x = {diff_align_x}") np_points = np.array(points) diff_left = np_points[2] - np_points[0] #left-bottom ,left-up diff_right = np_points[3] - np_points[1] #right-bottom,right-up print(f"diff left-y = {diff_left},diff right-y ={diff_right}") top_lip_thicks = lip_utils.get_top_lip_thicks(landmarks_list) # this ignore rotation top_lip_thicks2 = lip_utils.get_top_lip_thicks(landmarks_list,True) # this ignore rotation lip_thick = np.mean(top_lip_thicks) lip_thick2 = np.mean(top_lip_thicks2) base_mouth_size = lip_thick2*1.5 mouth_angle=lip_utils.calculate_clockwise_angle(points[2],points[3]) angled_point=lip_utils.calculate_new_point((0,0),base_mouth_size,mouth_angle+90) angled_mouth_size = angled_point[1] + open_size_y #print(f"lip_thick2={lip_thick2}") print(f"lip thick2 ={lip_thick2} base_mouth_size={base_mouth_size} mouth_angle={mouth_angle} angled_mouth_size={angled_mouth_size}") #上唇の範囲を元に、口全体を定義するため、根拠ないけど1.x倍にしている。 https://github.com/akjava/lip_recognition_tools/issues/8 diff_left[1] = angled_mouth_size diff_right[1] = angled_mouth_size diff_left[0] *=0 diff_right[0] *=0 expand_left = np_points[2] + diff_left expand_right = np_points[3] + diff_right # X座標も拡大するが、基本使わないので無視してもいい。 expand_points = np.array([np_points[0],np_points[1],expand_left,expand_right]) print(f"expand_points = {[np_points[0],np_points[1],expand_left,expand_right]}") cv2.polylines(img_lined, [expand_points], isClosed=True, color=(0,255,0), thickness=1) if lip_utils.DEBUG: cv2.imwrite("create_hole_image_top-align_line.jpg",img_lined) # これまた、hole用の画像をなんとなく、サイズに合わせている。 # そのため、画像の位置調整が非常に微妙になる # TODO 画像の指定引数 https://github.com/akjava/lip_recognition_tools/issues/9 # https://github.com/akjava/lip_recognition_tools/issues/10 #hole_image = cv2.imread("hole_images/hole_01_light_dark.jpg") hole_image = cv2.imread(f"hole_images/{hole_image_name}") hole_image = vertical_slide(hole_image,hole_offset) if lip_utils.DEBUG: cv2.imwrite("create_hole_image-slided_hole_image.jpg",hole_image) #exit(0) hole_image_h,hole_image_w = lip_utils.get_image_size(hole_image) max_w = hole_image_w max_h = hole_image_h expand_list = expand_points.tolist() aligned_hole_image = lip_utils.create_moved_image(hole_image, [(0,0),(max_w,0), (0,max_h),(max_w,max_h)], expand_list ) if lip_utils.DEBUG: cv2.imwrite("create_hole_image_top-align_image.jpg",aligned_hole_image) img_face = np.copy(img) lip_utils.copy_image(img_face,aligned_hole_image,expand_list[0][0] - diff_align_x,(expand_list[0][1]+expand_list[1][1])//2) if lip_utils.DEBUG: cv2.imwrite("create_hole_image_top-align_face.jpg",img_face) return img_face if __name__ == "__main__": # 画像ファイルのパス img_path = "00012245.jpg" #"straight.jpg" img = cv2.imread(img_path) landmarks_list = lip_utils.image_to_landmarks_list(img) process_create_hole_image(img,landmarks_list)