From 7c6a7ce50935188660bfbe54fe9577c1e06273a4 Mon Sep 17 00:00:00 2001 From: henryruhs Date: Tue, 17 Sep 2024 19:51:33 +0200 Subject: [PATCH] Sticky preview only for landscape images and videos --- facefusion/typing.py | 1 + facefusion/uis/assets/overrides.css | 7 +++++++ facefusion/uis/components/preview.py | 10 ++++++---- facefusion/vision.py | 10 +++++++++- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/facefusion/typing.py b/facefusion/typing.py index a8edfc21..f8ee1b54 100755 --- a/facefusion/typing.py +++ b/facefusion/typing.py @@ -68,6 +68,7 @@ MelFilterBank = NDArray[Any] Fps = float Padding = Tuple[int, int, int, int] +Orientation = Literal['landscape', 'portrait'] Resolution = Tuple[int, int] ProcessState = Literal['checking', 'processing', 'stopping', 'pending'] diff --git a/facefusion/uis/assets/overrides.css b/facefusion/uis/assets/overrides.css index cee8d01c..639c9870 100644 --- a/facefusion/uis/assets/overrides.css +++ b/facefusion/uis/assets/overrides.css @@ -87,3 +87,10 @@ { object-fit: cover; } + +:root:root:root:root .image-preview.is-landscape +{ + position: sticky; + top: 0; + z-index: 100; +} diff --git a/facefusion/uis/components/preview.py b/facefusion/uis/components/preview.py index 1bd0a936..18edacac 100755 --- a/facefusion/uis/components/preview.py +++ b/facefusion/uis/components/preview.py @@ -17,7 +17,7 @@ from facefusion.processors.core import get_processors_modules from facefusion.typing import AudioFrame, Face, FaceSet, VisionFrame from facefusion.uis.core import get_ui_component, get_ui_components, register_ui_component from facefusion.uis.typing import ComponentOptions -from facefusion.vision import count_video_frame_total, get_video_frame, normalize_frame_color, read_static_image, read_static_images, resize_frame_resolution +from facefusion.vision import count_video_frame_total, detect_frame_orientation, get_video_frame, normalize_frame_color, read_static_image, read_static_images, resize_frame_resolution PREVIEW_IMAGE : Optional[gradio.Image] = None PREVIEW_FRAME_SLIDER : Optional[gradio.Slider] = None @@ -56,11 +56,13 @@ def render() -> None: target_vision_frame = read_static_image(state_manager.get_item('target_path')) preview_vision_frame = process_preview_frame(reference_faces, source_face, source_audio_frame, target_vision_frame) preview_image_options['value'] = normalize_frame_color(preview_vision_frame) + preview_image_options['elem_classes'] = [ 'image-preview', 'is-' + detect_frame_orientation(preview_vision_frame) ] if is_video(state_manager.get_item('target_path')): temp_vision_frame = get_video_frame(state_manager.get_item('target_path'), state_manager.get_item('reference_frame_number')) preview_vision_frame = process_preview_frame(reference_faces, source_face, source_audio_frame, temp_vision_frame) preview_image_options['value'] = normalize_frame_color(preview_vision_frame) + preview_image_options['elem_classes'] = [ 'image-preview', 'is-' + detect_frame_orientation(preview_vision_frame) ] preview_image_options['visible'] = True preview_frame_slider_options['value'] = state_manager.get_item('reference_frame_number') preview_frame_slider_options['maximum'] = count_video_frame_total(state_manager.get_item('target_path')) @@ -202,14 +204,14 @@ def update_preview_image(frame_number : int = 0) -> gradio.Image: target_vision_frame = read_static_image(state_manager.get_item('target_path')) preview_vision_frame = process_preview_frame(reference_faces, source_face, source_audio_frame, target_vision_frame) preview_vision_frame = normalize_frame_color(preview_vision_frame) - return gradio.Image(value = preview_vision_frame) + return gradio.Image(value = preview_vision_frame, elem_classes = [ 'image-preview', 'is-' + detect_frame_orientation(preview_vision_frame) ]) if is_video(state_manager.get_item('target_path')): temp_vision_frame = get_video_frame(state_manager.get_item('target_path'), frame_number) preview_vision_frame = process_preview_frame(reference_faces, source_face, source_audio_frame, temp_vision_frame) preview_vision_frame = normalize_frame_color(preview_vision_frame) - return gradio.Image(value = preview_vision_frame) - return gradio.Image(value = None) + return gradio.Image(value = preview_vision_frame, elem_classes = [ 'image-preview', 'is-' + detect_frame_orientation(preview_vision_frame) ]) + return gradio.Image(value = None, elem_classes = None) def update_preview_frame_slider() -> gradio.Slider: diff --git a/facefusion/vision.py b/facefusion/vision.py index c4026ceb..d5c925db 100644 --- a/facefusion/vision.py +++ b/facefusion/vision.py @@ -8,7 +8,7 @@ from cv2.typing import Size from facefusion.choices import image_template_sizes, video_template_sizes from facefusion.common_helper import is_windows from facefusion.filesystem import is_image, is_video, sanitize_path_for_windows -from facefusion.typing import Fps, Resolution, VisionFrame +from facefusion.typing import Fps, Orientation, Resolution, VisionFrame @lru_cache(maxsize = 128) @@ -178,6 +178,14 @@ def unpack_resolution(resolution : str) -> Resolution: return width, height +def detect_frame_orientation(vision_frame : VisionFrame) -> Orientation: + height, width = vision_frame.shape[:2] + + if width > height: + return 'landscape' + return 'portrait' + + def resize_frame_resolution(vision_frame : VisionFrame, max_resolution : Resolution) -> VisionFrame: height, width = vision_frame.shape[:2] max_width, max_height = max_resolution