Akjava's picture
iniit
81e69dc
"""
bottom_lip.py
open_mouthの一部 下唇レイヤーの生成
単独ではまだ動かない。
著者: Akihito Miyazaki
作成日: 2024-04-23
更新履歴:
- 2024-04-23: 最初のリリース
"""
import cv2
import numpy as np
from PIL import Image
from lip_utils import *
import lip_utils
from scipy.ndimage import binary_dilation, gaussian_filter
def process_lip_image(img,landmarks_list, crop_image_margin, open_size_y, open_size_x):
"""
唇画像を処理する関数
open_size_x 最終画像で端をカットしている
side_tipsに値をコピーしている。side_tips
"""
# 画像の読み込み
side_tips = 0 # remove cropped pixel
edge_x =0 # remove side pixel from final image
# 口の開きに応じて、中心を下げようとしたが、真ん中が下がるのは極めて不自然なのでやめた。
# そのうち、5分割の中心を変形するのに使いたい
mid_lip_move_ratio = open_size_y/80.0 if open_size_y>0 else 0
mid_lip_move_ratio = 0
if open_size_x>0:# ここ謎コード? そのうち検証したい
print("only support shorten use minus open")
side_tips = open_size_x
edge_x = int(open_size_x*1.5) #som magic number
#edge_x = 0
open_size_x = 0 # TODO move (some transform broken)
# 不自然にはみ出す、サイドのカット用だが、いまいち機能しないので使用停止
# TOP と HOLEが未対応なのでOFF
side_tips = 0 # remove cropped pixel
edge_x =0 # remove side pixel from final image
img_h, img_w = lip_utils.get_image_size(img)
# 唇領域の抽出と処理 (マージンが追加される。透明化処理が怪しい)
gaus = 4
box = lip_utils.get_points_box(landmarks_list, lip_utils.POINTS_BOTTOM_LIP, crop_image_margin)
align_points = lip_utils.get_bottom_lip_align_points(landmarks_list)
alpha_image, rec = get_alpha_image(img, landmarks_list, lip_utils.POINTS_BOTTOM_LIP, crop_image_margin, crop_image_margin, gaus)
# 最後に返す画像の元を作成
h, w = lip_utils.get_image_size(alpha_image)
if lip_utils.DEBUG:
cv2.imwrite("debug/bottom_lip_alpha.png",alpha_image)
print(f"bottom-lip cropped w = {w} h = {h}")
bottom_lip_final_image=lip_utils.create_rgba(w,h+open_size_y+1)# some how transform image expand TODO まだ必要か確認
bottom_lip_final_image_h,bottom_lip_final_image_w = lip_utils.get_image_size(bottom_lip_final_image)
print(f"bottom_lip_final_image:w = {bottom_lip_final_image_w} h = {bottom_lip_final_image_h}")
#local_align_points = lip_utils.offset_points(align_points,box[0])
#print(align_points)
# 唇の位置、いまだ検討中 https://github.com/akjava/lip_recognition_tools/issues/2
mid_left = int(w/5*2)
mid_left = int(w/3)
mid_right = bottom_lip_final_image_w - mid_left
print(f"image width = {bottom_lip_final_image_w} mid_left = {mid_left} mid_right ={mid_right}")
mid_center = int((mid_right+mid_left)/2) # 過去に真ん中下げに使っていたが必要ないと思っている。
mid_move_y_divided = 5 # 0 means no move
# 真ん中左の唇の変形 中心さげのに、無駄に2分割している。 https://github.com/akjava/lip_recognition_tools/issues/3
mid_image_left = lip_utils.crop_image(alpha_image,mid_left,0,mid_center,h)
mid_image_left_h,mid_image_left_w = lip_utils.get_image_size(mid_image_left)
max_w = mid_image_left_w
max_h = mid_image_left_h
opend_mid_lip_left = lip_utils.create_moved_image(mid_image_left,
[(0,0),(max_w,0),
(0,max_h),(max_w,max_h)],
[(-0,-0),(max_w,int(max_h*mid_lip_move_ratio)),#int(max_h/2)
(0,max_h),(max_w,max_h)]
)
# 予定外にサイズが伸びると、エラーになるので避けたいが、もう少し検証が必要
#opend_mid_lip_left = cv2.resize(opend_mid_lip_left, (max_w, max_h), interpolation=cv2.INTER_AREA)
lip_utils.print_width_height(mid_image_left,"mid-left")
lip_utils.print_width_height(opend_mid_lip_left,"moved-mid-left")
# 真ん中右の唇の変形
mid_image_right = lip_utils.crop_image(alpha_image,mid_center,0,mid_right,h)
mid_image_right_h,mid_image_right_w = lip_utils.get_image_size(mid_image_right)
max_w = mid_image_right_w
max_h = mid_image_right_h
opend_mid_lip_right = lip_utils.create_moved_image(mid_image_right,
[(0,0),(max_w,0),
(0,max_h),(max_w,max_h)],
[(-0,int(max_h*mid_lip_move_ratio)),(max_w,0),#int(max_h/2)
(0,max_h),(max_w,max_h)]
)
#opend_mid_lip_right = cv2.resize(opend_mid_lip_right, (max_w, max_h), interpolation=cv2.INTER_AREA)
lip_utils.print_width_height(mid_image_right,"mid-right")
lip_utils.print_width_height(opend_mid_lip_right,"moved-mid-right")
#no remove side-tip area
left_image = lip_utils.crop_image(alpha_image,side_tips,0,mid_left,h)
right_image = lip_utils.crop_image(alpha_image,mid_right,0,w-side_tips,h)
# 左の唇を下げる 左側は固定
left_lip_image_h,left_lip_image_w = lip_utils.get_image_size(left_image)
print(f"left-image:w = {left_lip_image_w} h = {left_lip_image_h}")
max_w = left_lip_image_w
max_h = left_lip_image_h
opend_lip_left = lip_utils.create_moved_image(left_image,
[(0,0),(max_w,0),
(0,max_h),(max_w,max_h)],
[(0,-0),(max_w+open_size_x,open_size_y),
(0,max_h-0),(max_w+open_size_x,max_h+open_size_y)]
)
left_lip_image_h,left_lip_image_w = lip_utils.get_image_size(opend_lip_left)
max_w = left_lip_image_w
max_h = left_lip_image_h
new_h,new_w = lip_utils.get_image_size(opend_lip_left)
print(f"left-image moved:w = {new_w} h = {new_h}")
if lip_utils.DEBUG:
cv2.imwrite("open_botto_lip_left.png",opend_lip_left)
# 右の唇を下げる 右側は固定
right_lip_image_h,right_lip_image_w = lip_utils.get_image_size(right_image)
max_w = right_lip_image_w
max_h = right_lip_image_h
opend_lip_right = lip_utils.create_moved_image(right_image,
[(0,0),(max_w,0),
(0,max_h),(max_w,max_h)],
[(0,open_size_y),(max_w+open_size_x,-0),
(0,max_h+open_size_y),(0+max_w+open_size_x,max_h-0)]
)
new_h,new_w = lip_utils.get_image_size(opend_lip_right)
print(f"right-image moved :w = {new_w} h = {new_h}")
if lip_utils.DEBUG:
cv2.imwrite("open_botto_lip_right.png",opend_lip_right)
# 変形後の各画像を描く alpha含めた全コピーなので注意(元画像のAlphaは無視)
#is this ok?
#lip_utils.copy_image(bottom_lip_final_image,mid_image,mid_left-1,open_size_y)
#lip_utils.copy_image(bottom_lip_final_image,mid_image,mid_left,open_size_y)
## 中央部分
lip_utils.copy_image(bottom_lip_final_image,opend_mid_lip_left,mid_left,open_size_y)
lip_utils.copy_image(bottom_lip_final_image,opend_mid_lip_right,mid_center,open_size_y)
print(lip_utils.get_image_size(opend_lip_left))
print(lip_utils.get_image_size(bottom_lip_final_image))
## 左右の端 side_tips
lip_utils.copy_image(bottom_lip_final_image,opend_lip_left,open_size_x+side_tips,0)
lip_utils.copy_image(bottom_lip_final_image,opend_lip_right,mid_right,0)
#edge_x=22 #for40 #テスト中
# 両端の処理 https://github.com/akjava/lip_recognition_tools/issues/6
lip_utils.fade_in_x(bottom_lip_final_image,edge_x*2)
lip_utils.fade_out_x(bottom_lip_final_image,edge_x*2)
# 最終的な画像の作成と保存
if lip_utils.DEBUG:
cv2.imwrite("bottom_lip_opend.png", bottom_lip_final_image)
face_size_image = lip_utils.create_rgba(img_w, img_h)
lip_utils.copy_image(face_size_image, bottom_lip_final_image, box[0][0], box[0][1])
if lip_utils.DEBUG:
cv2.imwrite("bottom_lip_layer.png", face_size_image)
return face_size_image
if __name__ == "__main__":
# 画像ファイルのパス
img_path = "straight.jpg"
# パラメータ
crop_image_margin = 16
open_size_y = 10
open_size_x = -10
# 関数の呼び出し
process_lip_image(img_path, crop_image_margin, open_size_y, open_size_x)