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