* renaming and restructuring (#282)

* Renaming and restructuring

* Renaming and restructuring

* Renaming and restructuring

* Fix gender detection

* Implement distance to face debugger

* Implement distance to face debugger part2

* Implement distance to face debugger part3

* Mark as next

* Fix reference when face_debugger comes first

* Use official onnxruntime nightly

* CUDA on steroids

* CUDA on steroids

* Add some testing

* Set inswapper_128_fp16 as default

* Feat/block until post check (#292)

* Block until download is done

* Introduce post_check()

* Fix webcam

* Update dependencies

* Add --force-reinstall to installer

* Introduce config ini (#298)

* Introduce config ini

* Fix output video encoder

* Revert help listings back to commas, Move SSL hack to download.py

* Introduce output-video-preset which defaults to veryfast

* Mapping for nvenc encoders

* Rework on events and non-blocking UI

* Add fast bmp to temp_frame_formats

* Add fast bmp to temp_frame_formats

* Show total processing time on success

* Show total processing time on success

* Show total processing time on success

* Move are_images, is_image and is_video back to filesystem

* Fix some spacings

* Pissing everyone of by renaming stuff

* Fix seconds output

* feat/video output fps (#312)

* added output fps slider, removed 'keep fps' option (#311)

* added output fps slider, removed 'keep fps' option

* now uses passed fps instead of global fps for ffmpeg

* fps values are now floats instead of ints

* fix previous commit

* removed default value from fps slider

this is so we can implement a dynamic default value later

* Fix seconds output

* Some cleanup

---------

Co-authored-by: Ran Shaashua <47498956+ranshaa05@users.noreply.github.com>

* Allow 0.01 steps for fps

* Make fps unregulated

* Make fps unregulated

* Remove distance from face debugger again (does not work)

* Fix gender age

* Fix gender age

* Hotfix benchmark suite

* Warp face normalize (#313)

* use normalized kp templates

* Update face_helper.py

* My 50 cents to warp_face()

---------

Co-authored-by: Harisreedhar <46858047+harisreedhar@users.noreply.github.com>

* face-swapper-weight (#315)

* Move prepare_crop_frame and normalize_crop_frame out of apply_swap

* Fix UI bug with different range

* feat/output video resolution (#316)

* Introduce detect_video_resolution, Rename detect_fps to detect_video_fps

* Add calc_video_resolution_range

* Make output resolution work, does not auto-select yet

* Make output resolution work, does not auto-select yet

* Try to keep the origin resolution

* Split code into more fragments

* Add pack/unpack resolution

* Move video_template_sizes to choices

* Improve create_video_resolutions

* Reword benchmark suite

* Optimal speed for benchmark

* Introduce different video memory strategies, rename max_memory to max… (#317)

* Introduce different video memory strategies, rename max_memory to max_system_memory

* Update readme

* Fix limit_system_memory call

* Apply video_memory_strategy to face debugger

* Limit face swapper weight to 3.0

* Remove face swapper weight due bad render outputs

* Show/dide logic for output video preset

* fix uint8 conversion

* Fix whitespace

* Finalize layout and update preview

* Fix multi renders on face debugger

* Restore less restrictive rendering of preview and stream

* Fix block mode for model downloads

* Add testing

* Cosmetic changes

* Enforce valid fps and resolution via CLI

* Empty config

* Cosmetics on args processing

* Memory workover (#319)

* Cosmetics on args processing

* Fix for MacOS

* Rename all max_ to _limit

* More fixes

* Update preview

* Fix whitespace

---------

Co-authored-by: Ran Shaashua <47498956+ranshaa05@users.noreply.github.com>
Co-authored-by: Harisreedhar <46858047+harisreedhar@users.noreply.github.com>
This commit is contained in:
Henry Ruhs
2024-01-19 19:57:48 +01:00
committed by GitHub
parent 3e93f99eeb
commit f6e56a3d8c
61 changed files with 1097 additions and 432 deletions

View File

@@ -6,11 +6,11 @@ import gradio
import facefusion.globals
from facefusion import wording
from facefusion.face_analyser import get_face_analyser
from facefusion.face_store import clear_static_faces
from facefusion.processors.frame.core import get_frame_processors_modules
from facefusion.vision import count_video_frame_total
from facefusion.core import limit_resources, conditional_process
from facefusion.vision import count_video_frame_total, detect_video_resolution, detect_video_fps, pack_resolution
from facefusion.core import conditional_process
from facefusion.memory import limit_system_memory
from facefusion.normalizer import normalize_output_path
from facefusion.filesystem import clear_temp
from facefusion.uis.core import get_ui_component
@@ -77,6 +77,8 @@ def listen() -> None:
def start(benchmark_runs : List[str], benchmark_cycles : int) -> Generator[List[Any], None, None]:
facefusion.globals.source_paths = [ '.assets/examples/source.jpg' ]
facefusion.globals.temp_frame_format = 'bmp'
facefusion.globals.output_video_preset = 'ultrafast'
target_paths = [ BENCHMARKS[benchmark_run] for benchmark_run in benchmark_runs if benchmark_run in BENCHMARKS ]
benchmark_results = []
if target_paths:
@@ -88,8 +90,8 @@ def start(benchmark_runs : List[str], benchmark_cycles : int) -> Generator[List[
def pre_process() -> None:
limit_resources()
get_face_analyser()
if facefusion.globals.system_memory_limit > 0:
limit_system_memory(facefusion.globals.system_memory_limit)
for frame_processor_module in get_frame_processors_modules(facefusion.globals.frame_processors):
frame_processor_module.get_frame_processor()
@@ -101,9 +103,12 @@ def post_process() -> None:
def benchmark(target_path : str, benchmark_cycles : int) -> List[Any]:
process_times = []
total_fps = 0.0
for i in range(benchmark_cycles):
for index in range(benchmark_cycles):
facefusion.globals.target_path = target_path
facefusion.globals.output_path = normalize_output_path(facefusion.globals.source_paths, facefusion.globals.target_path, tempfile.gettempdir())
target_video_resolution = detect_video_resolution(facefusion.globals.target_path)
facefusion.globals.output_video_resolution = pack_resolution(target_video_resolution)
facefusion.globals.output_video_fps = detect_video_fps(facefusion.globals.target_path)
video_frame_total = count_video_frame_total(facefusion.globals.target_path)
start_time = time.perf_counter()
conditional_process()

View File

@@ -20,7 +20,7 @@ def render() -> None:
)
BENCHMARK_CYCLES_SLIDER = gradio.Slider(
label = wording.get('benchmark_cycles_slider_label'),
value = 3,
value = 5,
step = 1,
minimum = 1,
maximum = 10

View File

@@ -12,8 +12,6 @@ def render() -> None:
global COMMON_OPTIONS_CHECKBOX_GROUP
value = []
if facefusion.globals.keep_fps:
value.append('keep-fps')
if facefusion.globals.keep_temp:
value.append('keep-temp')
if facefusion.globals.skip_audio:
@@ -32,7 +30,6 @@ def listen() -> None:
def update(common_options : List[str]) -> None:
facefusion.globals.keep_fps = 'keep-fps' in common_options
facefusion.globals.keep_temp = 'keep-temp' in common_options
facefusion.globals.skip_audio = 'skip-audio' in common_options
facefusion.globals.skip_download = 'skip-download' in common_options

View File

@@ -66,11 +66,11 @@ def render() -> None:
def listen() -> None:
FACE_ANALYSER_ORDER_DROPDOWN.select(update_face_analyser_order, inputs = FACE_ANALYSER_ORDER_DROPDOWN)
FACE_ANALYSER_AGE_DROPDOWN.select(update_face_analyser_age, inputs = FACE_ANALYSER_AGE_DROPDOWN)
FACE_ANALYSER_GENDER_DROPDOWN.select(update_face_analyser_gender, inputs = FACE_ANALYSER_GENDER_DROPDOWN)
FACE_ANALYSER_ORDER_DROPDOWN.change(update_face_analyser_order, inputs = FACE_ANALYSER_ORDER_DROPDOWN)
FACE_ANALYSER_AGE_DROPDOWN.change(update_face_analyser_age, inputs = FACE_ANALYSER_AGE_DROPDOWN)
FACE_ANALYSER_GENDER_DROPDOWN.change(update_face_analyser_gender, inputs = FACE_ANALYSER_GENDER_DROPDOWN)
FACE_DETECTOR_MODEL_DROPDOWN.change(update_face_detector_model, inputs = FACE_DETECTOR_MODEL_DROPDOWN)
FACE_DETECTOR_SIZE_DROPDOWN.select(update_face_detector_size, inputs = FACE_DETECTOR_SIZE_DROPDOWN)
FACE_DETECTOR_SIZE_DROPDOWN.change(update_face_detector_size, inputs = FACE_DETECTOR_SIZE_DROPDOWN)
FACE_DETECTOR_SCORE_SLIDER.change(update_face_detector_score, inputs = FACE_DETECTOR_SCORE_SLIDER)

View File

@@ -7,9 +7,9 @@ import facefusion.choices
from facefusion import wording
from facefusion.face_store import clear_static_faces, clear_reference_faces
from facefusion.vision import get_video_frame, read_static_image, normalize_frame_color
from facefusion.filesystem import is_image, is_video
from facefusion.face_analyser import get_many_faces
from facefusion.typing import Frame, FaceSelectorMode
from facefusion.filesystem import is_image, is_video
from facefusion.uis.core import get_ui_component, register_ui_component
from facefusion.uis.typing import ComponentName
@@ -57,7 +57,7 @@ def render() -> None:
def listen() -> None:
FACE_SELECTOR_MODE_DROPDOWN.select(update_face_selector_mode, inputs = FACE_SELECTOR_MODE_DROPDOWN, outputs = [ REFERENCE_FACE_POSITION_GALLERY, REFERENCE_FACE_DISTANCE_SLIDER ])
FACE_SELECTOR_MODE_DROPDOWN.change(update_face_selector_mode, inputs = FACE_SELECTOR_MODE_DROPDOWN, outputs = [ REFERENCE_FACE_POSITION_GALLERY, REFERENCE_FACE_DISTANCE_SLIDER ])
REFERENCE_FACE_POSITION_GALLERY.select(clear_and_update_reference_face_position)
REFERENCE_FACE_DISTANCE_SLIDER.change(update_reference_face_distance, inputs = REFERENCE_FACE_DISTANCE_SLIDER)
multi_component_names : List[ComponentName] =\

View File

@@ -4,7 +4,7 @@ import gradio
import facefusion.globals
from facefusion import wording
from facefusion.processors.frame.core import load_frame_processor_module, clear_frame_processors_modules
from facefusion.filesystem import list_module_names
from facefusion.filesystem import list_directory
from facefusion.uis.core import register_ui_component
FRAME_PROCESSORS_CHECKBOX_GROUP : Optional[gradio.CheckboxGroup] = None
@@ -36,5 +36,5 @@ def update_frame_processors(frame_processors : List[str]) -> gradio.CheckboxGrou
def sort_frame_processors(frame_processors : List[str]) -> list[str]:
available_frame_processors = list_module_names('facefusion/processors/frame/modules')
available_frame_processors = list_directory('facefusion/processors/frame/modules')
return sorted(available_frame_processors, key = lambda frame_processor : frame_processors.index(frame_processor) if frame_processor in frame_processors else len(frame_processors))

View File

@@ -56,7 +56,7 @@ def render() -> None:
step = frame_processors_choices.frame_enhancer_blend_range[1] - frame_processors_choices.frame_enhancer_blend_range[0],
minimum = frame_processors_choices.frame_enhancer_blend_range[0],
maximum = frame_processors_choices.frame_enhancer_blend_range[-1],
visible = 'face_enhancer' in facefusion.globals.frame_processors
visible = 'frame_enhancer' in facefusion.globals.frame_processors
)
FACE_DEBUGGER_ITEMS_CHECKBOX_GROUP = gradio.CheckboxGroup(
label = wording.get('face_debugger_items_checkbox_group_label'),

View File

@@ -1,27 +0,0 @@
from typing import Optional
import gradio
import facefusion.globals
import facefusion.choices
from facefusion import wording
MAX_MEMORY_SLIDER : Optional[gradio.Slider] = None
def render() -> None:
global MAX_MEMORY_SLIDER
MAX_MEMORY_SLIDER = gradio.Slider(
label = wording.get('max_memory_slider_label'),
step = facefusion.choices.max_memory_range[1] - facefusion.choices.max_memory_range[0],
minimum = facefusion.choices.max_memory_range[0],
maximum = facefusion.choices.max_memory_range[-1]
)
def listen() -> None:
MAX_MEMORY_SLIDER.change(update_max_memory, inputs = MAX_MEMORY_SLIDER)
def update_max_memory(max_memory : int) -> None:
facefusion.globals.max_memory = max_memory if max_memory > 0 else None

View File

@@ -0,0 +1,41 @@
from typing import Optional
import gradio
import facefusion.globals
import facefusion.choices
from facefusion.typing import VideoMemoryStrategy
from facefusion import wording
VIDEO_MEMORY_STRATEGY : Optional[gradio.Dropdown] = None
SYSTEM_MEMORY_LIMIT_SLIDER : Optional[gradio.Slider] = None
def render() -> None:
global VIDEO_MEMORY_STRATEGY
global SYSTEM_MEMORY_LIMIT_SLIDER
VIDEO_MEMORY_STRATEGY = gradio.Dropdown(
label = wording.get('video_memory_strategy_dropdown_label'),
choices = facefusion.choices.video_memory_strategies,
value = facefusion.globals.video_memory_strategy
)
SYSTEM_MEMORY_LIMIT_SLIDER = gradio.Slider(
label = wording.get('system_memory_limit_slider_label'),
step =facefusion.choices.system_memory_limit_range[1] - facefusion.choices.system_memory_limit_range[0],
minimum = facefusion.choices.system_memory_limit_range[0],
maximum = facefusion.choices.system_memory_limit_range[-1],
value = facefusion.globals.system_memory_limit
)
def listen() -> None:
VIDEO_MEMORY_STRATEGY.change(update_video_memory_strategy, inputs = VIDEO_MEMORY_STRATEGY)
SYSTEM_MEMORY_LIMIT_SLIDER.change(update_system_memory_limit, inputs = SYSTEM_MEMORY_LIMIT_SLIDER)
def update_video_memory_strategy(video_memory_strategy : VideoMemoryStrategy) -> None:
facefusion.globals.video_memory_strategy = video_memory_strategy
def update_system_memory_limit(system_memory_limit : int) -> None:
facefusion.globals.system_memory_limit = system_memory_limit

View File

@@ -3,10 +3,11 @@ import gradio
import facefusion.globals
from facefusion import wording
from facefusion.core import limit_resources, conditional_process
from facefusion.core import conditional_process
from facefusion.memory import limit_system_memory
from facefusion.uis.core import get_ui_component
from facefusion.normalizer import normalize_output_path
from facefusion.filesystem import is_image, is_video, clear_temp
from facefusion.filesystem import clear_temp, is_image, is_video
OUTPUT_IMAGE : Optional[gradio.Image] = None
OUTPUT_VIDEO : Optional[gradio.Video] = None
@@ -47,7 +48,8 @@ def listen() -> None:
def start(output_path : str) -> Tuple[gradio.Image, gradio.Video]:
facefusion.globals.output_path = normalize_output_path(facefusion.globals.source_paths, facefusion.globals.target_path, output_path)
limit_resources()
if facefusion.globals.system_memory_limit > 0:
limit_system_memory(facefusion.globals.system_memory_limit)
conditional_process()
if is_image(facefusion.globals.output_path):
return gradio.Image(value = facefusion.globals.output_path, visible = True), gradio.Video(value = None, visible = False)

View File

@@ -5,22 +5,29 @@ import gradio
import facefusion.globals
import facefusion.choices
from facefusion import wording
from facefusion.typing import OutputVideoEncoder
from facefusion.typing import OutputVideoEncoder, OutputVideoPreset, Fps
from facefusion.filesystem import is_image, is_video
from facefusion.uis.typing import ComponentName
from facefusion.uis.core import get_ui_component, register_ui_component
from facefusion.vision import detect_video_fps, create_video_resolutions, detect_video_resolution, pack_resolution
OUTPUT_PATH_TEXTBOX : Optional[gradio.Textbox] = None
OUTPUT_IMAGE_QUALITY_SLIDER : Optional[gradio.Slider] = None
OUTPUT_VIDEO_ENCODER_DROPDOWN : Optional[gradio.Dropdown] = None
OUTPUT_VIDEO_PRESET_DROPDOWN : Optional[gradio.Dropdown] = None
OUTPUT_VIDEO_RESOLUTION_DROPDOWN : Optional[gradio.Dropdown] = None
OUTPUT_VIDEO_QUALITY_SLIDER : Optional[gradio.Slider] = None
OUTPUT_VIDEO_FPS_SLIDER : Optional[gradio.Slider] = None
def render() -> None:
global OUTPUT_PATH_TEXTBOX
global OUTPUT_IMAGE_QUALITY_SLIDER
global OUTPUT_VIDEO_ENCODER_DROPDOWN
global OUTPUT_VIDEO_PRESET_DROPDOWN
global OUTPUT_VIDEO_RESOLUTION_DROPDOWN
global OUTPUT_VIDEO_QUALITY_SLIDER
global OUTPUT_VIDEO_FPS_SLIDER
OUTPUT_PATH_TEXTBOX = gradio.Textbox(
label = wording.get('output_path_textbox_label'),
@@ -41,6 +48,12 @@ def render() -> None:
value = facefusion.globals.output_video_encoder,
visible = is_video(facefusion.globals.target_path)
)
OUTPUT_VIDEO_PRESET_DROPDOWN = gradio.Dropdown(
label = wording.get('output_video_preset_dropdown_label'),
choices = facefusion.choices.output_video_presets,
value = facefusion.globals.output_video_preset,
visible = is_video(facefusion.globals.target_path)
)
OUTPUT_VIDEO_QUALITY_SLIDER = gradio.Slider(
label = wording.get('output_video_quality_slider_label'),
value = facefusion.globals.output_video_quality,
@@ -49,14 +62,31 @@ def render() -> None:
maximum = facefusion.choices.output_video_quality_range[-1],
visible = is_video(facefusion.globals.target_path)
)
OUTPUT_VIDEO_RESOLUTION_DROPDOWN = gradio.Dropdown(
label = wording.get('output_video_resolution_dropdown_label'),
choices = create_video_resolutions(facefusion.globals.target_path),
value = facefusion.globals.output_video_resolution,
visible = is_video(facefusion.globals.target_path)
)
OUTPUT_VIDEO_FPS_SLIDER = gradio.Slider(
label = wording.get('output_video_fps_slider_label'),
value = facefusion.globals.output_video_fps,
step = 0.01,
minimum = 1,
maximum = 60,
visible = is_video(facefusion.globals.target_path)
)
register_ui_component('output_path_textbox', OUTPUT_PATH_TEXTBOX)
def listen() -> None:
OUTPUT_PATH_TEXTBOX.change(update_output_path, inputs = OUTPUT_PATH_TEXTBOX)
OUTPUT_IMAGE_QUALITY_SLIDER.change(update_output_image_quality, inputs = OUTPUT_IMAGE_QUALITY_SLIDER)
OUTPUT_VIDEO_ENCODER_DROPDOWN.select(update_output_video_encoder, inputs = OUTPUT_VIDEO_ENCODER_DROPDOWN)
OUTPUT_VIDEO_ENCODER_DROPDOWN.change(update_output_video_encoder, inputs = OUTPUT_VIDEO_ENCODER_DROPDOWN)
OUTPUT_VIDEO_PRESET_DROPDOWN.change(update_output_video_preset, inputs = OUTPUT_VIDEO_PRESET_DROPDOWN)
OUTPUT_VIDEO_QUALITY_SLIDER.change(update_output_video_quality, inputs = OUTPUT_VIDEO_QUALITY_SLIDER)
OUTPUT_VIDEO_RESOLUTION_DROPDOWN.change(update_output_video_resolution, inputs = OUTPUT_VIDEO_RESOLUTION_DROPDOWN)
OUTPUT_VIDEO_FPS_SLIDER.change(update_output_video_fps, inputs = OUTPUT_VIDEO_FPS_SLIDER)
multi_component_names : List[ComponentName] =\
[
'source_image',
@@ -67,15 +97,19 @@ def listen() -> None:
component = get_ui_component(component_name)
if component:
for method in [ 'upload', 'change', 'clear' ]:
getattr(component, method)(remote_update, outputs = [ OUTPUT_IMAGE_QUALITY_SLIDER, OUTPUT_VIDEO_ENCODER_DROPDOWN, OUTPUT_VIDEO_QUALITY_SLIDER ])
getattr(component, method)(remote_update, outputs = [ OUTPUT_IMAGE_QUALITY_SLIDER, OUTPUT_VIDEO_ENCODER_DROPDOWN, OUTPUT_VIDEO_PRESET_DROPDOWN, OUTPUT_VIDEO_QUALITY_SLIDER, OUTPUT_VIDEO_RESOLUTION_DROPDOWN, OUTPUT_VIDEO_FPS_SLIDER ])
def remote_update() -> Tuple[gradio.Slider, gradio.Dropdown, gradio.Slider]:
def remote_update() -> Tuple[gradio.Slider, gradio.Dropdown, gradio.Dropdown, gradio.Slider, gradio.Dropdown, gradio.Slider]:
if is_image(facefusion.globals.target_path):
return gradio.Slider(visible = True), gradio.Dropdown(visible = False), gradio.Slider(visible = False)
return gradio.Slider(visible = True), gradio.Dropdown(visible = False), gradio.Dropdown(visible = False), gradio.Slider(visible = False), gradio.Dropdown(visible = False, value = None, choices = None), gradio.Slider(visible = False, value = None)
if is_video(facefusion.globals.target_path):
return gradio.Slider(visible = False), gradio.Dropdown(visible = True), gradio.Slider(visible = True)
return gradio.Slider(visible = False), gradio.Dropdown(visible = False), gradio.Slider(visible = False)
target_video_resolution = detect_video_resolution(facefusion.globals.target_path)
output_video_resolution = pack_resolution(target_video_resolution)
output_video_resolutions = create_video_resolutions(facefusion.globals.target_path)
output_video_fps = detect_video_fps(facefusion.globals.target_path)
return gradio.Slider(visible = False), gradio.Dropdown(visible = True), gradio.Dropdown(visible = True), gradio.Slider(visible = True), gradio.Dropdown(visible = True, value = output_video_resolution, choices = output_video_resolutions), gradio.Slider(visible = True, value = output_video_fps)
return gradio.Slider(visible = False), gradio.Dropdown(visible = False), gradio.Dropdown(visible = False), gradio.Slider(visible = False), gradio.Dropdown(visible = False, value = None, choices = None), gradio.Slider(visible = False, value = None)
def update_output_path(output_path : str) -> None:
@@ -90,5 +124,17 @@ def update_output_video_encoder(output_video_encoder: OutputVideoEncoder) -> Non
facefusion.globals.output_video_encoder = output_video_encoder
def update_output_video_preset(output_video_preset : OutputVideoPreset) -> None:
facefusion.globals.output_video_preset = output_video_preset
def update_output_video_quality(output_video_quality : int) -> None:
facefusion.globals.output_video_quality = output_video_quality
def update_output_video_resolution(output_video_resolution : str) -> None:
facefusion.globals.output_video_resolution = output_video_resolution
def update_output_video_fps(output_video_fps : Fps) -> None:
facefusion.globals.output_video_fps = output_video_fps

View File

@@ -1,17 +1,18 @@
from typing import Any, Dict, List, Optional
from time import sleep
import cv2
import gradio
import facefusion.globals
from facefusion import wording
from facefusion import wording, logger
from facefusion.core import conditional_append_reference_faces
from facefusion.face_store import clear_static_faces, get_reference_faces, clear_reference_faces
from facefusion.typing import Frame, Face, FaceSet
from facefusion.vision import get_video_frame, count_video_frame_total, normalize_frame_color, resize_frame_dimension, read_static_image, read_static_images
from facefusion.vision import get_video_frame, count_video_frame_total, normalize_frame_color, resize_frame_resolution, read_static_image, read_static_images
from facefusion.filesystem import is_image, is_video
from facefusion.face_analyser import get_average_face, clear_face_analyser
from facefusion.content_analyser import analyse_frame
from facefusion.processors.frame.core import load_frame_processor_module
from facefusion.filesystem import is_image, is_video
from facefusion.uis.typing import ComponentName
from facefusion.uis.core import get_ui_component, register_ui_component
@@ -94,9 +95,7 @@ def listen() -> None:
change_one_component_names : List[ComponentName] =\
[
'face_debugger_items_checkbox_group',
'face_enhancer_model_dropdown',
'face_enhancer_blend_slider',
'frame_enhancer_model_dropdown',
'frame_enhancer_blend_slider',
'face_selector_mode_dropdown',
'reference_face_distance_slider',
@@ -115,7 +114,9 @@ def listen() -> None:
change_two_component_names : List[ComponentName] =\
[
'frame_processors_checkbox_group',
'face_enhancer_model_dropdown',
'face_swapper_model_dropdown',
'frame_enhancer_model_dropdown',
'face_detector_model_dropdown',
'face_detector_size_dropdown',
'face_detector_score_slider'
@@ -130,22 +131,29 @@ def clear_and_update_preview_image(frame_number : int = 0) -> gradio.Image:
clear_face_analyser()
clear_reference_faces()
clear_static_faces()
sleep(0.5)
return update_preview_image(frame_number)
def update_preview_image(frame_number : int = 0) -> gradio.Image:
for frame_processor in facefusion.globals.frame_processors:
frame_processor_module = load_frame_processor_module(frame_processor)
while not frame_processor_module.post_check():
logger.disable()
sleep(0.5)
logger.enable()
conditional_append_reference_faces()
source_frames = read_static_images(facefusion.globals.source_paths)
source_face = get_average_face(source_frames)
reference_face = get_reference_faces() if 'reference' in facefusion.globals.face_selector_mode else None
reference_faces = get_reference_faces() if 'reference' in facefusion.globals.face_selector_mode else None
if is_image(facefusion.globals.target_path):
target_frame = read_static_image(facefusion.globals.target_path)
preview_frame = process_preview_frame(source_face, reference_face, target_frame)
preview_frame = process_preview_frame(source_face, reference_faces, target_frame)
preview_frame = normalize_frame_color(preview_frame)
return gradio.Image(value = preview_frame)
if is_video(facefusion.globals.target_path):
temp_frame = get_video_frame(facefusion.globals.target_path, frame_number)
preview_frame = process_preview_frame(source_face, reference_face, temp_frame)
preview_frame = process_preview_frame(source_face, reference_faces, temp_frame)
preview_frame = normalize_frame_color(preview_frame)
return gradio.Image(value = preview_frame)
return gradio.Image(value = None)
@@ -159,12 +167,14 @@ def update_preview_frame_slider() -> gradio.Slider:
def process_preview_frame(source_face : Face, reference_faces : FaceSet, temp_frame : Frame) -> Frame:
temp_frame = resize_frame_dimension(temp_frame, 640, 640)
temp_frame = resize_frame_resolution(temp_frame, 640, 640)
if analyse_frame(temp_frame):
return cv2.GaussianBlur(temp_frame, (99, 99), 0)
for frame_processor in facefusion.globals.frame_processors:
frame_processor_module = load_frame_processor_module(frame_processor)
logger.disable()
if frame_processor_module.pre_process('preview'):
logger.enable()
temp_frame = frame_processor_module.process_frame(
source_face,
reference_faces,

View File

@@ -33,7 +33,7 @@ def render() -> None:
def listen() -> None:
TEMP_FRAME_FORMAT_DROPDOWN.select(update_temp_frame_format, inputs = TEMP_FRAME_FORMAT_DROPDOWN)
TEMP_FRAME_FORMAT_DROPDOWN.change(update_temp_frame_format, inputs = TEMP_FRAME_FORMAT_DROPDOWN)
TEMP_FRAME_QUALITY_SLIDER.change(update_temp_frame_quality, inputs = TEMP_FRAME_QUALITY_SLIDER)
target_video = get_ui_component('target_video')
if target_video:

View File

@@ -1,22 +1,23 @@
from typing import Optional, Generator, Deque
from concurrent.futures import ThreadPoolExecutor
from collections import deque
from typing import Optional, Generator, Deque, List
import os
import platform
import subprocess
import cv2
import gradio
from time import sleep
from concurrent.futures import ThreadPoolExecutor
from collections import deque
from tqdm import tqdm
import facefusion.globals
from facefusion import logger, wording
from facefusion.content_analyser import analyse_stream
from facefusion.typing import Frame, Face
from facefusion.typing import Frame, Face, Fps
from facefusion.face_analyser import get_average_face
from facefusion.processors.frame.core import get_frame_processors_modules
from facefusion.processors.frame.core import get_frame_processors_modules, load_frame_processor_module
from facefusion.ffmpeg import open_ffmpeg
from facefusion.vision import normalize_frame_color, read_static_images
from facefusion.uis.typing import StreamMode, WebcamMode
from facefusion.vision import normalize_frame_color, read_static_images, unpack_resolution
from facefusion.uis.typing import StreamMode, WebcamMode, ComponentName
from facefusion.uis.core import get_ui_component
WEBCAM_CAPTURE : Optional[cv2.VideoCapture] = None
@@ -73,28 +74,36 @@ def listen() -> None:
if webcam_mode_radio and webcam_resolution_dropdown and webcam_fps_slider:
start_event = WEBCAM_START_BUTTON.click(start, inputs = [ webcam_mode_radio, webcam_resolution_dropdown, webcam_fps_slider ], outputs = WEBCAM_IMAGE)
WEBCAM_STOP_BUTTON.click(stop, cancels = start_event)
source_image = get_ui_component('source_image')
if source_image:
for method in [ 'upload', 'change', 'clear' ]:
getattr(source_image, method)(stop, cancels = start_event)
change_two_component_names : List[ComponentName] =\
[
'frame_processors_checkbox_group',
'face_swapper_model_dropdown',
'face_enhancer_model_dropdown',
'frame_enhancer_model_dropdown',
'source_image'
]
for component_name in change_two_component_names:
component = get_ui_component(component_name)
if component:
component.change(update, cancels = start_event)
def start(webcam_mode : WebcamMode, resolution : str, fps : float) -> Generator[Frame, None, None]:
def start(webcam_mode : WebcamMode, webcam_resolution : str, webcam_fps : Fps) -> Generator[Frame, None, None]:
facefusion.globals.face_selector_mode = 'one'
facefusion.globals.face_analyser_order = 'large-small'
source_frames = read_static_images(facefusion.globals.source_paths)
source_face = get_average_face(source_frames)
stream = None
if webcam_mode in [ 'udp', 'v4l2' ]:
stream = open_stream(webcam_mode, resolution, fps) # type: ignore[arg-type]
webcam_width, webcam_height = map(int, resolution.split('x'))
stream = open_stream(webcam_mode, webcam_resolution, webcam_fps) # type: ignore[arg-type]
webcam_width, webcam_height = unpack_resolution(webcam_resolution)
webcam_capture = get_webcam_capture()
if webcam_capture and webcam_capture.isOpened():
webcam_capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG')) # type: ignore[attr-defined]
webcam_capture.set(cv2.CAP_PROP_FRAME_WIDTH, webcam_width)
webcam_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, webcam_height)
webcam_capture.set(cv2.CAP_PROP_FPS, fps)
for capture_frame in multi_process_capture(source_face, webcam_capture, fps):
webcam_capture.set(cv2.CAP_PROP_FPS, webcam_fps)
for capture_frame in multi_process_capture(source_face, webcam_capture, webcam_fps):
if webcam_mode == 'inline':
yield normalize_frame_color(capture_frame)
else:
@@ -105,14 +114,14 @@ def start(webcam_mode : WebcamMode, resolution : str, fps : float) -> Generator[
yield None
def multi_process_capture(source_face : Face, webcam_capture : cv2.VideoCapture, fps : float) -> Generator[Frame, None, None]:
def multi_process_capture(source_face : Face, webcam_capture : cv2.VideoCapture, webcam_fps : Fps) -> Generator[Frame, None, None]:
with tqdm(desc = wording.get('processing'), unit = 'frame', ascii = ' =', disable = facefusion.globals.log_level in [ 'warn', 'error' ]) as progress:
with ThreadPoolExecutor(max_workers = facefusion.globals.execution_thread_count) as executor:
futures = []
deque_capture_frames : Deque[Frame] = deque()
while webcam_capture and webcam_capture.isOpened():
_, capture_frame = webcam_capture.read()
if analyse_stream(capture_frame, fps):
if analyse_stream(capture_frame, webcam_fps):
return
future = executor.submit(process_stream_frame, source_face, capture_frame)
futures.append(future)
@@ -125,6 +134,15 @@ def multi_process_capture(source_face : Face, webcam_capture : cv2.VideoCapture,
yield deque_capture_frames.popleft()
def update() -> None:
for frame_processor in facefusion.globals.frame_processors:
frame_processor_module = load_frame_processor_module(frame_processor)
while not frame_processor_module.post_check():
logger.disable()
sleep(0.5)
logger.enable()
def stop() -> gradio.Image:
clear_webcam_capture()
return gradio.Image(value = None)
@@ -132,7 +150,9 @@ def stop() -> gradio.Image:
def process_stream_frame(source_face : Face, temp_frame : Frame) -> Frame:
for frame_processor_module in get_frame_processors_modules(facefusion.globals.frame_processors):
logger.disable()
if frame_processor_module.pre_process('stream'):
logger.enable()
temp_frame = frame_processor_module.process_frame(
source_face,
None,
@@ -141,8 +161,8 @@ def process_stream_frame(source_face : Face, temp_frame : Frame) -> Frame:
return temp_frame
def open_stream(stream_mode : StreamMode, resolution : str, fps : float) -> subprocess.Popen[bytes]:
commands = [ '-f', 'rawvideo', '-pix_fmt', 'bgr24', '-s', resolution, '-r', str(fps), '-i', '-' ]
def open_stream(stream_mode : StreamMode, stream_resolution : str, stream_fps : Fps) -> subprocess.Popen[bytes]:
commands = [ '-f', 'rawvideo', '-pix_fmt', 'bgr24', '-s', stream_resolution, '-r', str(stream_fps), '-i', '-']
if stream_mode == 'udp':
commands.extend([ '-b:v', '2000k', '-f', 'mpegts', 'udp://localhost:27000?pkt_size=1316' ])
if stream_mode == 'v4l2':