From 4d926117057a7381c43d6a916ecc7a292ba8d70f Mon Sep 17 00:00:00 2001 From: harisreedhar Date: Thu, 19 Sep 2024 17:21:41 +0530 Subject: [PATCH] changes --- facefusion.ini | 3 + facefusion/processors/choices.py | 3 + facefusion/processors/modules/face_editor.py | 63 ++++++++++++++----- facefusion/processors/typing.py | 4 ++ .../uis/components/face_editor_options.py | 54 +++++++++++++++- facefusion/uis/components/preview.py | 3 + facefusion/uis/typing.py | 3 + facefusion/wording.py | 6 ++ 8 files changed, 121 insertions(+), 18 deletions(-) diff --git a/facefusion.ini b/facefusion.ini index d29ac9f9..a6b99ed3 100644 --- a/facefusion.ini +++ b/facefusion.ini @@ -67,6 +67,9 @@ face_editor_mouth_purse = face_editor_mouth_smile = face_editor_mouth_position_horizontal = face_editor_mouth_position_vertical = +face_editor_pose_pitch = +face_editor_pose_yaw = +face_editor_pose_roll = face_enhancer_model = face_enhancer_blend = face_swapper_model = diff --git a/facefusion/processors/choices.py b/facefusion/processors/choices.py index 1b516ced..45d4e2b9 100755 --- a/facefusion/processors/choices.py +++ b/facefusion/processors/choices.py @@ -38,6 +38,9 @@ face_editor_mouth_purse_range : Sequence[float] = create_float_range(-1.0, 1.0, face_editor_mouth_smile_range : Sequence[float] = create_float_range(-1.0, 1.0, 0.05) face_editor_mouth_position_horizontal_range : Sequence[float] = create_float_range(-1.0, 1.0, 0.05) face_editor_mouth_position_vertical_range : Sequence[float] = create_float_range(-1.0, 1.0, 0.05) +face_editor_pose_pitch_range : Sequence[float] = create_float_range(-1.0, 1.0, 0.05) +face_editor_pose_yaw_range : Sequence[float] = create_float_range(-1.0, 1.0, 0.05) +face_editor_pose_roll_range : Sequence[float] = create_float_range(-1.0, 1.0, 0.05) face_enhancer_blend_range : Sequence[int] = create_int_range(0, 100, 1) frame_colorizer_blend_range : Sequence[int] = create_int_range(0, 100, 1) frame_enhancer_blend_range : Sequence[int] = create_int_range(0, 100, 1) diff --git a/facefusion/processors/modules/face_editor.py b/facefusion/processors/modules/face_editor.py index f9c527b1..1eaa246c 100755 --- a/facefusion/processors/modules/face_editor.py +++ b/facefusion/processors/modules/face_editor.py @@ -13,13 +13,13 @@ from facefusion.common_helper import create_float_metavar from facefusion.download import conditional_download_hashes, conditional_download_sources from facefusion.face_analyser import get_many_faces, get_one_face from facefusion.face_helper import paste_back, scale_face_landmark_5, warp_face_by_face_landmark_5 -from facefusion.face_masker import create_occlusion_mask, create_static_box_mask +from facefusion.face_masker import create_static_box_mask from facefusion.face_selector import find_similar_faces, sort_and_filter_faces from facefusion.face_store import get_reference_faces from facefusion.filesystem import in_directory, is_image, is_video, resolve_relative_path, same_file_extension from facefusion.processors import choices as processors_choices from facefusion.processors.live_portrait import limit_expression -from facefusion.processors.typing import FaceEditorInputs, LivePortraitExpression, LivePortraitFeatureVolume, LivePortraitMotionPoints, LivePortraitPitch, LivePortraitRoll, LivePortraitScale, LivePortraitTranslation, LivePortraitYaw +from facefusion.processors.typing import FaceEditorInputs, LivePortraitExpression, LivePortraitFeatureVolume, LivePortraitMotionPoints, LivePortraitPitch, LivePortraitRoll, LivePortraitRotation, LivePortraitScale, LivePortraitTranslation, LivePortraitYaw from facefusion.program_helper import find_argument_group from facefusion.thread_helper import conditional_thread_semaphore, thread_semaphore from facefusion.typing import ApplyStateItem, Args, Face, FaceLandmark68, InferencePool, ModelOptions, ModelSet, ProcessMode, QueuePayload, UpdateProgress, VisionFrame @@ -51,6 +51,11 @@ MODEL_SET : ModelSet =\ 'url': 'https://github.com/facefusion/facefusion-assets/releases/download/models-3.0.0/live_portrait_lip_retargeter.hash', 'path': resolve_relative_path('../.assets/models/live_portrait_lip_retargeter.hash') }, + 'stitcher': + { + 'url': 'https://github.com/facefusion/facefusion-assets/releases/download/models-3.0.0/live_portrait_stitcher.hash', + 'path': resolve_relative_path('../.assets/models/live_portrait_stitcher.hash') + }, 'generator': { 'url': 'https://github.com/facefusion/facefusion-assets/releases/download/models-3.0.0/live_portrait_generator.hash', @@ -79,6 +84,11 @@ MODEL_SET : ModelSet =\ 'url': 'https://github.com/facefusion/facefusion-assets/releases/download/models-3.0.0/live_portrait_lip_retargeter.onnx', 'path': resolve_relative_path('../.assets/models/live_portrait_lip_retargeter.onnx') }, + 'stitcher': + { + 'url': 'https://github.com/facefusion/facefusion-assets/releases/download/models-3.0.0/live_portrait_stitcher.onnx', + 'path': resolve_relative_path('../.assets/models/live_portrait_stitcher.onnx') + }, 'generator': { 'url': 'https://github.com/facefusion/facefusion-assets/releases/download/models-3.0.0/live_portrait_generator.onnx', @@ -122,7 +132,10 @@ def register_args(program : ArgumentParser) -> None: group_processors.add_argument('--face-editor-mouth-smile', help = wording.get('help.face_editor_mouth_smile'), type = float, default = config.get_float_value('processors.face_editor_mouth_smile', '0'), choices = processors_choices.face_editor_mouth_smile_range, metavar = create_float_metavar(processors_choices.face_editor_mouth_smile_range)) group_processors.add_argument('--face-editor-mouth-position-horizontal', help = wording.get('help.face_editor_mouth_position_horizontal'), type = float, default = config.get_float_value('processors.face_editor_mouth_position_horizontal', '0'), choices = processors_choices.face_editor_mouth_position_horizontal_range, metavar = create_float_metavar(processors_choices.face_editor_mouth_position_horizontal_range)) group_processors.add_argument('--face-editor-mouth-position-vertical', help = wording.get('help.face_editor_mouth_position_vertical'), type = float, default = config.get_float_value('processors.face_editor_mouth_position_vertical', '0'), choices = processors_choices.face_editor_mouth_position_vertical_range, metavar = create_float_metavar(processors_choices.face_editor_mouth_position_vertical_range)) - facefusion.jobs.job_store.register_step_keys([ 'face_editor_model', 'face_editor_eyebrow_direction', 'face_editor_eye_gaze_horizontal', 'face_editor_eye_gaze_vertical', 'face_editor_eye_open_ratio', 'face_editor_lip_open_ratio', 'face_editor_mouth_grim', 'face_editor_mouth_pout', 'face_editor_mouth_purse', 'face_editor_mouth_smile', 'face_editor_mouth_position_horizontal', 'face_editor_mouth_position_vertical' ]) + group_processors.add_argument('--face-editor-pose-pitch', help = wording.get('help.face_editor_pose_pitch'), type = float, default = config.get_float_value('processors.face_editor_pose_pitch', '0'), choices = processors_choices.face_editor_pose_pitch_range, metavar = create_float_metavar(processors_choices.face_editor_pose_pitch_range)) + group_processors.add_argument('--face-editor-pose-yaw', help=wording.get('help.face_editor_pose_yaw'), type = float, default = config.get_float_value('processors.face_editor_pose_yaw', '0'), choices = processors_choices.face_editor_pose_yaw_range, metavar = create_float_metavar(processors_choices.face_editor_pose_yaw_range)) + group_processors.add_argument('--face-editor-pose-roll', help=wording.get('help.face_editor_pose_roll'), type = float, default = config.get_float_value('processors.face_editor_pose_roll', '0'), choices = processors_choices.face_editor_pose_roll_range, metavar = create_float_metavar(processors_choices.face_editor_pose_roll_range)) + facefusion.jobs.job_store.register_step_keys([ 'face_editor_model', 'face_editor_eyebrow_direction', 'face_editor_eye_gaze_horizontal', 'face_editor_eye_gaze_vertical', 'face_editor_eye_open_ratio', 'face_editor_lip_open_ratio', 'face_editor_mouth_grim', 'face_editor_mouth_pout', 'face_editor_mouth_purse', 'face_editor_mouth_smile', 'face_editor_mouth_position_horizontal', 'face_editor_mouth_position_vertical', 'face_editor_pose_pitch', 'face_editor_pose_yaw', 'face_editor_pose_roll' ]) def apply_args(args : Args, apply_state_item : ApplyStateItem) -> None: @@ -138,6 +151,9 @@ def apply_args(args : Args, apply_state_item : ApplyStateItem) -> None: apply_state_item('face_editor_mouth_smile', args.get('face_editor_mouth_smile')) apply_state_item('face_editor_mouth_position_horizontal', args.get('face_editor_mouth_position_horizontal')) apply_state_item('face_editor_mouth_position_vertical', args.get('face_editor_mouth_position_vertical')) + apply_state_item('face_editor_pose_pitch', args.get('face_editor_pose_pitch')) + apply_state_item('face_editor_pose_yaw', args.get('face_editor_pose_yaw')) + apply_state_item('face_editor_pose_roll', args.get('face_editor_pose_roll')) def pre_check() -> bool: @@ -177,23 +193,13 @@ def post_process() -> None: def edit_face(target_face : Face, temp_vision_frame : VisionFrame) -> VisionFrame: model_template = get_model_options().get('template') model_size = get_model_options().get('size') - face_landmark_5 = scale_face_landmark_5(target_face.landmark_set.get('5/68'), 1.2) + face_landmark_5 = scale_face_landmark_5(target_face.landmark_set.get('5/68'), 1.5) crop_vision_frame, affine_matrix = warp_face_by_face_landmark_5(temp_vision_frame, face_landmark_5, model_template, model_size) box_mask = create_static_box_mask(crop_vision_frame.shape[:2][::-1], state_manager.get_item('face_mask_blur'), (0, 0, 0, 0)) - crop_masks =\ - [ - box_mask - ] - - if 'occlusion' in state_manager.get_item('face_mask_types'): - occlusion_mask = create_occlusion_mask(crop_vision_frame) - crop_masks.append(occlusion_mask) - crop_vision_frame = prepare_crop_frame(crop_vision_frame) crop_vision_frame = apply_edit(crop_vision_frame, target_face.landmark_set.get('68')) crop_vision_frame = normalize_crop_frame(crop_vision_frame) - crop_mask = numpy.minimum.reduce(crop_masks).clip(0, 1) - temp_vision_frame = paste_back(temp_vision_frame, crop_vision_frame, crop_mask, affine_matrix) + temp_vision_frame = paste_back(temp_vision_frame, crop_vision_frame, box_mask, affine_matrix) return temp_vision_frame @@ -211,12 +217,14 @@ def apply_edit(crop_vision_frame : VisionFrame, face_landmark_68 : FaceLandmark6 expression = edit_mouth_smile(expression) expression = edit_eyebrow_direction(expression) expression = limit_expression(expression) + rotation = edit_head_pose_rotation(pitch, yaw, roll) motion_points_source = motion_points @ rotation motion_points_source += expression motion_points_source *= scale motion_points_source += translation motion_points_source += edit_eye_open(motion_points_target, face_landmark_68) motion_points_source += edit_lip_open(motion_points_target, face_landmark_68) + motion_points_source = forward_stitch_motion_points(motion_points_source, motion_points_target) crop_vision_frame = forward_generate_frame(feature_volume, motion_points_source, motion_points_target) return crop_vision_frame @@ -269,6 +277,19 @@ def forward_retarget_lip(lip_motion_points : LivePortraitMotionPoints) -> LivePo return lip_motion_points +def forward_stitch_motion_points(source_motion_points : LivePortraitMotionPoints, target_motion_points : LivePortraitMotionPoints) -> LivePortraitMotionPoints: + stitcher = get_inference_pool().get('stitcher') + + with thread_semaphore(): + motion_points = stitcher.run(None, + { + 'source': source_motion_points, + 'target': target_motion_points + })[0] + + return motion_points + + def forward_generate_frame(feature_volume : LivePortraitFeatureVolume, source_motion_points : LivePortraitMotionPoints, target_motion_points : LivePortraitMotionPoints) -> VisionFrame: generator = get_inference_pool().get('generator') @@ -419,6 +440,18 @@ def edit_mouth_smile(expression : LivePortraitExpression) -> LivePortraitExpress return expression +def edit_head_pose_rotation(pitch : LivePortraitPitch, yaw : LivePortraitYaw, roll : LivePortraitRoll) -> LivePortraitRotation: + face_editor_pose_pitch = state_manager.get_item('face_editor_pose_pitch') + face_editor_pose_yaw = state_manager.get_item('face_editor_pose_yaw') + face_editor_pose_roll = state_manager.get_item('face_editor_pose_roll') + pitch += float(numpy.interp(face_editor_pose_pitch, [ -1, 1 ], [ 30, -30 ])) + yaw += float(numpy.interp(face_editor_pose_yaw, [ -1, 1 ], [ 30, -30 ])) + roll += float(numpy.interp(face_editor_pose_roll, [ -1, 1 ], [ -30, 30 ])) + rotation = scipy.spatial.transform.Rotation.from_euler('xyz', [ pitch, yaw, roll ], degrees=True).as_matrix() + rotation = rotation.T.astype(numpy.float32) + return rotation + + def calc_distance_ratio(face_landmark_68 : FaceLandmark68, top_index : int, bottom_index : int, left_index : int, right_index : int) -> float: vertical_direction = face_landmark_68[top_index] - face_landmark_68[bottom_index] horizontal_direction = face_landmark_68[left_index] - face_landmark_68[right_index] diff --git a/facefusion/processors/typing.py b/facefusion/processors/typing.py index 0abfa858..37732e72 100644 --- a/facefusion/processors/typing.py +++ b/facefusion/processors/typing.py @@ -82,6 +82,9 @@ ProcessorStateKey = Literal\ 'face_editor_mouth_smile', 'face_editor_mouth_position_horizontal', 'face_editor_mouth_position_vertical', + 'face_editor_pose_pitch', + 'face_editor_pose_yaw', + 'face_editor_pose_roll', 'face_enhancer_model', 'face_enhancer_blend', 'face_swapper_model', @@ -117,5 +120,6 @@ LivePortraitRoll = float LivePortraitExpression = NDArray[Any] LivePortraitFeatureVolume = NDArray[Any] LivePortraitMotionPoints = NDArray[Any] +LivePortraitRotation = NDArray[Any] LivePortraitScale = NDArray[Any] LivePortraitTranslation = NDArray[Any] diff --git a/facefusion/uis/components/face_editor_options.py b/facefusion/uis/components/face_editor_options.py index b47687c3..73948c35 100755 --- a/facefusion/uis/components/face_editor_options.py +++ b/facefusion/uis/components/face_editor_options.py @@ -21,6 +21,9 @@ FACE_EDITOR_MOUTH_PURSE_SLIDER : Optional[gradio.Slider] = None FACE_EDITOR_MOUTH_SMILE_SLIDER : Optional[gradio.Slider] = None FACE_EDITOR_MOUTH_POSITION_HORIZONTAL_SLIDER : Optional[gradio.Slider] = None FACE_EDITOR_MOUTH_POSITION_VERTICAL_SLIDER : Optional[gradio.Slider] = None +FACE_EDITOR_POSE_PITCH_SLIDER : Optional[gradio.Slider] = None +FACE_EDITOR_POSE_YAW_SLIDER : Optional[gradio.Slider] = None +FACE_EDITOR_POSE_ROLL_SLIDER : Optional[gradio.Slider] = None def render() -> None: @@ -36,6 +39,9 @@ def render() -> None: global FACE_EDITOR_MOUTH_SMILE_SLIDER global FACE_EDITOR_MOUTH_POSITION_HORIZONTAL_SLIDER global FACE_EDITOR_MOUTH_POSITION_VERTICAL_SLIDER + global FACE_EDITOR_POSE_PITCH_SLIDER + global FACE_EDITOR_POSE_YAW_SLIDER + global FACE_EDITOR_POSE_ROLL_SLIDER FACE_EDITOR_MODEL_DROPDOWN = gradio.Dropdown( label = wording.get('uis.face_editor_model_dropdown'), @@ -131,6 +137,30 @@ def render() -> None: maximum = processors_choices.face_editor_mouth_position_vertical_range[-1], visible = 'face_editor' in state_manager.get_item('processors'), ) + FACE_EDITOR_POSE_PITCH_SLIDER = gradio.Slider( + label = wording.get('uis.face_editor_pose_pitch_slider'), + value = state_manager.get_item('face_editor_pose_pitch'), + step = calc_float_step(processors_choices.face_editor_pose_pitch_range), + minimum = processors_choices.face_editor_pose_pitch_range[0], + maximum = processors_choices.face_editor_pose_pitch_range[-1], + visible = 'face_editor' in state_manager.get_item('processors'), + ) + FACE_EDITOR_POSE_YAW_SLIDER = gradio.Slider( + label = wording.get('uis.face_editor_pose_yaw_slider'), + value = state_manager.get_item('face_editor_pose_yaw'), + step = calc_float_step(processors_choices.face_editor_pose_yaw_range), + minimum = processors_choices.face_editor_pose_yaw_range[0], + maximum = processors_choices.face_editor_pose_yaw_range[-1], + visible = 'face_editor' in state_manager.get_item('processors'), + ) + FACE_EDITOR_POSE_ROLL_SLIDER = gradio.Slider( + label = wording.get('uis.face_editor_pose_roll_slider'), + value = state_manager.get_item('face_editor_pose_roll'), + step = calc_float_step(processors_choices.face_editor_pose_roll_range), + minimum = processors_choices.face_editor_pose_roll_range[0], + maximum = processors_choices.face_editor_pose_roll_range[-1], + visible = 'face_editor' in state_manager.get_item('processors'), + ) register_ui_component('face_editor_model_dropdown', FACE_EDITOR_MODEL_DROPDOWN) register_ui_component('face_editor_eyebrow_direction_slider', FACE_EDITOR_EYEBROW_DIRECTION_SLIDER) register_ui_component('face_editor_eye_gaze_horizontal_slider', FACE_EDITOR_EYE_GAZE_HORIZONTAL_SLIDER) @@ -143,6 +173,9 @@ def render() -> None: register_ui_component('face_editor_mouth_smile_slider', FACE_EDITOR_MOUTH_SMILE_SLIDER) register_ui_component('face_editor_mouth_position_horizontal_slider', FACE_EDITOR_MOUTH_POSITION_HORIZONTAL_SLIDER) register_ui_component('face_editor_mouth_position_vertical_slider', FACE_EDITOR_MOUTH_POSITION_VERTICAL_SLIDER) + register_ui_component('face_editor_pose_pitch_slider', FACE_EDITOR_POSE_PITCH_SLIDER) + register_ui_component('face_editor_pose_yaw_slider', FACE_EDITOR_POSE_YAW_SLIDER) + register_ui_component('face_editor_pose_roll_slider', FACE_EDITOR_POSE_ROLL_SLIDER) def listen() -> None: @@ -158,15 +191,18 @@ def listen() -> None: FACE_EDITOR_MOUTH_SMILE_SLIDER.release(update_face_editor_mouth_smile, inputs = FACE_EDITOR_MOUTH_SMILE_SLIDER) FACE_EDITOR_MOUTH_POSITION_HORIZONTAL_SLIDER.release(update_face_editor_mouth_position_horizontal, inputs = FACE_EDITOR_MOUTH_POSITION_HORIZONTAL_SLIDER) FACE_EDITOR_MOUTH_POSITION_VERTICAL_SLIDER.release(update_face_editor_mouth_position_vertical, inputs = FACE_EDITOR_MOUTH_POSITION_VERTICAL_SLIDER) + FACE_EDITOR_POSE_PITCH_SLIDER.release(update_face_editor_pose_pitch, inputs = FACE_EDITOR_POSE_PITCH_SLIDER) + FACE_EDITOR_POSE_YAW_SLIDER.release(update_face_editor_pose_yaw, inputs=FACE_EDITOR_POSE_YAW_SLIDER) + FACE_EDITOR_POSE_ROLL_SLIDER.release(update_face_editor_pose_roll, inputs=FACE_EDITOR_POSE_ROLL_SLIDER) processors_checkbox_group = get_ui_component('processors_checkbox_group') if processors_checkbox_group: - processors_checkbox_group.change(remote_update, inputs = processors_checkbox_group, outputs = [FACE_EDITOR_MODEL_DROPDOWN, FACE_EDITOR_EYEBROW_DIRECTION_SLIDER, FACE_EDITOR_EYE_GAZE_HORIZONTAL_SLIDER, FACE_EDITOR_EYE_GAZE_VERTICAL_SLIDER, FACE_EDITOR_EYE_OPEN_RATIO_SLIDER, FACE_EDITOR_LIP_OPEN_RATIO_SLIDER, FACE_EDITOR_MOUTH_GRIM_SLIDER, FACE_EDITOR_MOUTH_POUT_SLIDER, FACE_EDITOR_MOUTH_PURSE_SLIDER, FACE_EDITOR_MOUTH_SMILE_SLIDER, FACE_EDITOR_MOUTH_POSITION_HORIZONTAL_SLIDER, FACE_EDITOR_MOUTH_POSITION_VERTICAL_SLIDER]) + processors_checkbox_group.change(remote_update, inputs = processors_checkbox_group, outputs = [FACE_EDITOR_MODEL_DROPDOWN, FACE_EDITOR_EYEBROW_DIRECTION_SLIDER, FACE_EDITOR_EYE_GAZE_HORIZONTAL_SLIDER, FACE_EDITOR_EYE_GAZE_VERTICAL_SLIDER, FACE_EDITOR_EYE_OPEN_RATIO_SLIDER, FACE_EDITOR_LIP_OPEN_RATIO_SLIDER, FACE_EDITOR_MOUTH_GRIM_SLIDER, FACE_EDITOR_MOUTH_POUT_SLIDER, FACE_EDITOR_MOUTH_PURSE_SLIDER, FACE_EDITOR_MOUTH_SMILE_SLIDER, FACE_EDITOR_MOUTH_POSITION_HORIZONTAL_SLIDER, FACE_EDITOR_MOUTH_POSITION_VERTICAL_SLIDER, FACE_EDITOR_POSE_PITCH_SLIDER, FACE_EDITOR_POSE_YAW_SLIDER, FACE_EDITOR_POSE_ROLL_SLIDER]) -def remote_update(processors : List[str]) -> Tuple[gradio.Dropdown, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider]: +def remote_update(processors : List[str]) -> Tuple[gradio.Dropdown, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider, gradio.Slider]: has_face_editor = 'face_editor' in processors - return gradio.Dropdown(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor) + return gradio.Dropdown(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor), gradio.Slider(visible = has_face_editor) def update_face_editor_model(face_editor_model : FaceEditorModel) -> gradio.Dropdown: @@ -221,3 +257,15 @@ def update_face_editor_mouth_position_horizontal(face_editor_mouth_position_hori def update_face_editor_mouth_position_vertical(face_editor_mouth_position_vertical : float) -> None: state_manager.set_item('face_editor_mouth_position_vertical', face_editor_mouth_position_vertical) + + +def update_face_editor_pose_pitch(face_editor_pose_pitch : float) -> None: + state_manager.set_item('face_editor_pose_pitch', face_editor_pose_pitch) + + +def update_face_editor_pose_yaw(face_editor_pose_yaw : float) -> None: + state_manager.set_item('face_editor_pose_yaw', face_editor_pose_yaw) + + +def update_face_editor_pose_roll(face_editor_pose_roll : float) -> None: + state_manager.set_item('face_editor_pose_roll', face_editor_pose_roll) diff --git a/facefusion/uis/components/preview.py b/facefusion/uis/components/preview.py index 18edacac..3c0c3bc4 100755 --- a/facefusion/uis/components/preview.py +++ b/facefusion/uis/components/preview.py @@ -122,6 +122,9 @@ def listen() -> None: 'face_editor_mouth_smile_slider', 'face_editor_mouth_position_horizontal_slider', 'face_editor_mouth_position_vertical_slider', + 'face_editor_pose_pitch_slider', + 'face_editor_pose_yaw_slider', + 'face_editor_pose_roll_slider', 'face_enhancer_blend_slider', 'frame_colorizer_blend_slider', 'frame_enhancer_blend_slider', diff --git a/facefusion/uis/typing.py b/facefusion/uis/typing.py index 71938197..37f80d0a 100644 --- a/facefusion/uis/typing.py +++ b/facefusion/uis/typing.py @@ -28,6 +28,9 @@ ComponentName = Literal\ 'face_editor_mouth_smile_slider', 'face_editor_mouth_position_horizontal_slider', 'face_editor_mouth_position_vertical_slider', + 'face_editor_pose_pitch_slider', + 'face_editor_pose_yaw_slider', + 'face_editor_pose_roll_slider', 'face_enhancer_blend_slider', 'face_enhancer_model_dropdown', 'face_landmarker_model_dropdown', diff --git a/facefusion/wording.py b/facefusion/wording.py index b1bdc08f..9192dc51 100755 --- a/facefusion/wording.py +++ b/facefusion/wording.py @@ -152,6 +152,9 @@ WORDING : Dict[str, Any] =\ 'face_editor_mouth_smile': 'specify the mouth smile amount', 'face_editor_mouth_position_horizontal': 'specify the mouth position horizontal amount', 'face_editor_mouth_position_vertical': 'specify the mouth position vertical amount', + 'face_editor_pose_pitch': 'specify the pose pitch amount', + 'face_editor_pose_yaw': 'specify the pose yaw amount', + 'face_editor_pose_roll': 'specify the pose roll amount', 'face_enhancer_model': 'choose the model responsible for enhancing the face', 'face_enhancer_blend': 'blend the enhanced into the previous face', 'face_swapper_model': 'choose the model responsible for swapping the face', @@ -232,6 +235,9 @@ WORDING : Dict[str, Any] =\ 'face_editor_mouth_smile_slider': 'FACE EDITOR MOUTH SMILE', 'face_editor_mouth_position_horizontal_slider': 'FACE EDITOR MOUTH POSITION HORIZONTAL', 'face_editor_mouth_position_vertical_slider': 'FACE EDITOR MOUTH POSITION VERTICAL', + 'face_editor_pose_pitch_slider': 'FACE EDITOR POSE PITCH', + 'face_editor_pose_yaw_slider': 'FACE EDITOR POSE YAW', + 'face_editor_pose_roll_slider': 'FACE EDITOR POSE ROLL', 'face_enhancer_blend_slider': 'FACE ENHANCER BLEND', 'face_enhancer_model_dropdown': 'FACE ENHANCER MODEL', 'face_landmarker_model_dropdown': 'FACE LANDMARKER MODEL',